diff options
Diffstat (limited to 'Northstar.Client')
50 files changed, 11956 insertions, 1762 deletions
diff --git a/Northstar.Client/kb_act.lst b/Northstar.Client/kb_act.lst new file mode 100644 index 00000000..1a4f7129 --- /dev/null +++ b/Northstar.Client/kb_act.lst @@ -0,0 +1,13 @@ +"blank" "==========================" +"blank" "NORTHSTAR" +"blank" "==========================" +"toggleconsole" "Toggle Developer Console" +"vote 1" "Vote 1" +"vote 2" "Vote 2" +"vote 3" "Vote 3" +"vote 4" "Vote 4" +"vote 5" "Vote 5" +"vote 6" "Vote 6" +"vote 7" "Vote 7" +"vote 8" "Vote 8" +"vote 9" "Vote 9" diff --git a/Northstar.Client/keyvalues/resource/fontfiletable.txt b/Northstar.Client/keyvalues/resource/fontfiletable.txt new file mode 100644 index 00000000..f0b91c07 --- /dev/null +++ b/Northstar.Client/keyvalues/resource/fontfiletable.txt @@ -0,0 +1,10 @@ +FontFileTable +{ + "arial unicode ms" "resource/Lato-Regular.ttf" + + "lucida console" "resource/NorthstarMono.ttf" [$PC] + + "arial" "resource/Lato-Regular.ttf" + "arial bold" "resource/Lato-Regular.ttf" + "arial narrow" "resource/Lato-Regular.ttf" +} diff --git a/Northstar.Client/mod.json b/Northstar.Client/mod.json index 17b01543..44937a2b 100644 --- a/Northstar.Client/mod.json +++ b/Northstar.Client/mod.json @@ -1,10 +1,15 @@ { "Name": "Northstar.Client", "Description": "Various ui and client changes to fix bugs and add better support for mods", - "Version": "1.9.0", + "Version": "1.19.0", "LoadPriority": 0, + "InitScript": "cl_northstar_client_init.nut", "ConVars": [ { + "Name": "allow_mod_auto_download", + "DefaultValue": "0" + }, + { "Name": "filter_hide_empty", "DefaultValue": "0" }, @@ -31,15 +36,22 @@ { "Name": "filter_map_hide_locked", "DefaultValue": "0" + }, + { + "Name": "modlist_show_convars", + "DefaultValue": "0", + "Flags": "ARCHIVE_PLAYERPROFILE" + }, + { + "Name": "modlist_reverse", + "DefaultValue": "0", + "Flags": "ARCHIVE_PLAYERPROFILE" } ], "Scripts": [ { "Path": "_custom_codecallbacks_client.gnut", - "RunOn": "CLIENT", - "ClientCallback": { - "Before": "NSSetupChathooksClient" - } + "RunOn": "CLIENT" }, { "Path": "client/cl_chat.gnut", @@ -75,6 +87,10 @@ } }, { + "Path": "ui/menu_ns_moddownload.nut", + "RunOn": "UI" + }, + { "Path": "ui/menu_ns_serverbrowser.nut", "RunOn": "UI", "UICallback": { @@ -105,6 +121,28 @@ { "Path": "ui/controller_prompts.nut", "RunOn": "UI" + }, + { + "Path": "ui/ns_slider.nut", + "RunOn": "UI" + }, + { + "Path": "ui/menu_mod_settings.nut", + "RunOn": "UI", + "UICallback":{ + "Before": "AddModSettingsMenu" + } + }, + { + "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/materials/vgui/reset.vmt b/Northstar.Client/mod/materials/vgui/reset.vmt new file mode 100644 index 00000000..84034586 --- /dev/null +++ b/Northstar.Client/mod/materials/vgui/reset.vmt @@ -0,0 +1,12 @@ +"Basic" +{ + "$basetexture" "vgui/reset" + "$translucent" 1 + "$vertexcolor" 1 + "$vertexalpha" 1 + "$no_fullbright" 1 + "$ignorez" 1 + "$nolod" 1 + + "$SHADERSRGBREAD360" 1 +} diff --git a/Northstar.Client/mod/materials/vgui/reset.vtf b/Northstar.Client/mod/materials/vgui/reset.vtf Binary files differnew file mode 100644 index 00000000..5ffb86a9 --- /dev/null +++ b/Northstar.Client/mod/materials/vgui/reset.vtf diff --git a/Northstar.Client/mod/resource/Lato-Regular.ttf b/Northstar.Client/mod/resource/Lato-Regular.ttf Binary files differnew file mode 100644 index 00000000..adbfc467 --- /dev/null +++ b/Northstar.Client/mod/resource/Lato-Regular.ttf diff --git a/Northstar.Client/mod/resource/NorthstarMono.ttf b/Northstar.Client/mod/resource/NorthstarMono.ttf Binary files differnew file mode 100644 index 00000000..2814eee6 --- /dev/null +++ b/Northstar.Client/mod/resource/NorthstarMono.ttf diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt index 8c6cadcf..baceed22 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt @@ -227,6 +227,7 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "classic_rodeo" "Classic Rodeo" "oob_timer_enabled" "Out of Bounds Timer" "riff_instagib" "Instagib Mode" + "player_force_respawn" "Forced Respawn" "riff_player_bleedout" "Pilot Bleedout" "player_bleedout_forceHolster" "Holster weapons when downed" @@ -276,7 +277,7 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "PLAYERS_COLUMN" "Players" "MAP_COLUMN" "Map" "GAMEMODE_COLUMN" "Gamemode" - "LATENCY_COLUMN" "Latency" + "REGION_COLUMN" "Region" "SEARCHBAR_LABEL" "Search:" "MAP_FILTER" "Map" "GAMEMODE_FILTER" "Gamemode" @@ -301,6 +302,9 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "SHOW_ALL" "All" "SHOW_ONLY_ENABLED" "Only Enabled" "SHOW_ONLY_DISABLED" "Only Disabled" + "SHOW_ONLY_NOT_REQUIRED" "Only Optional Mods" + "SHOW_ONLY_REQUIRED" "Only Required Mods" + "MOD_REQUIRED_WARNING" " : This mod may get (un)loaded when joining a server" // Maps menu "HIDE_LOCKED" "Hide locked" @@ -316,8 +320,75 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "UNAUTHORIZED_PWD" "Wrong password" "STRYDER_RESPONSE" "Couldn't parse stryder response" "PLAYER_NOT_FOUND" "Couldn't find player account" - "INVALID_MASTERSERVER_TOKEN" "Invalid or expired masterserver token" + "INVALID_MASTERSERVER_TOKEN" "Invalid or expired masterserver token, try restarting EA App." "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" + "NORTHSTAR_BASE_SETTINGS" "Northstar Base Settings" + "ONLY_HOST_MATCH_SETTINGS" "Only Host can change Private Match settings" + "ONLY_HOST_CAN_START_MATCH" "Only Host can Start the Match" + "MATCH_COUNTDOWN_LENGTH" "Private Match Countdown Duration" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Log Unknown Client Commands" + "DISALLOWED_TACTICALS" "Prohibited Tacticals" + "TACTICAL_REPLACEMENT" "Replacement Tactical" + "DISALLOWED_WEAPONS" "Prohibited Weapons" + "REPLACEMENT_WEAPON" "Replacement Weapon" + "SHOULD_RETURN_TO_LOBBY" "Return To Lobby After Match End" + "ARE_YOU_SURE" "Are you sure?" + "WILL_RESET_ALL_SETTINGS" "This will reset ALL settings that belong to this category.\n\nThis is not revertable." + "WILL_RESET_SETTING" "This will reset the %s1 setting to it's default value.\n\nThis is not revertable." + "MOD_SETTINGS_SERVER" "Server" + "MOD_SETTINGS_RESET" "Reset" + "MOD_SETTINGS_RESET_ALL" "Reset All" + "NO_RESULTS" "No results." + "NO_MODS" "No settings available! Install more mods at ^5588FF00northstar.thunderstore.io^0." + + // Toggleable progression + "TOGGLE_PROGRESSION" "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." + + "PROGRESSION_TOGGLE_DISABLED_HEADER" "Enable Progression?" + "PROGRESSION_TOGGLE_DISABLED_BODY" "Titans, Weapons, Factions, Skins, etc. will need to be unlocked by levelling up, or bought with Merits.\n\nThis can be changed at any time in the multiplayer lobby.\n\n^CC000000Warning: if you have currently equipped any items that you do not have unlocked, they will be reset!" + + "PROGRESSION_ENABLED_HEADER" "Progression Enabled!" + "PROGRESSION_ENABLED_BODY" "^CCCC0000Progression has been enabled.^\n\nTitans, Weapons, Factions, Skins, etc. will need to be unlocked by levelling up, or bought with Merits.\n\nThis can be changed at any time in the multiplayer lobby." + + "PROGRESSION_DISABLED_HEADER" "Progression Disabled!" + "PROGRESSION_DISABLED_BODY" "^CCCC0000Progression has been disabled.^\n\nTitans, 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." + + "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000Progression can now be enabled!^\n\nNorthstar now supports vanilla progression, meaning you can choose to unlock Weapons, Skins, Titans, etc. through levelling up and completing challenges.\n\nYou can enable progression using the button at the bottom of the lobby screen.\n\nThis can be changed at any time." + + // Mod downloading + "MISSING_MOD" "Missing mod \"%s1\" v%s2" + "WRONG_MOD_VERSION" "Server has mod \"%s1\" v%s2 while you have v%s3" + "MOD_NOT_VERIFIED" "(mod is not verified, and couldn't be downloaded automatically)" + "MOD_DL_DISABLED" "(automatic mod downloading is disabled)" + "MANIFESTO_FETCHING_TITLE" "Setting up mod download" + "MANIFESTO_FETCHING_TEXT" "Retrieving the list of verified mods..." + "DOWNLOADING_MOD_TITLE" "Downloading mod" + "DOWNLOADING_MOD_TITLE_W_PROGRESS" "Downloading mod (%s1%)" + "DOWNLOADING_MOD_TEXT" "Downloading %s1 v%s2..." + "DOWNLOADING_MOD_TEXT_W_PROGRESS" "Downloading %s1 v%s2...\n(%s3/%s4 MB)" + "CHECKSUMING_TITLE" "Checksuming mod" + "CHECKSUMING_TEXT" "Verifying contents of %s1 v%s2..." + "EXTRACTING_MOD_TITLE" "Extracting mod (%s1%)" + "EXTRACTING_MOD_TEXT" "Extracting %s1 v%s2...\n(%s3/%s4 MB)" + "FAILED_DOWNLOADING" "Failed downloading mod" + "FAILED_READING_ARCHIVE" "An error occurred while reading mod archive." + "FAILED_WRITING_TO_DISK" "An error occurred while extracting mod files to the filesystem." + "MOD_FETCHING_FAILED" "Mod archive could not be downloaded from Thunderstore." + "MOD_CORRUPTED" "Downloaded archive checksum does not match verified signature." + "NO_DISK_SPACE_AVAILABLE" "There is not enough space on your disk." + "MOD_FETCHING_FAILED_GENERAL" "Mod extraction failed. Check logs for more details." } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_french.txt b/Northstar.Client/mod/resource/northstar_client_localisation_french.txt index 0d4786a0..9444a39e 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_french.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_french.txt @@ -64,7 +64,7 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "earn_meter_pilot_multiplier" "Multiplicateur de boost pilote" "earn_meter_titan_multiplier" "Multiplicateur de boost titan" - "aegis_upgrades" "Aegis Upgrades" + "aegis_upgrades" "Upgrades Aegis" "infinite_doomed_state" "Etat condamné infini" "titan_shield_regen" "Régénération des boucliers" @@ -82,15 +82,17 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "cp_amped_capture_points" "Points de capture améliorés" "coliseum_loadouts_enabled" "Equipements du Colisée" + "aitdm_archer_grunts" "Soldats (Archer)" + // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "Bac à sable" - "PL_sbox_lobby" "Lobby: Bac à sable" - "PL_sbox_desc" "GMod, mais en pire..." + "PL_sbox_lobby" "Lobby : Bac à sable" + "PL_sbox_desc" "GMod, mais en pire" "PL_sbox_abbr" "SBOX" "GAMEMODE_SBOX" "Bac à sable" "PL_gg" "Gun game" - "PL_gg_lobby" "Lobby: Gun game" + "PL_gg_lobby" "Lobby : Gun game" "PL_gg_desc" "Obtenez une nouvelle arme à chaque frag.\nTuez un pilote avec chaque arme pour gagner." "PL_gg_hint" "Obtenez une nouvelle arme à chaque frag.\nTuez un pilote avec chaque arme pour gagner." "PL_gg_abbr" "GG" @@ -100,21 +102,21 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "gg_execution_reward" "Récompense pourcentage d'exécutions" "PL_tt" "Titan tag" - "PL_tt_lobby" "Lobby: Titan tag" + "PL_tt_lobby" "Lobby : Titan tag" "PL_tt_desc" "Gagnez des points lorsque vous êtes dans votre titan.\nDétruisez un titan pour obtenir le vôtre." "PL_tt_hint" "Gagnez des points lorsque vous êtes dans votre titan.\nDétruisez un titan pour obtenir le vôtre." "PL_tt_abbr" "TT" "GAMEMODE_TT" "Titan tag" "PL_chamber" "Le professionnel" - "PL_chamber_lobby" "Lobby: Le professionnel" + "PL_chamber_lobby" "Lobby : Le professionnel" "PL_chamber_desc" "Un tir, un mort.\nObtenez une balle en tuant un pilote." "PL_chamber_hint" "Un tir, un mort.\nObtenez une balle en tuant un pilote." "PL_chamber_abbr" "CHAMBER" "GAMEMODE_CHAMBER" "Le professionnel" "PL_hidden" "Chasse" - "PL_hidden_lobby" "Lobby: Chasse" + "PL_hidden_lobby" "Lobby : Chasse" "PL_hidden_desc" "Un pilote est invisible et chasse les autres." "PL_hidden_hint" "Un pilote est invisible et chasse les autres." "PL_hidden_abbr" "HIDDEN" @@ -124,7 +126,7 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "HIDDEN_FIRST_HIDDEN" "%s1 est le chasseur." "PL_sns" "Sticks and Stones" - "PL_sns_lobby" "Lobby: Sticks and Stones" + "PL_sns_lobby" "Lobby : Sticks and Stones" "PL_sns_desc" "Chacun pour soi.\nLes exécutions et les lames à impulsions réinitialisent le score de vos ennemis." "PL_sns_abbr" "SNS" "GAMEMODE_SNS" "Sticks and Stones" @@ -142,7 +144,7 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "sns_softball_enabled" "Softball activé" "PL_inf" "Infection" - "PL_inf_lobby" "Lobby: Infection" + "PL_inf_lobby" "Lobby : Infection" "PL_inf_desc" "Les pilotes survivants deviennent infectés lorsque tués." "PL_inf_hint" "Les pilotes survivants deviennent infectés lorsque tués." "PL_inf_abbr" "INF" @@ -156,14 +158,14 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "INFECTION_SURVIVE_LAST_SURVIVOR" "Survivez." "PL_tffa" "Chacun pour soi (titans)" - "PL_tffa_lobby" "Lobby: Chacun pour soi (titans)" + "PL_tffa_lobby" "Lobby : Chacun pour soi (titans)" "PL_tffa_desc" "Chacun pour soi.\nDétruisez les titans ennemis." "PL_tffa_hint" "Chacun pour soi.\nDétruisez les titans ennemis." "PL_tffa_abbr" "TFFA" "GAMEMODE_TFFA" "Chacun pour soi (titans)" "PL_hs" "Cache-cache" - "PL_hs_lobby" "Lobby: Cache-cache" + "PL_hs_lobby" "Lobby : Cache-cache" "PL_hs_desc" "Les pilotes doivent se cacher pour ne pas être trouvés par l'un d'eux." "PL_hs_hint" "Les pilotes doivent se cacher pour ne pas être trouvés par l'un d'eux." "PL_hs_abbr" "HS" @@ -183,13 +185,13 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst // these are defined in r1_english but titan war is a shit name so i'm changing it to another one that was referenced in development "GAMEMODE_fw" "Guerre pour la Frontière" "PL_fw" "Guerre pour la Frontière" - "PL_fw_lobby" "Lobby: Guerre pour la Frontière" + "PL_fw_lobby" "Lobby : Guerre pour la Frontière" "PL_fw_desc" "Détruisez le collecteur ennemi et protégez le vôtre." "PL_fw_abbr" "FW" "GAMEMODE_kr" "Course aux frags" "PL_kr" "Course aux frags" - "PL_kr_lobby" "Lobby: Course aux frags" + "PL_kr_lobby" "Lobby : Course aux frags" "PL_kr_desc" "Capturez le drapeau pour devenir le prédateur.\nFaites des victimes pour établir un nouveau record de frags.\nLe pilote ayant le plus de frags à la fin de la partie l'emporte." "PL_kr_hint" "Capturez le drapeau pour devenir le prédateur.\nFaites des victimes pour établir un nouveau record de frags.\nLe pilote ayant le plus de frags à la fin de la partie l'emporte." "PL_kr_abbr" "KR" @@ -205,12 +207,12 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "GAMEMODE_fastball" "Fastball" "PL_fastball" "Fastball" - "PL_fastball_lobby" "Lobby: Fastball" + "PL_fastball_lobby" "Lobby : Fastball" "PL_fastball_desc" "Mort permanente.\nPiratez les panneaux de contrôle pour faire réapparaître vos équipiers." "PL_fastball_hint" "Mort permanente.\nPiratez les panneaux de contrôle pour faire réapparaître vos équipiers." "PL_fastball_abbr" "FB" "FASTBALL_PANEL_CAPTURED" "%s1 a piraté le panneau de contrôle %s2 !" - "SCOREBOARD_FASTBALL_HACKS" "Panneaux de\ncontrôle capturés" + "SCOREBOARD_FASTBALL_HACKS" "Panneaux de contrôle capturés" "GAMEMODE_ctf_comp" "Capture de drapeau - Compétitif" @@ -237,7 +239,7 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst // coop stuff "PL_sp_coop" "(ALPHA) Campagne (coop)" - "PL_sp_coop_lobby" "Lobby: Campagne (coop)" + "PL_sp_coop_lobby" "Lobby : Campagne (coop)" "PL_sp_coop_desc" "Jouez la campagne avec des amis." "PL_sp_coop_hint" "Jouez la campagne avec des amis." "PL_sp_coop_abbr" "SP" @@ -274,7 +276,7 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "PLAYERS_COLUMN" "Joueurs" "MAP_COLUMN" "Carte" "GAMEMODE_COLUMN" "Mode de jeu" - "LATENCY_COLUMN" "Latence" + "REGION_COLUMN" "Région" "SEARCHBAR_LABEL" "Recherche :" "MAP_FILTER" "Carte" "GAMEMODE_FILTER" "Mode de jeu" @@ -314,8 +316,68 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst "UNAUTHORIZED_PWD" "Mot de passe incorrect" "STRYDER_RESPONSE" "Impossible d'analyser la réponse de Stryder" "PLAYER_NOT_FOUND" "Impossible de trouver le compte du joueur" - "INVALID_MASTERSERVER_TOKEN" "Jeton du server maître invalide ou expiré" + "INVALID_MASTERSERVER_TOKEN" "Token du server maître invalide ou expiré, veuillez relancer l'application EA." "JSON_PARSE_ERROR" "Une erreur est survenue durant l'analyse JSON" "UNSUPPORTED_VERSION" "La version que vous utilisez n'est plus supportée" + + "MOD_SETTINGS" "Paramètres de mod" + "NORTHSTAR_BASE_SETTINGS" "Paramètres de base de Northstar" + "ONLY_HOST_MATCH_SETTINGS" "Seul l'hôte peut changer les paramètres de match privé" + "ONLY_HOST_CAN_START_MATCH" "Seul l'hôte peut lancer le match" + "MATCH_COUNTDOWN_LENGTH" "Durée du compte à rebours de match privé" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Enregistrer les commandes client inconnues" + "DISALLOWED_TACTICALS" "Capacités interdites" + "TACTICAL_REPLACEMENT" "Capacités de remplacement" + "DISALLOWED_WEAPONS" "Armes interdites" + "REPLACEMENT_WEAPON" "Armes de remplacement" + "SHOULD_RETURN_TO_LOBBY" "Retour au lobby après la fin du match" + "ARE_YOU_SURE" "Êtes-vous certain ?" + "WILL_RESET_ALL_SETTINGS" "Ceci réinitialisera tous les paramètres de cette catégorie.\n\nCette action est irréversible." + "WILL_RESET_SETTING" "Ceci réinitialisera le paramètre %s1 à sa valeur par défaut.\n\nCette action est irréversible." + "MOD_SETTINGS_SERVER" "Serveur" + "MOD_SETTINGS_RESET" "Réinitialiser" + "MOD_SETTINGS_RESET_ALL" "Tout réinitialiser" + "SHOW_ONLY_REQUIRED" "Afficher les mods requis" + "SHOW_ONLY_NOT_REQUIRED" "Uniquement les mods optionnels" + "NO_RESULTS" "Aucun résultat." + "NO_MODS" "Aucun paramètre trouvé ! Installez d'autres mods depuis ^5588FF00northstar.thunderstore.io^0." + "player_force_respawn" "Réapparition forcée" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "Désactiver la progression ?" + "PROGRESSION_TOGGLE_ENABLED_BODY" "Les Titans, Armes, Factions, Skins, et autres seront débloqués et utilisables en tout temps.\n\nPeut être changé à n'importe que moment dans le salon multijoueurs." + "PROGRESSION_TOGGLE_DISABLED_HEADER" "Activer la progression ?" + "PROGRESSION_ENABLED_HEADER" "Progression activée !" + "PROGRESSION_DISABLED_HEADER" "Progression désactivée !" + "PROGRESSION_DISABLED_BODY" "^CCCC0000La progression a été désactivée.^\n\nLes Titans, Armes, Factions, Skins, et autres seront débloqués et utilisables en tout temps.\n\nPeut être changé à n'importe que moment dans le salon multijoueurs." + "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 équipez 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" + "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." + "AUTHENTICATION_FAILED_HEADER" "Échec de l'authentification" + "AUTHENTICATION_FAILED_HELP" "Aide" + "AUTHENTICATION_FAILED_ERROR_CODE" "Code d'erreur : ^DB6F2C00%s1^" + "AUTHENTICATION_FAILED_BODY" "L'authentification avec Atlas a échoué." + "MISSING_MOD" "Mod manquant \"%s1\" v%s2" + "MOD_REQUIRED_WARNING" " : Ce mod peut être (dé)chargé automatiquement en rejoignant un serveur" + "EXTRACTING_MOD_TITLE" "Extraction du mod (%s1%)" + "MOD_NOT_VERIFIED" "(ce mod n'est pas vérifié, et n'a donc pas pu être automatiquement téléchargé)" + "MOD_DL_DISABLED" "(le téléchargement automatique de mods est désactivé)" + "DOWNLOADING_MOD_TITLE" "Téléchargement du mod" + "DOWNLOADING_MOD_TITLE_W_PROGRESS" "Téléchargement du mod (%s1%)" + "DOWNLOADING_MOD_TEXT" "Téléchargement de %s1 v%s2..." + "WRONG_MOD_VERSION" "Le serveur requiert la version v%s2 du mod \"%s1\" (vous avez la version v%s3)" + "DOWNLOADING_MOD_TEXT_W_PROGRESS" "Téléchargement de %s1 v%s2...\n(%s3/%s4 Mo)" + "CHECKSUMING_TITLE" "Vérification de la somme de contrôle du mod" + "CHECKSUMING_TEXT" "Vérification du contenu de %s1 v%s2..." + "EXTRACTING_MOD_TEXT" "Extraction de %s1 v%s2...\n(%s3/%s4 Mo)" + "FAILED_DOWNLOADING" "Echec du téléchargement du mod" + "FAILED_READING_ARCHIVE" "Une erreur est survenue lors de la lecture de l'archive." + "FAILED_WRITING_TO_DISK" "Une erreur est survenue lors de l'extraction des fichiers." + "MOD_FETCHING_FAILED" "L'archive n'a pas pu être téléchargée depuis Thunderstore." + "MOD_CORRUPTED" "La somme de contrôle de l'archive ne correspond pas à la signature vérifiée." + "NO_DISK_SPACE_AVAILABLE" "L'espace restant sur votre disque est insuffisant." + "MOD_FETCHING_FAILED_GENERAL" "L'extraction du mod a échoué. Consultez le journal pour plus d'informations." + "MANIFESTO_FETCHING_TITLE" "Préparation du téléchargement du mod" + "MANIFESTO_FETCHING_TEXT" "Récupération de la liste des mods vérifiés..." } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_german.txt b/Northstar.Client/mod/resource/northstar_client_localisation_german.txt index 0eded5bc..996a3e2b 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_german.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_german.txt @@ -8,6 +8,9 @@ "MENU_LAUNCH_NORTHSTAR" "Northstar starten" "MENU_TITLE_MODS" "Mods" "RELOAD_MODS" "Mods neu laden" + "WARNING" "Warnung" + "CORE_MOD_DISABLE_WARNING" "Das Deaktivieren von essentiellen Mods kann die Funktion deines Clients beeinträchtigen!" + "DISABLE" "Deaktiviere" "DIALOG_TITLE_INSTALLED_NORTHSTAR" "Danke, dass du Northstar installiert hast!" "AUTHENTICATION_AGREEMENT_DIALOG_TEXT" "Damit Northstar funktionieren kann, muss es mithilfe des Northstar Masterservers authentifizieren. Dies setzt ein Weitergeben deines Origin Tokens an den Masterserver voraus, er wird nicht gespeichert oder für andere Zwecke verwendet. @@ -16,6 +19,9 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü "AUTHENTICATION_AGREEMENT" "Authentifizierungs-Einwilligung" "AUTHENTICATION_AGREEMENT_RESTART" "Ein Neustart ist notwendig, um diese Änderung zu übernehmen" + "DIALOG_AUTHENTICATING_MASTERSERVER" "Authentifizierung mit Master Server" + "AUTHENTICATIONAGREEMENT_NO" "Du hast dich gegen die Authentifizierung mit Northstar entschieden. Du kannst die Authentifizierungs-Einwilligung im Modmenü ansehen." + "MENU_TITLE_SERVER_BROWSER" "Server Browser" "NS_SERVERBROWSER_NOSERVERS" "Keine Server gefunden" "NS_SERVERBROWSER_UNKNOWNMODE" "Unbekannter Modus" @@ -75,6 +81,8 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü "cp_amped_capture_points" "Verstärkte Hardpoints" "coliseum_loadouts_enabled" "Coliseum Loadouts" + "aitdm_archer_grunts" "Archer Frontsoldaten" + // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "Sandbox" "PL_sbox_lobby" "Sandbox Lobby" @@ -88,6 +96,8 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü "PL_gg_hint" "Erhalte einen Kill mit jeder Waffe um zu siegen." "PL_gg_abbr" "GG" "GAMEMODE_GG" "Gun Game" + "gg_kill_reward" "Killprozentbelohnung" + "gg_execution_reward" "Exekutierungsprozentbelohnung" "PL_tt" "Titan Tag" "PL_tt_lobby" "Titan Tag Lobby" @@ -113,6 +123,17 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü "HIDDEN_KILL_SURVIVORS" "Töte alle Überlebenden" "HIDDEN_FIRST_HIDDEN" "%s1 ist the The Hidden." + "PL_sns" "Stock und Stein" + "PL_sns_lobby" "Stock und Stein Lobby" + "PL_sns_desc" "Frei für Alle. Erziele Kills mit Impulsklingen und Exekutierungen um die Punktzahl des Gegners zurückzusetzen" + "PL_sns_abbr" "SuS" + "GAMEMODE_SNS" "Stock und Stein" + "sns_wme_kill_value" "Wingman Elite Killwert" + "sns_softball_kill_value" "Softball Killwert" + "sns_reset_kill_value" "Pulseklinge/Exekutierung Killwert" + "sns_melee_kill_value" "Nahkampfkill Killwert" + "sns_softball_enabled" "Softball aktiviert" + "PL_inf" "Infektion" "PL_inf_lobby" "Infektion-Lobby" "PL_inf_desc" "Überlebe die Infektion. Überlebende werden nach dem Tod infiziert." @@ -246,7 +267,7 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü "PLAYERS_COLUMN" "Spieler" "MAP_COLUMN" "Karte" "GAMEMODE_COLUMN" "Modus" - "LATENCY_COLUMN" "Ping" + "REGION_COLUMN" "Region" "SEARCHBAR_LABEL" "Suche:" "MAP_FILTER" "Karte" "GAMEMODE_FILTER" "Modus" @@ -266,6 +287,15 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü "INGAME_PLAYERS" "Spieler: ^6BA6C400%s1" "TOTAL_SERVERS" "Server: ^C46C6C00%s1" + // Mods menu + "SHOW" "Anzeigen" + "SHOW_ALL" "Alle anzeigen" + "SHOW_ONLY_ENABLED" "Nur aktivierte" + "SHOW_ONLY_DISABLED" "Nur deaktivierte" + + // Maps menu + "HIDE_LOCKED" "Verstecke gesperrte" + // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" @@ -280,5 +310,71 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü "INVALID_MASTERSERVER_TOKEN" "Ungültiger oder abgelaufener Token vom Masterserver" "JSON_PARSE_ERROR" "Fehler beim Verarbeiten der JSON-Antwort" "UNSUPPORTED_VERSION" "Die Version die du benutzt ist nicht länger unterstützt" + "SNS_LEADER_BANKRUPT_SUB" "%s1 Wurde Von %s2 Zurückgesetzt" + "SNS_BANKRUPT_SUB" "Dein Punkestand wurde von %s1 zurückgesetzt" + "respawnprotection" "Respawn Schutzdauer" + "SNS_BANKRUPT" "Bankrott!" + "SNS_LEADER_BANKRUPT" "Punktzahlführer Bankrott!" + "sns_reset_pulse_blade_cooldown_on_pulse_blade_kill" "Kill Cooldown Zurücksetzungen" + "player_force_respawn" "Erzwungener Respawn" + "SHOW_ONLY_NOT_REQUIRED" "Nur optionale Mods" + "SHOW_ONLY_REQUIRED" "Nur notwendige Mods" + "PROGRESSION_TOGGLE_DISABLED_HEADER" "Fortschritt aktivieren?" + "TOGGLE_PROGRESSION" "Fortschritt zuschalten" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "Fortschritt deaktivieren?" + "PROGRESSION_TOGGLE_ENABLED_BODY" "Titans, Waffen, Fraktionen, Skins, usw werden freigeschaltet und sind zu jeder Zeit verfügbar .\n\nDies kann in der Mehrspielerlobby zu jedem Zeitpunkt geändert werden." + "MATCH_COUNTDOWN_LENGTH" "Countdown für privates Match" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Unbekannte Clientbefehle loggen" + "DISALLOWED_TACTICALS" "Verbotene Taktiken" + "TACTICAL_REPLACEMENT" "Taktischer Austausch" + "AUTHENTICATION_FAILED_HEADER" "Authentifizierung fehlgeschlagen" + "AUTHENTICATION_FAILED_BODY" "Authentifizierung mit Atlas fehlgeschlagen!" + "AUTHENTICATION_FAILED_ERROR_CODE" "Fehlercode: ^DB6F2C00%s1^" + "AUTHENTICATION_FAILED_HELP" "Hilfe" + "NORTHSTAR_BASE_SETTINGS" "Northstar Grundeinstellungen" + "ONLY_HOST_MATCH_SETTINGS" "Nur der Host kann die Einstellungen eines privaten Matches ändern" + "ONLY_HOST_CAN_START_MATCH" "Nur der Host kann das Match starten" + "MISSING_MOD" "Fehlender Mod \"%s1\" v%s2" + "MOD_DL_DISABLED" "(automatisches Herunterladen ist deaktiviert)" + "DOWNLOADING_MOD_TITLE" "Lade Mod herunter" + "DOWNLOADING_MOD_TITLE_W_PROGRESS" "Lade Mod (%s1%)" + "DOWNLOADING_MOD_TEXT" "Lade %s1 v%s2..." + "DOWNLOADING_MOD_TEXT_W_PROGRESS" "Lade %s1 v%s2...\n(%s3/%s4 MB)" + "CHECKSUMING_TITLE" "Überprüfe Mod Prüfsumme" + "MOD_NOT_VERIFIED" "(mod ist nicht verifiziert und kann nicht automatisch herunterladen werden)" + "MOD_REQUIRED_WARNING" " : Dieser Mod könnte Sie (un)ausgestattet hinterlassen, sobald Sie einem Server beitreten" + "MOD_SETTINGS" "Mod Einstellungen" + "DISALLOWED_WEAPONS" "Verbotene Waffen" + "REPLACEMENT_WEAPON" "Austausch Waffen" + "SHOULD_RETURN_TO_LOBBY" "Zur Lobby nach Matchende zurückkehren" + "ARE_YOU_SURE" "Sind Sie sich sicher?" + "MOD_SETTINGS_SERVER" "Server" + "MOD_SETTINGS_RESET" "Zurücksetzen" + "MOD_SETTINGS_RESET_ALL" "Alles zurücksetzen" + "NO_RESULTS" "Keine Ergebnisse." + "NO_MODS" "Keine Einstellungen verfügbar! Installieren sie weitere Mods über^5588FF00northstar.thunderstore.io^0." + "PROGRESSION_ENABLED_HEADER" "Fortschritt aktiviert!" + "PROGRESSION_DISABLED_HEADER" "Fortschritt deaktiviert!" + "WILL_RESET_ALL_SETTINGS" "Dadurch werden ALLE Einstellungen, die zu dieser Kategorie gehören, zurückgesetzt.\n\nDies kann nicht rückgängig gemacht werden." + "WILL_RESET_SETTING" "Dies setzten die Einstellungen %s1 auf deren Ursprungeswert zurück.\n\nDies kann nicht rückgängig gemacht werden." + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Fortschritt zuschalten." + "PROGRESSION_TOGGLE_DISABLED_BODY" "Titans, Waffen, Fraktionen, Skins usw. müssen durch Levelaufstieg freigeschaltet oder mit Verdiensten gekauft werden.\n\nDies kann jederzeit in der Mehrspieler-Lobby geändert werden.\n\n^CC000000Warnung: Wenn Sie derzeit ausgerüstete Gegenstände besitzen, die Sie nicht freigeschaltet haben, werden diese zurückgesetzt!" + "PROGRESSION_ENABLED_BODY" "^CCCC0000Fortschritt wurde aktiviert.^\n\nTitans, Waffen, Fraktionen, Skins usw. müssen durch Levelaufstieg freigeschaltet oder mit Verdiensten gekauft werden.\n\nDies kann jederzeit in der Mehrspieler-Lobby geändert werden." + "PROGRESSION_DISABLED_BODY" "^CCCC0000Fortschritt wurde deaktiviert.^\n\nTitans, Waffen, Fraktionen, Skins usw. werden alle freigeschaltet und jederzeit nutzbar sein.\n\nDies kann jederzeit in der Mehrspieler-Lobby geändert werden." + "CHECKSUMING_TEXT" "Verifiziere Inhalte von %s1 v%s2..." + "EXTRACTING_MOD_TITLE" "Extrahiere Mod (%s1%)" + "EXTRACTING_MOD_TEXT" "Extrahiere %s1 v%s2...\n(%s3/%s4 MB)" + "FAILED_DOWNLOADING" "Herunterladen der Mod fehlgeschlagen" + "FAILED_READING_ARCHIVE" "Während des Lesens der Mod Archivs ist ein Fehler aufgetreten." + "FAILED_WRITING_TO_DISK" "Während des Extrahierens der Mod in das Dateisysteme ist ein Fehler aufgetreten." + "WRONG_MOD_VERSION" "Der Server verfügt über Mod \"%s1\" v%s2 während Sie v%s3 haben" + "MOD_FETCHING_FAILED" "Mod Archiv konnte nicht von Thunderstore heruntergeladen werden." + "MOD_CORRUPTED" "Prüfsumme des heruntergeladenen Archivs stimmt nicht mit der verifizierten Signatur überein." + "NO_DISK_SPACE_AVAILABLE" "Sie verfügen nicht über ausreichend Speicherplatz auf ihrer Festplatte." + "MOD_FETCHING_FAILED_GENERAL" "Mod Extraktion fehlgeschlagen. Überprüfen Sie die Logs für weitere Details." + "gg_assist_reward" "Assist Anteilige Belohnung" + "SCOREBOARD_BANKRUPTS" "Bankrott Kills" + "sns_offhand_kill_value" "Freihand Killwert" + "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000Fortschritt kann jetzt aktiviert werden!^\n\nNorthstar unterstützt nun den standardmäßigen Fortschritt, was bedeutet, dass Sie Waffen, Skins, Titans usw. durch Levelaufstieg und das Abschließen von Herausforderungen freischalten können.\n\nSie können den Fortschritt mit dem Button am unteren Rand des Lobbybildschirms aktivieren.\n\nDies kann jederzeit geändert werden." } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt b/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt index b8253ad9..38e67dea 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt @@ -6,16 +6,23 @@ "MENU_LAUNCH_NORTHSTAR" "Avvia Northstar" "MENU_TITLE_MODS" "Mods" "RELOAD_MODS" "Ricarica Mods" + "WARNING", "Attenzione" + "CORE_MOD_DISABLE_WARNING", "Disattivare le Mods Principali può rompere il tuo Client!" + "DISABLE", "Disattiva" "DIALOG_TITLE_INSTALLED_NORTHSTAR" "Grazie per aver installato Northstar!" "AUTHENTICATION_AGREEMENT_DIALOG_TEXT" "Affinché Northstar funzioni, è necessario autenticarsi utilizzando il server principale di Northstar. Ciò richiederà l'invio del tuo token di Origin al server principale, non verrà archiviato o utilizzato per altri scopi. -Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi momento nel menu mods." +Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi momento nel Menu delle Mods." "BACK_AUTHENTICATION_AGREEMENT" "Accordo di autenticazione" "AUTHENTICATION_AGREEMENT" "Accordo di autenticazione" "AUTHENTICATION_AGREEMENT_RESTART" "Dovrai riavviare Titanfall 2 affinché questa scelta abbia effetto." + "DIALOG_AUTHENTICATING_MASTERSERVER", "Autenticazione Sul Master Server in corso" + "AUTHENTICATIONAGREEMENT_NO", "Hai Scelto di non autenticarti con Northstar. Puoi vedere l'Accordo nel Menu delle Mods" + "MENU_TITLE_SERVER_BROWSER" "Server Browser" "NS_SERVERBROWSER_NOSERVERS" "Nessun server trovato" + "NS_SERVERBROWSER_UNKNOWNMODE", "Modalità Sconosciuta" "NS_SERVERBROWSER_WAITINGFORSERVERS" "In attesa dei server..." "NS_SERVERBROWSER_CONNECTIONFAILED" "Connessione fallita!" "REFRESH_SERVERS" "Aggiorna" @@ -32,7 +39,7 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "PRIVATE_MATCH_SINGLEPLAYER_LEVEL" "%s1 (Single-Player)" // fra hint for private match menu, because fra only has PL_fra_desc in vanilla - "PL_fra_hint" "Tutti contro tutti. Uccidi nemici per vincere. Raccogli 3 batterie per chiamare il Titan." + "PL_fra_hint" "Tutti contro tutti. Uccidi i nemici per vincere. Raccogli 3 batterie per chiamare il tuo Titan." // mode settings "MODE_SETTING_CATEGORY_PILOT" "Pilota" @@ -46,6 +53,7 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "roundscorelimit" "Limite Punteggio (per round)" "timelimit" "Limite di Tempo" "roundtimelimit" "Limite di Tempo (per round)" + "respawnprotection", "Tempo Protezione di Respawn" "pilot_health_multiplier" "Moltiplicatore di Salute" "respawn_delay" "Tempo di Respawn" @@ -55,7 +63,7 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "earn_meter_titan_multiplier" "Moltiplicatore nucleo Titan" "aegis_upgrades" "Upgrade Aegis" - "infinite_doomed_state" "Doom state Infinito" + "infinite_doomed_state" "Stato Doom Infinito" "titan_shield_regen" "Rigenerazione Scudi" "riff_floorislava" "Terreno Mortale" @@ -72,10 +80,12 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "cp_amped_capture_points" "Hardpoints Amplificati" "coliseum_loadouts_enabled" "Equipaggiamento Colosseo" + "aitdm_archer_grunts", "Scagnozzi Archer" + // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "Sandbox" - "PL_sbox_lobby" "Sandbox Lobby" - "PL_sbox_desc" "come gmod ma peggio." + "PL_sbox_lobby" "Lobby: Sandbox" + "PL_sbox_desc" "Come gmod ma peggio" "PL_sbox_abbr" "SBOX" "GAMEMODE_SBOX" "Sandbox" @@ -84,7 +94,11 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "PL_gg_desc" "Ottieni un'uccisione con ogni arma per vincere." "PL_gg_hint" "Ottieni una nuova arma ogni uccisione." "PL_gg_abbr" "GG" - "GAMEMODE_GG" "Gioco d'Armi" + "GAMEMODE_GG" "Gioco delle Armi" + "aitdm_archer_grunts", "Scagnozzi Archer" + "gg_kill_reward", "Punteggio Ricompensa Uccisione" + "gg_assist_reward", "Punteggio Ricompensa Assist" + "gg_execution_reward", "Punteggio Ricompensa Esecuzione" "PL_tt" "Titan Tag" "PL_tt_lobby" "Lobby: Titan Tag" @@ -110,6 +124,24 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "HIDDEN_KILL_SURVIVORS" "Uccidi tutti i giocatori." "HIDDEN_FIRST_HIDDEN" "%s1 è il Cacciatore." + "PL_sns", "Sticks and Stones" + "PL_sns_lobby", "Sticks and Stones Lobby" + "PL_sns_desc", "Tutti contro Tutti, Usa la Pulse Blade e le Esecuzioni per Resettare il Punteggio Nemico" + "PL_sns_abbr", "SNS" + "GAMEMODE_SNS", "Sticks and Stones" + "SCOREBOARD_BANKRUPTS", "Uccisioni Bancarotta" + "SNS_LEADER_BANKRUPT", "Il Leader punteggio è andato in Bancarotta!" + "SNS_LEADER_BANKRUPT_SUB", "%s1 è stato Resettato da %s2" + "SNS_BANKRUPT", "Bancarotta!" + "SNS_BANKRUPT_SUB", "Il Tuo Punteggio è stato Resettato da %s1" + "sns_wme_kill_value", "Valore Uccisione Wingman d'Elite" + "sns_softball_kill_value", "Valore Uccisione Softball" + "sns_offhand_kill_value", "Valore Uccisione Improvvisa" + "sns_reset_kill_value", "Valore Uccisione Pulse/Esecuzione" + "sns_melee_kill_value", "Valore Uccisione Corpo a Corpo" + "sns_reset_pulse_blade_cooldown_on_pulse_blade_kill", "Reset Cooldown Uccisione" + "sns_softball_enabled", "Softball Attivato" + "PL_inf" "Infetto" "PL_inf_lobby" "Lobby: Infetto" "PL_inf_desc" "Sopravvivi all'infezione. I sopravvissuti vengono infettati quando uccisi." @@ -124,6 +156,13 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "INFECTION_YOU_ARE_LAST_SURVIVOR" "Sei l'Ultimo Sopravvissuto!" "INFECTION_SURVIVE_LAST_SURVIVOR" "Sopravvivi." + "PL_tffa", "Titan Tutti contro Tutti" + "PL_tffa_lobby", "Lobby: Titan Tutti contro Tutti" + "PL_tffa_desc", "Ogni Pilota per sè, distruggi tutti i Titan Nemici." + "PL_tffa_hint", "Ogni Pilota per sè, distruggi tutti i Titan Nemici." + "PL_tffa_abbr", "TFFA" + "GAMEMODE_TFFA", "Titan Tutti contro Tutti" + "PL_hs" "Nascondino" "PL_hs_lobby" "Lobby: Nascondino" "PL_hs_desc" "Nasconditi oppure trova gli avversari." @@ -131,22 +170,22 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "PL_hs_abbr" "NS" "GAMEMODE_hs" "Nascondino" "HIDEANDSEEK_YOU_ARE_SEEKER" "TROVA I GIOCATORI NASCOSTI" - "HIDEANDSEEK_SEEKER_DESC" "Trova ed uccidi tutti i giocatori nascosti. \nRespawnerai in %s1 secondi." + "HIDEANDSEEK_SEEKER_DESC" "Trova ed uccidi tutti i giocatori nascosti. \nRespawnerai in %s1 secondi" "HIDEANDSEEK_YOU_ARE_HIDER" "NASCONDITI" "HIDEANDSEEK_HIDER_DESC" "Nasconditi e cerca di non farti trovare." "HIDEANDSEEK_SEEKERS_INCOMING" "HANNO INIZIATO A CERCARTI" "HIDEANDSEEK_DONT_GET_FOUND" "Non farti trovare!" "HIDEANDSEEK_GET_LAST_HIDER" "%s1 è L'ULTIMO CERCATORE" "HIDEANDSEEK_YOU_ARE_LAST_HIDER" "SEI L'ULTIMO NASCOSTO" - "HIDEANDSEEK_GOT_STIM" "Sei stimmato! Non farti prendere!" - "hideandseek_balance_teams" "Bilanciamento Squadre..." + "HIDEANDSEEK_GOT_STIM" "Sei stimolato! Non farti prendere!" + "hideandseek_balance_teams" "Bilanciamento Squadre" "hideandseek_hiding_time" "Tempo per Nascondersi" // these are defined in r1_english but titan war is a shit name so i'm changing it to another one that was referenced in development - "GAMEMODE_fw" "Frontier War" - "PL_fw" "Frontier War" - "PL_fw_lobby" "Lobby: Frontier War" - "PL_fw_desc" "Distruggi il mietiore nemico e proteggi il tuo." + "GAMEMODE_fw" "Guerra di Frontiera" + "PL_fw" "Guerra di Frontiera" + "PL_fw_lobby" "Lobby: Guerra di Frontiera" + "PL_fw_desc" "Distruggi il mietiore nemico e proteggi il tuo" "PL_fw_abbr" "FW" "GAMEMODE_kr" "Killrace Amplificata" @@ -159,10 +198,10 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "KR_NEW_RACER" "%s1 è il killracer amplificato" "KR_YOU_ARE_NEW_RACER" "Sei il killracer amplificato" "KR_YOU_SET_NEW_RECORD" "Stabilisci un nuovo record di uccisioni!" - "KR_FLAG_INCOMING" "Bandiera in Arrivo!" + "KR_FLAG_INCOMING" "Bandiera in Arrivo" "KR_COLLECT_FLAG" "Raccoglila per diventare il killracer!" - "KR_ENEMY_KILLRACE_OVER" "La killrace di %s1 è finita." - "KR_YOUR_KILLRACE_OVER" "La tua killrace è finita." + "KR_ENEMY_KILLRACE_OVER" "La killrace di %s1 è finita" + "KR_YOUR_KILLRACE_OVER" "La tua killrace è finita" "KR_YOUR_KILLRACE_SCORE" "Hai ottenuto %s1 uccisioni." "GAMEMODE_fastball" "Fastball" @@ -183,7 +222,7 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "custom_air_accel_pilot" "Accelerazione Aerea" "no_pilot_collision" "Collisione tra Piloti" "promode_enable" "Armi Modalità Competitiva" - "fp_embark_enabled" "Imbarchi/esecuzioni in 1ºpers." + "fp_embark_enabled" "Imbarchi/esecuzioni in 1º persona" "classic_rodeo" "Rodeo classico" "oob_timer_enabled" "Timer Fuori dai Limiti" "riff_instagib" "Modalità Instagib" @@ -211,7 +250,7 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "SP_CRASHSITE_CLASSIC_DESC" "Jack Cooper incontra BT-7274." "SP_SEWERS1" "Sangue e Ruggine" - "SP_SEWERS1_CLASSIC_DESC" "Cooper e BT cercano di raggiungere il Major Anderson." + "SP_SEWERS1_CLASSIC_DESC" "Cooper e BT cercano di raggiungere il Maggiore Anderson." "SP_BOOMTOWN_START" "Nell'abisso" "SP_BOOMTOWN_START_CLASSIC_DESC" "Una scorciatoia sotterranea porta a conseguenze impreviste." @@ -223,7 +262,7 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "SP_BEACON_CLASSIC_DESC" "Cooper e BT tentano di informare la flotta rimanente dei piani dell'IMC." "SP_TDAY" "Prova del fuoco" - "SP_TDAY_CLASSIC_DESC" "Le abilità del Titan di Cooper vengono messe alla prova in una battaglia senza quartiere per la cattura dell'Arca." + "SP_TDAY_CLASSIC_DESC" "Le abilità del Titan di Cooper vengono messe alla prova in una battaglia senza quartiere per la cattura dell'Arca" "SP_S2S" "L'Arca" "SP_S2S_CLASSIC_DESC" "Cooper e BT inseguono l'Arca affrontando una nave dopo l'altra." @@ -233,10 +272,10 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo // Better.Serverbrowser "SERVERS_COLUMN" "Server" - "PLAYERS_COLUMN" "Players" + "PLAYERS_COLUMN" "Giocatori" "MAP_COLUMN" "Mappa" "GAMEMODE_COLUMN" "Modalità" - "LATENCY_COLUMN" "Latenza" + "REGION_COLUMN" "Regione" "SEARCHBAR_LABEL" "Cerca:" "MAP_FILTER" "Mappa" "GAMEMODE_FILTER" "Modalità" @@ -257,19 +296,89 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo "INGAME_PLAYERS" "Players: ^6BA6C400%s1" "TOTAL_SERVERS" "Server: ^C46C6C00%s1" + // Mods menu + "SHOW", "Mostra" + "SHOW_ALL", "Mostra Tutti" + "SHOW_ONLY_ENABLED", "Mostra solo Attivi" + "SHOW_ONLY_DISABLED", "Mostra solo Inattivi" + + // Maps menu + "HIDE_LOCKED" "Nascondi bloccati" + // In-game chat - "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" + "HUD_CHAT_WHISPER_PREFIX" [BISBIGLIO]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" "NO_GAMESERVER_RESPONSE" "Non è stato possibile raggiungere il server" "BAD_GAMESERVER_RESPONSE" "Il server ha dato una risposta invalida" "UNAUTHORIZED_GAMESERVER" "Il server non è autorizzato a fare quella richiesta" - "UNAUTHORIZED_GAME" "Stryder non è riuscito a confermare che questo account possiede Titanfall 2" + "UNAUTHORIZED_GAME" "Stryder non è riuscito a confermare che questo account possieda Titanfall 2" "UNAUTHORIZED_PWD" "Password errata" - "STRYDER_RESPONSE" "Non è stato possibile analizzare la risposta Stryder" + "STRYDER_RESPONSE" "Non è stato possibile analizzare la risposta di Stryder" "PLAYER_NOT_FOUND" "Non è stato trovato l'account player" "INVALID_MASTERSERVER_TOKEN" "Token Masterserver invalido o scaduto" - "JSON_PARSE_ERROR" "Errore nell'analisi di risposta json" + "JSON_PARSE_ERROR" "Errore nell'analisi della risposta json" "UNSUPPORTED_VERSION" "La versione che stai usando non è più supportata" + + "MOD_SETTINGS" "Impostazioni Mod" + "NORTHSTAR_BASE_SETTINGS" "Impostazioni base Northstar" + "ONLY_HOST_MATCH_SETTINGS" "Solo l'Host può modificare le impostazioni della Partita Privata" + "ONLY_HOST_CAN_START_MATCH" "Solo l'Host può Iniziare la Partita" + "MATCH_COUNTDOWN_LENGTH" "Durata Countdown della Partita Privata" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Registra Comandi Client Sconosciuti" + "DISALLOWED_TACTICALS" "Abilità Proibite" + "TACTICAL_REPLACEMENT" "Sostituzione Abilità" + "DISALLOWED_WEAPONS" "Armi Proibite" + "REPLACEMENT_WEAPON" "Sostituzione Armi" + "SHOULD_RETURN_TO_LOBBY" "Ritorna alla Lobby dopo Fine Partita" + "ARE_YOU_SURE" "Sei sicuro?" + "WILL_RESET_ALL_SETTINGS" "Questo ripristinerà TUTTE le impostazioni che appartengono a questa categoria.\n\nNON può essere annullato." + "WILL_RESET_SETTING" "Questo ripristinerà l'impostazione %s1 al suo valore predefinito.\n\nNON è reversibile." // obviously, don't translate %s1. + "MOD_SETTINGS_SERVER" "Server" + "MOD_SETTINGS_RESET" "Ripristina" + "MOD_SETTINGS_RESET_ALL" "Ripristina Tutto" + "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" + "NO_RESULTS" "Nessun Risultato." + "DISABLE" "Disattiva" + "DIALOG_AUTHENTICATING_MASTERSERVER" "Autenticazione al master server." + "NS_SERVERBROWSER_UNKNOWNMODE" "Modalità sconosciuta" + "respawnprotection" "Tempo di protezione al respawn" + "NO_MODS" "Nessuna impostazione disponibile! Installa più mods a ^5588FF00northstar.thunderstore.io^0." + "gg_assist_reward" "Percentuale ricompensa per assist" + "gg_execution_reward" "Percentuale ricompensa per esecuzione" + "PL_sns" "Sticks and Stones" + "PL_sns_lobby" "Lobby: Sticks and Stones" + "PL_sns_abbr" "SNS" + "GAMEMODE_SNS" "Sticks and Stones" + "SCOREBOARD_BANKRUPTS" "Uccisioni bancarotta" + "SNS_LEADER_BANKRUPT" "Leader punteggio in bancarotta!" + "SNS_LEADER_BANKRUPT_SUB" "%s1 è stato resettato da %s2" + "SNS_BANKRUPT" "Bancarotta!" + "sns_softball_kill_value" "Valore per uccisione Softball" + "sns_offhand_kill_value" "Valore per uccisione manuale" + "sns_melee_kill_value" "Valore per uccisione corpo a corpo" + "sns_softball_enabled" "Softball abilitato" + "PL_tffa" "Tutti contro tutti Titan" + "PL_tffa_lobby" "Lobby: Tutti contro tutti Titan" + "PL_tffa_hint" "Ogni pilota per sè, distruggi tutti i titan nemici." + "PL_tffa_abbr" "TFFA" + "GAMEMODE_TFFA" "Tutti contro tutti Titan" + "sns_reset_pulse_blade_cooldown_on_pulse_blade_kill" "Cooldown reset all'uccisione" + "SHOW" "Mostra" + "SHOW_ALL" "Tutto" + "SHOW_ONLY_ENABLED" "Solo Abilitate" + "SHOW_ONLY_DISABLED" "Solo Disabilitate" + "SHOW_ONLY_NOT_REQUIRED" "Solo Mods opzionali" + "SHOW_ONLY_REQUIRED" "Solo Mods richieste" + "WARNING" "Attenzione" + "CORE_MOD_DISABLE_WARNING" "Disattivare mods di base può rompere il client!" + "AUTHENTICATIONAGREEMENT_NO" "Hai scelto di non autenticarti con Northstar. Puoi vedere l'accordo nel menu delle Mods." + "aitdm_archer_grunts" "Soldati Archer" + "gg_kill_reward" "Percentuale ricompensa per uccisione" + "PL_sns_desc" "Tutti contro tutti. Usa la Lama Impulsi e l'esecuzione per resettare il punteggio avversario" + "SNS_BANKRUPT_SUB" "Il you punteggio è stato resettato da %s1" + "sns_wme_kill_value" "Valore per uccisione Wingman d'Elite" + "sns_reset_kill_value" "Valore per uccisione Lama Impulsi/Esecuzione" + "PL_tffa_desc" "Ogni pilota per sè, distruggi tutti i titan nemici." } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_japanese.txt b/Northstar.Client/mod/resource/northstar_client_localisation_japanese.txt index 08772933..798d603e 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_japanese.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_japanese.txt @@ -3,9 +3,15 @@ "Language" "japanese" "Tokens" { + // ファイルはUTF-16 LEでエンコードしてください、メモ帳なら"名前を付けて保存"から + "MENU_LAUNCH_NORTHSTAR" "Northstarを起動" "MENU_TITLE_MODS" "Modの管理" "RELOAD_MODS" "Modをリロード" + "WARNING" "警告" + "CORE_MOD_DISABLE_WARNING" "コアModを無効化すると、クライアントが破損する可能性があります!" + // 多分ボタンに使われると思うので「無効化」としたが、今後変更する必要があるかもしれない + "DISABLE" "無効化" "MENU_MAIN_AUTHENTICATING" "認証中..." "MENU_MAIN_CONNECTING" "ローカルサーバーへの接続" @@ -17,8 +23,12 @@ "AUTHENTICATION_AGREEMENT" "認証への同意" "AUTHENTICATION_AGREEMENT_RESTART" "変更を適用するには、一度Titanfall 2を再起動する必要があります。" + "DIALOG_AUTHENTICATING_MASTERSERVER" "マスターサーバーへ認証中..." + "AUTHENTICATIONAGREEMENT_NO" "Northstarの認証を行わないことを選択しました。Modメニューから再度このダイアログを開くことができます。" + "MENU_TITLE_SERVER_BROWSER" "サーバーブラウザー" "NS_SERVERBROWSER_NOSERVERS" "サーバーが見つかりませんでした。" + "NS_SERVERBROWSER_UNKNOWNMODE" "不明なモード" "NS_SERVERBROWSER_WAITINGFORSERVERS" "サーバーを待っています..." "NS_SERVERBROWSER_CONNECTIONFAILED" "接続に失敗しました!" // 要議論 @@ -60,6 +70,7 @@ // 要議論: "時間制限"のままか、"マッチ時間"、"タイム上限"、それ以外への差し替え "timelimit" "時間制限" "roundtimelimit" "時間制限 (ラウンドベース)" + "respawnprotection" "リスポーン保護時間" "pilot_health_multiplier" "ヘルス倍率" // 要議論: "リスポーン遅延" のままか、"リスポーンまでの時間"、それ以外への差し替え @@ -89,29 +100,76 @@ "cp_amped_capture_points" "拠点増幅" "coliseum_loadouts_enabled" "コロシアムロードアウト" + // そのまま「グラント」よりも、Respawn翻訳で使われている + //「ミニオン」のほうが伝わりやすいかもしれないのでこっちにする + // 「アーチャーを持ったミニオン」とかだと流石によくなさそうなのでとりあえずそのまま日本語に。 + "aitdm_archer_grunts" "アーチャー持ちミニオン" + // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "サンドボックス" - "PL_sbox_lobby" "サンドボックスロビー" + "PL_sbox_lobby" "サンドボックス ロビー" "PL_sbox_desc" "サンドボックス" "PL_sbox_abbr" "SBOX" "GAMEMODE_SBOX" "Sandbox" "PL_gg" "ガン・ゲーム" - "PL_gg_lobby" "ガン・ゲームロビー" + "PL_gg_lobby" "ガン・ゲーム ロビー" "PL_gg_desc" "全ての銃でキルを取って勝利しろ。" "PL_gg_hint" "全ての銃でキルを取って勝利しろ。" "PL_gg_abbr" "GG" "GAMEMODE_GG" "ガン・ゲーム" + "gg_kill_reward" "キルリワード倍率" + "gg_assist_reward" "アシストリワード倍率" + "gg_execution_reward" "処刑リワード倍率" "PL_tt" "タイタン・タグ" - "PL_tt_lobby" "タイタン・タグロビー" + "PL_tt_lobby" "タイタン・タグ ロビー" "PL_tt_desc" "タイタンとしてポイントを稼げ。敵のタイタンを破壊し自分のタイタンを確保しろ。" "PL_tt_hint" "タイタンとしてポイントを稼げ。敵のタイタンを破壊し自分のタイタンを確保しろ。" "PL_tt_abbr" "TT" "GAMEMODE_TT" "タイタン・タグ" + "PL_chamber" "ワン・イン・ザ・チャンバー" + "PL_chamber_lobby" "ワン・イン・ザ・チャンバー ロビー" + "PL_chamber_desc" "ワンショット・ワンキル。敵をキルして、弾倉に新たな弾丸を込めろ。" + "PL_chamber_hint" "ワンショット・ワンキル。敵をキルして、弾倉に新たな弾丸を込めろ。" + "PL_chamber_abbr" "CHAMBER" + "GAMEMODE_CHAMBER" "ワン・イン・ザ・チャンバー" + + "PL_hidden" "ザ・ヒデゥン" + "PL_hidden_lobby" "ザ・ヒデゥン ロビー" + "PL_hidden_desc" "透明化しているプレイヤーが一人潜んでいる。ヒデゥンを撃破せよ。" + "PL_hidden_hint" "透明化しているプレイヤーが一人潜んでいる。ヒデゥンを撃破せよ。" + "PL_hidden_abbr" "HIDDEN" + "GAMEMODE_HIDDEN" "ザ・ヒデゥン" + "HIDDEN_YOU_ARE_HIDDEN" "ヒデゥンになった!" + "HIDDEN_KILL_SURVIVORS" "すべてのサバイバーを撃破せよ。" + "HIDDEN_FIRST_HIDDEN" "%s1 はヒデゥンになった。" + + "PL_sns" "スティック・アンド・ストーン" + "PL_sns_lobby" "スティック・アンド・ストーン ロビー" + "PL_sns_desc" "フリー・フォー・オール。パルスブレードか、処刑を使用して敵のスコアをリセットできる。" + "PL_sns_abbr" "SNS" + "GAMEMODE_SNS" "スティック・アンド・ストーン" + // 要変更: 破産以外の言葉に置き換える + "SCOREBOARD_BANKRUPTS" "破産キル" + "SNS_LEADER_BANKRUPT" "スコアリーダーが破産した!" + "SNS_LEADER_BANKRUPT_SUB" "%s1 は %s2 にスコアをリセットされた" + "SNS_BANKRUPT" "破産!" + "SNS_BANKRUPT_SUB" "あなたのスコアは %s1 によってリセットされた" + // 要議論: value -> "数"?それとも"値"? + "sns_wme_kill_value" "ウィングマン・エリートキル数" + "sns_softball_kill_value" "ソフトボールキル数" + "sns_offhand_kill_value" "オフハンドキル数" + "sns_reset_kill_value" "パルスブレード/処刑キル数" + "sns_melee_kill_value" "格闘キル数" + // 要変更: 「キルリセットまでのクールダウンを有効化するかどうか」なのか、「キルによってクールダウンをリセットするかどうか」なのか。 + // ひとまずそのまま日本語に直したが、わかりにくいので変更するべき。 + "sns_reset_pulse_blade_cooldown_on_pulse_blade_kill" "キルクールダウンリセット" + "sns_softball_enabled" "ソフトボールを有効化" + "PL_inf" "インフェクション" - "PL_inf_lobby" "インフェクションロビー" + "PL_inf_lobby" "インフェクション ロビー" "PL_inf_desc" "生き残りは死亡するとインフェクターになる。" "PL_inf_hint" "生き残りは死亡するとインフェクターになる。" "PL_inf_abbr" "INF" @@ -125,8 +183,15 @@ "INFECTION_YOU_ARE_LAST_SURVIVOR" "お前が最後の生き残りだ!" "INFECTION_SURVIVE_LAST_SURVIVOR" "生きろ" + "PL_tffa" "タイタン フリー・フォー・オール" + "PL_tffa_lobby" "タイタン フリー・フォー・オール ロビー" + "PL_tffa_desc" "すべてのパイロットはタイタンに搭乗している。すべての敵タイタンを撃破せよ。" + "PL_tffa_hint" "すべてのパイロットはタイタンに搭乗している。すべての敵タイタンを撃破せよ。" + "PL_tffa_abbr" "TFFA" + "GAMEMODE_TFFA" "タイタン フリー・フォー・オール" + "PL_hs" "ハイド・アンド・シーク" - "PL_hs_lobby" "ハイド・アンド・シークロビー" + "PL_hs_lobby" "ハイド・アンド・シーク ロビー" "PL_hs_desc" "ハイダーは隠れ、シーカーはハイダーを探せ!" "PL_hs_hint" "ハイダーは隠れ、シーカーはハイダーを探せ!" "PL_hs_abbr" "HS" @@ -145,13 +210,13 @@ "GAMEMODE_fw" "フロンティア戦争" "PL_fw" "フロンティア戦争" - "PL_fw_lobby" "フロンティア戦争ロビー" + "PL_fw_lobby" "フロンティア戦争 ロビー" "PL_fw_desc" "敵のハーベスターを破壊し、自分のを守れ!" "PL_fw_abbr" "FW" "GAMEMODE_kr" "強化キルレース" "PL_kr" "強化キルレース" - "PL_kr_lobby" "強化キルレースロビー" + "PL_kr_lobby" "強化キルレース ロビー" "PL_kr_desc" "旗を拾い、キルレースを開始しろ。キルでポイントを上げ、キルレースの時間を延ばせ。最高ポイント記録が一番高い者が勝利する" "PL_kr_hint" "旗を拾い、キルレースを開始しろ。キルでポイントを上げ、キルレースの時間を延ばせ。最高ポイント記録が一番高い者が勝利する" "PL_kr_abbr" "KR" @@ -167,9 +232,9 @@ "GAMEMODE_fastball" "ファストボール" "PL_fastball" "ファストボール" - "PL_fastball_lobby" "ファストボールロビー" - "PL_fastball_desc" "ライブファイア。パネルをハックし、味方を蘇生できる" - "PL_fastball_hint" "ライブファイア。パネルをハックし、味方を蘇生できる" + "PL_fastball_lobby" "ファストボール ロビー" + "PL_fastball_desc" "ライブファイア。パネルをハックし、味方を蘇生できる。" + "PL_fastball_hint" "ライブファイア。パネルをハックし、味方を蘇生できる。" "PL_fastball_abbr" "FB" "FASTBALL_PANEL_CAPTURED" "%s1 がパネル%s2を制圧した" "SCOREBOARD_FASTBALL_HACKS" "制圧パネル" @@ -182,6 +247,7 @@ "MODE_SETTING_CATEGORY_BLEEDOUT" "パイロットのダウン" "custom_air_accel_pilot" "空中加速度" + "no_pilot_collision" "パイロット同士の当たり判定" "promode_enable" "Proモードの武器" "fp_embark_enabled" "搭乗と処刑の一人称視点" "classic_rodeo" "クラシックロデオ" @@ -199,10 +265,10 @@ "player_bleedout_aiBleedingPlayerMissChance" "ダウン時のAI命中率" // coop stuff - "PL_sp_coop" "(UNFINISHED) Singleplayer Coop" - "PL_sp_coop_lobby" "Singleplayer Coop Lobby" - "PL_sp_coop_desc" "Play through the singleplayer campaign with friends" - "PL_sp_coop_hint" "Play through the singleplayer campaign with friends" + "PL_sp_coop" "(未完成) シングルプレイヤー 協力モード" + "PL_sp_coop_lobby" "シングルプレイヤー 協力モード ロビー" + "PL_sp_coop_desc" "シングルプレイヤーのキャンペーンモードをフレンドと一緒にプレイできる" + "PL_sp_coop_hint" "シングルプレイヤーのキャンペーンモードをフレンドと一緒にプレイできる" "PL_sp_coop_abbr" "SP" "SP_TRAINING" "パイロット・ガントレット" @@ -237,7 +303,7 @@ "PLAYERS_COLUMN" "プレイヤー" "MAP_COLUMN" "マップ" "GAMEMODE_COLUMN" "ゲームモード" - "LATENCY_COLUMN" "レイテンシー" + "REGION_COLUMN" "領域" "SEARCHBAR_LABEL" "検索:" "MAP_FILTER" "マップ" "GAMEMODE_FILTER" "ゲームモード" @@ -257,10 +323,88 @@ "CONNECTING" "接続中..." "INGAME_PLAYERS" "プレイヤー数: ^6BA6C400%s1" "TOTAL_SERVERS" "サーバー数: ^C46C6C00%s1" - // Translation done by Zetryox and CYakigasi + + // Mods menu + "SHOW" "表示" + "SHOW_ALL" "全て" + "SHOW_ONLY_ENABLED" "有効のみ" + "SHOW_ONLY_DISABLED" "無効のみ" + + // Maps menu + "HIDE_LOCKED" "ロック中を隠す" // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + + "NO_GAMESERVER_RESPONSE" "ゲームサーバーに接続できません\n(Couldn't reach game server)" + "BAD_GAMESERVER_RESPONSE" "ゲームサーバーが不明なレスポンスを返しました\n(Game server gave an invalid response)" + "UNAUTHORIZED_GAMESERVER" "ゲームサーバーにそのリクエストを作成する許可がありません\n(Game server is not authorized to make that request)" + "UNAUTHORIZED_GAME" "StryderはこのアカウントがTitanfall 2を所持しているかどうかを確認できませんでした\n(Stryder couldn't confirm that this account owns Titanfall 2)" + "UNAUTHORIZED_PWD" "パスワードが間違っています\n(Wrong password)" + "STRYDER_RESPONSE" "Stryderからのレスポンスの処理に失敗しました\n(Couldn't parse stryder response)" + "PLAYER_NOT_FOUND" "プレイヤーのアカウントが見つかりません\n(Couldn't find player account)" + "INVALID_MASTERSERVER_TOKEN" "マスターサーバーのトークンが不明か期限切れです。EAアプリの再起動をお試しください。\n(Invalid or expired masterserver token, try restarting EA App.)" + "JSON_PARSE_ERROR" "JSONレスポンスの処理に失敗しました\n(Error parsing json response)" + "UNSUPPORTED_VERSION" "現在使用しているバージョンはサポートされていません\n(The version you are using is no longer supported)" + "player_force_respawn" "強制リスポーン" + "SHOW_ONLY_REQUIRED" "必須のModのみ" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% 進行システム切り替え" + "TOGGLE_PROGRESSION" "進行システム切り替え" + "AUTHENTICATION_FAILED_HEADER" "認証に失敗" + "DOWNLOADING_MOD_TITLE" "Modをダウンロード中" + "PROGRESSION_TOGGLE_ENABLED_BODY" "タイタン、武器、勢力、スキンなどが全てアンロックされ、いつでも使えるようになる。\n\nこの設定は、マルチプレイヤーロビーでいつでも変更可能だ。" + "PROGRESSION_TOGGLE_DISABLED_HEADER" "進行システムを有効にしますか?" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "進行システムを無効にしますか?" + "PROGRESSION_DISABLED_HEADER" "進行システムが無効になりました!" + "PROGRESSION_ENABLED_HEADER" "進行システムが有効になりました!" + "PROGRESSION_DISABLED_BODY" "^CCCC0000進行システムが無効化された。^\n\nタイタン、武器、勢力、スキンなどが全てアンロックされ、いつでも使えるようになる。\n\nこの設定は、マルチプレイヤーロビーでいつでも変更可能だ。" + "SHOULD_RETURN_TO_LOBBY" "マッチ終了後にロビーへ戻る" + "REPLACEMENT_WEAPON" "武器の置き換え" + "TACTICAL_REPLACEMENT" "戦術の置き換え" + "DISALLOWED_TACTICALS" "戦術の禁止" + "DISALLOWED_WEAPONS" "武器の禁止" + "ONLY_HOST_CAN_START_MATCH" "マッチを開始できるのはホストのみ" + "ONLY_HOST_MATCH_SETTINGS" "プライベートマッチの設定を変更できるのはホストのみ" + "AUTHENTICATION_FAILED_HELP" "ヘルプ" + "MATCH_COUNTDOWN_LENGTH" "プライベートマッチのカウントダウン時間" + "ARE_YOU_SURE" "よろしいですか?" + "MOD_SETTINGS_SERVER" "サーバー" + "MOD_SETTINGS_RESET" "リセット" + "MOD_SETTINGS_RESET_ALL" "全てリセット" + "NO_RESULTS" "リザルトなし。" + "MOD_SETTINGS" "Modの設定" + "NORTHSTAR_BASE_SETTINGS" "Northstarの基本設定" + "NO_DISK_SPACE_AVAILABLE" "ディスクに十分な領域がありません。" + "FAILED_DOWNLOADING" "Modのダウンロードに失敗" + "FAILED_READING_ARCHIVE" "Modアーカイブの読込中にエラーが発生しました。" + "DOWNLOADING_MOD_TITLE_W_PROGRESS" "Modをダウンロード中 (%s1%)" + "DOWNLOADING_MOD_TEXT" "ダウンロード中 %s1 v%s2..." + "DOWNLOADING_MOD_TEXT_W_PROGRESS" "ダウンロード中 %s1 v%s2...\n(%s3/%s4 MB)" + "MOD_FETCHING_FAILED" "ThunderstoreからModアーカイブをダウンロードできませんでした。" + "EXTRACTING_MOD_TITLE" "Modを抽出中 (%s1%)" + "EXTRACTING_MOD_TEXT" "抽出中 %s1 v%s2...\n(%s3/%s4 MB)" + "FAILED_WRITING_TO_DISK" "Modファイルをファイルシステムに抽出する際にエラーが発生しました。" + "MOD_FETCHING_FAILED_GENERAL" "Modの抽出に失敗。詳細はログを確認してください。" + "MOD_CORRUPTED" "ダウンロードしたアーカイブのチェックサムが検証済み署名と一致しませんでした。" + "CHECKSUMING_TITLE" "Modをチェックサム中" + "CHECKSUMING_TEXT" "コンテンツを検証中 %s1 v%s2..." + "MOD_DL_DISABLED" "(自動Modダウンロードは無効です)" + "PROGRESSION_TOGGLE_DISABLED_BODY" "タイタン、武器、勢力、スキンなどのアンロックにレベル上げやメリットが必要になる。\n\nこの設定は、マルチプレイヤーロビーでいつでも変更可能だ。\n\n^CC000000警告: 現在装備しているアイテムがロック中の場合、装備状況は初期化されます!" + "PROGRESSION_ENABLED_BODY" "^CCCC0000進行システムが有効化された。^\n\nタイタン、武器、勢力、スキンなどのアンロックにレベル上げやメリットが必要になる。\n\nこの設定は、マルチプレイヤーロビーでいつでも変更可能だ。" + "LOG_UNKNOWN_CLIENTCOMMANDS" "不明なクライアントコマンドを記録する" + "SHOW_ONLY_NOT_REQUIRED" "任意のModのみ" + "AUTHENTICATION_FAILED_ERROR_CODE" "エラーコード: ^DB6F2C00%s1^" + "AUTHENTICATION_FAILED_BODY" "Atlasの認証に失敗しました!\n(Failed to authenticate with Atlas!)" + "MISSING_MOD" "Mod消失 \"%s1\" v%s2" + "MOD_REQUIRED_WARNING" " :このModはサーバーに参加した際に読み込まる(または読み込まれない)ことがあります" + "WILL_RESET_ALL_SETTINGS" "カテゴリー内の全設定をリセットしようとしています。\n\nこの操作は取り消せません。" + "WILL_RESET_SETTING" "%s1 の設定を初期値に戻そうとしています。\n\nこの操作は取り消せません。" + "NO_MODS" "設定が利用できません!Modのインストールはこちらから: ^5588FF00northstar.thunderstore.io^0" + "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000進行システムが開放されました!^\n\nNorthstarはバニラの進行システム、つまり武器、スキン、タイタン等をレベルアップやチャレンジ達成で解除する機能をサポートしています。\n\nこの進行システムは、ロビー画面下のボタンから有効にできます。\n\nこの設定はいつでも変更可能です。" + "MOD_NOT_VERIFIED" "(Modが検証されていないため、自動ダウンロードできませんでした)" + "WRONG_MOD_VERSION" "サーバーはMod\"%s1\"v%s2 を要求していますが、あなたのModバージョンは%s3です" + + // Translation done by Zetryox and CYakigasi } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt b/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt index ea62415e..50d1ef17 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt @@ -82,6 +82,8 @@ Si estas de acuerdo con esto, presiona SI. Esta decision puede ser cambiada en e "cp_amped_capture_points" "Fortalezas amplificadas" "coliseum_loadouts_enabled" "Equipamientos de coliseo" + "aitdm_archer_grunts" "Soldado Archer" + // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "Sandbox" "PL_sbox_lobby" "Lobby sandbox" @@ -274,7 +276,7 @@ Si estas de acuerdo con esto, presiona SI. Esta decision puede ser cambiada en e "PLAYERS_COLUMN" "Jugadores" "MAP_COLUMN" "Mapa" "GAMEMODE_COLUMN" "Modo de juego" - "LATENCY_COLUMN" "Latencia" + "REGION_COLUMN" "Región" "SEARCHBAR_LABEL" "Buscar:" "MAP_FILTER" "Mapa" "GAMEMODE_FILTER" "Modo de juego" @@ -317,5 +319,35 @@ Si estas de acuerdo con esto, presiona SI. Esta decision puede ser cambiada en e "INVALID_MASTERSERVER_TOKEN" "Token de jugador expirado o invalido" "JSON_PARSE_ERROR" "Error procesando respuesta json" "UNSUPPORTED_VERSION" "La versión que estas usando ya no esta soportada" + "SHOW_ONLY_REQUIRED" "Solo Mods requeridos" + "player_force_respawn" "Reaparición Forzada" + "TOGGLE_PROGRESSION" "Alternar Progreso" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "Desactivar Progreso?" + "NO_RESULTS" "No hay resultados." + "NO_MODS" "No hay configuraciones disponibles! Instala mas mods en: ^5588FF00northstar.thunderstore.io^0." + "AUTHENTICATION_FAILED_HEADER" "Verificacion fallida" + "AUTHENTICATION_FAILED_BODY" "Autenticación fallada con Atlas!" + "AUTHENTICATION_FAILED_ERROR_CODE" "Codigo de error: ^DB6F2C00%s1^" + "AUTHENTICATION_FAILED_HELP" "Ayuda" + "WILL_RESET_ALL_SETTINGS" "Esto reiniciará TODAS las configuraciones de categoría\nEsto no es reversible" + "WILL_RESET_SETTING" "Esto revertirá %s1 a la configuracion por defecto. \n \nEsto no es revertible." + "MOD_SETTINGS_SERVER" "Servidor" + "MOD_SETTINGS_RESET" "Reiniciar" + "MOD_SETTINGS_RESET_ALL" "Reiniciar todo" + "MOD_REQUIRED_WARNING" " Este mod puede ser deshabilitado al entrar a un servidor" + "MOD_SETTINGS" "Configuracion de Mods" + "NORTHSTAR_BASE_SETTINGS" "Configuracion base de Northstar" + "ONLY_HOST_MATCH_SETTINGS" "Solo el Host puede cambiar ajustes de partida" + "ONLY_HOST_CAN_START_MATCH" "Solo el host puede iniciar la partida" + "MATCH_COUNTDOWN_LENGTH" "Cuenta Atrás de partida privada" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Registro desconocido de comandos de cliente" + "DISALLOWED_TACTICALS" "Tactica Prohibida" + "TACTICAL_REPLACEMENT" "Reemplazo de Tactica" + "DISALLOWED_WEAPONS" "Arma Prohibida" + "REPLACEMENT_WEAPON" "Arma de Reemplazo" + "SHOULD_RETURN_TO_LOBBY" "Volver al lobby al finalizar partida" + "ARE_YOU_SURE" "Seguro?" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Alternar Progreso" + "SHOW_ONLY_NOT_REQUIRED" "Solo Mods Opcionales" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_portuguese.txt b/Northstar.Client/mod/resource/northstar_client_localisation_portuguese.txt index d398e557..75a5faad 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_portuguese.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_portuguese.txt @@ -15,14 +15,14 @@ "DIALOG_TITLE_INSTALLED_NORTHSTAR" "Obrigado por instalar Northstar!" "AUTHENTICATION_AGREEMENT_DIALOG_TEXT" "Para o Northstar funcionar é necessário autenticar com o servidor mestre Northstar. Isso requer enviar seu token da Origin para o servidor, ele não será utilizado pra outros propósitos. Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momento no menu de mods." - "BACK_AUTHENTICATION_AGREEMENT" "Aceitação de autorização" - "AUTHENTICATION_AGREEMENT" "Aceitação de autorização" + "BACK_AUTHENTICATION_AGREEMENT" "Acordo de Autenticação" + "AUTHENTICATION_AGREEMENT" "Acordo de Autenticação" "AUTHENTICATION_AGREEMENT_RESTART" "Você precisa reiniciar o Titanfall 2 para esta mudança ter efeito." "DIALOG_AUTHENTICATING_MASTERSERVER" "Autenticando com o servidor mestre." - "AUTHENTICATIONAGREEMENT_NO" "Você não autorizou a autenticação com Northstar. Troque a configuração no menu de mods." + "AUTHENTICATIONAGREEMENT_NO" "Você escolheu não autenticar com Northstar. Você pode ver o acordo no menu de Mods." - "MENU_TITLE_SERVER_BROWSER" "Servidores" + "MENU_TITLE_SERVER_BROWSER" "Lista de Servidores" "NS_SERVERBROWSER_NOSERVERS" "Nenhum servidor encontrado" "NS_SERVERBROWSER_UNKNOWNMODE" "Modo desconhecido" "NS_SERVERBROWSER_WAITINGFORSERVERS" "Aguardando servidores..." @@ -52,9 +52,9 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "classic_mp" "MP Clássico" "run_epilogue" "Executar epílogo" "scorelimit" "Limite de pontos" - "roundscorelimit" "Limite de pontos (por round)" + "roundscorelimit" "Limite de pontos (por rodada)" "timelimit" "Tempo limite" - "roundtimelimit" "Tempo limite (por round)" + "roundtimelimit" "Tempo limite (por rodada)" "respawnprotection" "Proteção de reaparecimento" "pilot_health_multiplier" "Multiplicador de vida" @@ -64,16 +64,16 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "earn_meter_pilot_multiplier" "Multiplicador de bônus" "earn_meter_titan_multiplier" "Multiplicador de bônus do titã" - "aegis_upgrades" "Upgrades Aegis" + "aegis_upgrades" "Melhorias de Égide" "infinite_doomed_state" "Estado condenado infinito" "titan_shield_regen" "Escudos regeneradores" - "riff_floorislava" "Deadly Ground" - "featured_mode_all_holopilot" "The Great Bamboozle" - "featured_mode_all_grapple" "Attack on Titanfall" - "featured_mode_all_phase" "The Otherside" - "featured_mode_all_ticks" "Spicy" - "featured_mode_tactikill" "Tactikill" + "riff_floorislava" "Terreno Mortal" + "featured_mode_all_holopilot" "A Grande Enganação" + "featured_mode_all_grapple" "Ataque aos Titãs" + "featured_mode_all_phase" "O Outro Lado" + "featured_mode_all_ticks" "Picante" + "featured_mode_tactikill" "Mortático" "featured_mode_amped_tacticals" "Habilidades táticas melhoradas" "featured_mode_rocket_arena" "Arena Foguete" "featured_mode_shotguns_snipers" "Armado e perigoso" @@ -89,14 +89,14 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "PL_sbox_abbr" "SBOX" "GAMEMODE_SBOX" "Sandbox" - "PL_gg" "Gun Game" - "PL_gg_lobby" "Saguão de Gun Game" - "PL_gg_desc" "Mate com todas as armas para vencer" - "PL_gg_hint" "Mate com todas as armas para vencer" + "PL_gg" "Jogo de Armas" + "PL_gg_lobby" "Saguão de Jogo de Armas" + "PL_gg_desc" "Mate com cada arma para vencer." + "PL_gg_hint" "Mate com cada arma para vencer." "PL_gg_abbr" "GG" - "GAMEMODE_GG" "Gun Game" + "GAMEMODE_GG" "Jogo de Armas" "gg_kill_reward" "% recompensa/morte" - "gg_assist_reward" "% recompensa/assist" + "gg_assist_reward" "% recompensa/assistência" "gg_execution_reward" "% recompensa/execução" "PL_tt" "Titan Tag" @@ -106,20 +106,20 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "PL_tt_abbr" "TT" "GAMEMODE_TT" "Titan Tag" - "PL_chamber" "One in the Chamber" - "PL_chamber_lobby" "Saguão de One in the Chamber" - "PL_chamber_desc" "Um tiro, uma morte. Ganhe outra munição ao abater um inimigo." - "PL_chamber_hint" "Um tiro, uma morte. Ganhe outra munição ao abater um inimigo." - "PL_chamber_abbr" "CHAMBER" - "GAMEMODE_CHAMBER" "One in the Chamber" + "PL_chamber" "Um na Câmara" + "PL_chamber_lobby" "Saguão de Um na Câmara" + "PL_chamber_desc" "Um tiro, uma morte. Ganhe uma bala no pente ao abater um inimigo." + "PL_chamber_hint" "Um tiro, uma morte. Ganhe uma bala no pente ao abater um inimigo." + "PL_chamber_abbr" "CÂMARA" + "GAMEMODE_CHAMBER" "Um na Câmara" - "PL_hidden" "O Fantasma" - "PL_hidden_lobby" "Saguão de O Fantasma" + "PL_hidden" "O Oculto" + "PL_hidden_lobby" "Saguão de O Oculto" "PL_hidden_desc" "Um jogador se torna invisível enquanto o resto o caça." "PL_hidden_hint" "Um jogador se torna invisível enquanto o resto o caça." "PL_hidden_abbr" "HIDDEN" - "GAMEMODE_HIDDEN" "The Hidden" - "HIDDEN_YOU_ARE_HIDDEN" "Você é o fantasma!" + "GAMEMODE_HIDDEN" "O Oculto" + "HIDDEN_YOU_ARE_HIDDEN" "Você é o ocultado!" "HIDDEN_KILL_SURVIVORS" "Mate todos os sobreviventes." "HIDDEN_FIRST_HIDDEN" "%s1 é O Fantasma." @@ -155,12 +155,12 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "INFECTION_YOU_ARE_LAST_SURVIVOR" "Você é o último sobrevivente!" "INFECTION_SURVIVE_LAST_SURVIVOR" "Sobreviva." - "PL_tffa" "Free for All Titã" - "PL_tffa_lobby" "Saguão de Free for All Titã" + "PL_tffa" "Cada Titã por si" + "PL_tffa_lobby" "Saguão de Cada Titã por si" "PL_tffa_desc" "Cada um por si, destrua todos os titãs inimigos." "PL_tffa_hint" "Cada um por si, destrua todos os titãs inimigos." "PL_tffa_abbr" "TFFA" - "GAMEMODE_TFFA" "Free for All Titã" + "GAMEMODE_TFFA" "Cada Titã por si" "PL_hs" "Esconde-esconde" "PL_hs_lobby" "Saguão de Esconde-esconde" @@ -168,7 +168,7 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "PL_hs_hint" "Jogo clássico de esconde-esconde." "PL_hs_abbr" "HS" "GAMEMODE_hs" "Esconde-esconde" - "HIDEANDSEEK_YOU_ARE_SEEKER" "VOCÊ PEGA!" + "HIDEANDSEEK_YOU_ARE_SEEKER" "VOCÊ PEGA" "HIDEANDSEEK_SEEKER_DESC" "Ache os outros e bata neles.\nVocê reaparecerá em %s1 segundos" "HIDEANDSEEK_YOU_ARE_HIDER" "VOCÊ ESCONDE" "HIDEANDSEEK_HIDER_DESC" "Esconda-se." @@ -203,8 +203,8 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "KR_YOUR_KILLRACE_OVER" "Sua matança acabou" "KR_YOUR_KILLRACE_SCORE" "Você conseguiu %s1 mortes." - "GAMEMODE_fastball" "Fastball" - "PL_fastball" "Fastball" + "GAMEMODE_fastball" "Travessia Impulsionada" + "PL_fastball" "Travessia Impulsionada" "PL_fastball_lobby" "Saguão de Fastball" "PL_fastball_desc" "Sem reaparecimento. Invada painéis de controle para ganhar rounds e reaparecer seus aliados." "PL_fastball_hint" "Sem reaparecimento. Invada painéis de controle para ganhar rounds e reaparecer seus aliados." @@ -236,8 +236,8 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "player_bleedout_aiBleedingPlayerMissChance" "Chance de erro da IA ao cair" // coop stuff - "PL_sp_coop" "(UNFINISHED) Singleplayer Coop" - "PL_sp_coop_lobby" "Saguão de Singleplayer em grupo" + "PL_sp_coop" "(NÃO-TERMINADO) Campanha Cooperativa" + "PL_sp_coop_lobby" "Saguão de Campanha Cooperativa" "PL_sp_coop_desc" "Jogue através da campanha com seus amigos" "PL_sp_coop_hint" "Jogue através da campanha com seus amigos" "PL_sp_coop_abbr" "SP" @@ -274,7 +274,7 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen "PLAYERS_COLUMN" "Jogadores" "MAP_COLUMN" "Mapa" "GAMEMODE_COLUMN" "Modo" - "LATENCY_COLUMN" "Latência" + "REGION_COLUMN" "Região" "SEARCHBAR_LABEL" "Buscar:" "MAP_FILTER" "Mapa" "GAMEMODE_FILTER" "Modo" @@ -306,5 +306,75 @@ Clique em Sim se você concorda. Esta escolha pode ser alterada a qualquer momen // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + "ONLY_HOST_MATCH_SETTINGS" "Somente o Host pode mudar as configurações da Partida Privada" + "ONLY_HOST_CAN_START_MATCH" "Somente o Host pode Iniciar a Partida" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Registrar Comandos desconhecidos de Clientes" + "DISALLOWED_TACTICALS" "Táticos Proibidos" + "TACTICAL_REPLACEMENT" "Tático Substituto" + "DISALLOWED_WEAPONS" "Armas Proibidas" + "REPLACEMENT_WEAPON" "Armas Substitutas" + "ARE_YOU_SURE" "Tem certeza?" + "WILL_RESET_ALL_SETTINGS" "Isso irá resetar TODAS as configurações que pertecem a essa categoria.\n\nAção não reversível." + "MOD_SETTINGS_SERVER" "Servidor" + "MOD_SETTINGS_RESET" "Resetar" + "MOD_SETTINGS_RESET_ALL" "Resetar Tudo" + "NO_RESULTS" "Sem resultados." + "NO_MODS" "Sem configurações disponíveis. Instale mais mods em ^5588FF00northstar.thunderstore.io^0." + "SHOW_ONLY_NOT_REQUIRED" "Somente Mods Opcionais" + "NO_GAMESERVER_RESPONSE" "Não foi possível alcançar o servidor da partida" + "BAD_GAMESERVER_RESPONSE" "Servidor da partida sem resposta válida" + "UNAUTHORIZED_GAMESERVER" "Servidor da partida não está autorizado a fazer tal requisição" + "UNAUTHORIZED_PWD" "Senha inválida" + "PLAYER_NOT_FOUND" "Não foi possível encontrar conta do jogador" + "INVALID_MASTERSERVER_TOKEN" "Token do servidor mestre inválido ou vencido, tente reiniciar o EA App." + "JSON_PARSE_ERROR" "Erro ao ler a resposta json" + "SHOW_ONLY_REQUIRED" "Somente Mods Mandatórios" + "UNAUTHORIZED_GAME" "Stryder não pode confirmar que esta conta possui Titanfall 2" + "STRYDER_RESPONSE" "Não foi possível ler a resposta do Stryder" + "UNSUPPORTED_VERSION" "A versão que você está usando não é mais suportada" + "MOD_SETTINGS" "Configurações de Mod" + "NORTHSTAR_BASE_SETTINGS" "Configurações Base do Northstar" + "MATCH_COUNTDOWN_LENGTH" "Duração da contagem da Partida Privada" + "SHOULD_RETURN_TO_LOBBY" "Retornar ao saguão após término de Partida" + "WILL_RESET_SETTING" "Isso irá resetar a configuração %s1 ao valor padrão.\n\nAção não reversível." + "aitdm_archer_grunts" "Soldados com Archer" + "player_force_respawn" "Resurgimento Forçado" + "PROGRESSION_ENABLED_HEADER" "Progressão Habilitada!" + "PROGRESSION_ENABLED_BODY" "^CCCC0000Progressão foi habilitada.^\n\nTitãs, Armas, Facções, Cosméticos, etc. serão destravados ao ganhar níveis, ou comprados com Méritos.\n\nIsso pode ser alterado a qualquer momento no menu de multijogador." + "PROGRESSION_DISABLED_HEADER" "Progressão Desabilitada!" + "TOGGLE_PROGRESSION" "Habilitar Progressão" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "Desabilitar Progressão?" + "PROGRESSION_TOGGLE_ENABLED_BODY" "Titãs, Armas, Facções, Cosméticos etc. serão todos destravados e usáveis a qualquer momento.\n\nIsso pode ser alterado a qualquer hora no menu de multijogador." + "PROGRESSION_TOGGLE_DISABLED_HEADER" "Habilitar Progressão?" + "PROGRESSION_TOGGLE_DISABLED_BODY" "Titãs, Armas, Facções, Cosméticos, etc. terão que ser destravados ao ganhar níveis, ou comprados com Méritos.\n\nIsso pode ser alterado a qualquer momento no menu de multijogador.\n\n^CC000000Aviso: Se você atualmente tem qualquer item equipado que não foi préviamente destravado, ele será resetado!" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Alternar Progressão" + "DOWNLOADING_MOD_TITLE_W_PROGRESS" "Baixando mod (%s1%)" + "DOWNLOADING_MOD_TEXT" "Baixando %s1 v%s2..." + "MISSING_MOD" "Mod em falta \"%s1\" v%s2" + "MOD_NOT_VERIFIED" "(o mod não é verificado, e não pode ser baixado automaticamente)" + "MOD_DL_DISABLED" "(download automático de mod está desabilitado)" + "DOWNLOADING_MOD_TITLE" "Baixando mod" + "DOWNLOADING_MOD_TEXT_W_PROGRESS" "Baixando %s1 v%s2...\n(%s3/%s4 MB)" + "CHECKSUMING_TITLE" "Verificando o mod" + "CHECKSUMING_TEXT" "Verificando conteúdo de %s1 v%s2..." + "EXTRACTING_MOD_TITLE" "Extraíndo mod (%s1%)" + "MOD_REQUIRED_WARNING" " Este mod pode ser desativado quando entrar em um servidor" + "AUTHENTICATION_FAILED_HEADER" "Autenticação Falhou" + "AUTHENTICATION_FAILED_BODY" "Falha ao autenticar com Atlas!" + "AUTHENTICATION_FAILED_ERROR_CODE" "Código de Erro: ^DB6F2C00%s1^" + "AUTHENTICATION_FAILED_HELP" "Ajuda" + "EXTRACTING_MOD_TEXT" "Extraíndo %s1 v%s2...\n(%s3/%s4 MB)" + "FAILED_DOWNLOADING" "Falha ao baixar mod" + "FAILED_READING_ARCHIVE" "Um erro ocorreu ao ler o aqruivo do mod." + "MOD_FETCHING_FAILED" "O arquivo do mod não pode ser baixado da Thunderstore." + "MOD_CORRUPTED" "O aquivo baixado não condiz com a assinatura de verificação registrada." + "NO_DISK_SPACE_AVAILABLE" "Não há espaço suficiente no disco." + "PROGRESSION_DISABLED_BODY" "^CCCC0000Progressão foi desabilitada.^\n\nTitãs, Facções, Armas, Cosméticos, etc. estarão disponíveis para uso a qualquer momento.\n\nIsso pode ser alterado a qualquer hora no menu de multijogador." + "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000Progressão agora pode ser habilitada!^\n\nNorthstar agora suporta a progressão original, o que significa que você pode optar por destravar Armas, Cosméticos, Titãs e outros através do ganho de níveis e completando os desafios.\n\nVocê pode habilitar a progressão usando o botão no rodapé do menu de multijogador.\n\nIsso pode ser alterado a qualquer momento." + "WRONG_MOD_VERSION" "O servidor tem o mod \"%s1\" v%s2 enquanto você possui v%s3" + "FAILED_WRITING_TO_DISK" "Um erro ocorreu enquanto se extraía o conteúdo do mod para o sistema." + "MOD_FETCHING_FAILED_GENERAL" "Extração do mod falhou. Verifique os logs para mais detalhes." + "MANIFESTO_FETCHING_TEXT" "Retornando a lista de mods verificados..." + "MANIFESTO_FETCHING_TITLE" "Preparando o download do mod" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt index af9eb0ff..91a0dede 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt @@ -17,7 +17,7 @@ "MENU_TITLE_SERVER_BROWSER" "Список серверов" "NS_SERVERBROWSER_NOSERVERS" "Серверов не найдено" "NS_SERVERBROWSER_WAITINGFORSERVERS" "Ожидание серверов..." - "NS_SERVERBROWSER_CONNECTIONFAILED" "Соединение провалено!" + "NS_SERVERBROWSER_CONNECTIONFAILED" "Не удалось подключиться!" "REFRESH_SERVERS" "Обновить" "MENU_TITLE_CONNECT_PASSWORD" "Подключиться с помощью пароля" @@ -41,7 +41,7 @@ "MODE_SETTING_CATEGORY_MATCH" "Матч" "classic_mp" "Классический мультиплеер" - "run_epilogue" "Запустить эпилог" + "run_epilogue" "Показывать эпилог" "scorelimit" "Лимит очков" "roundscorelimit" "Лимит очков (по раундам)" "timelimit" "Лимит времени" @@ -58,19 +58,19 @@ "infinite_doomed_state" "Бесконечное обречённое состояние" "titan_shield_regen" "Регенерация щитов" - "riff_floorislava" "Смертельная Земля" + "riff_floorislava" "Пол это лава" "featured_mode_all_holopilot" "Великий обманщик" - "featured_mode_all_grapple" "Зацепщик" - "featured_mode_all_phase" "Альтернативное пространство" - "featured_mode_all_ticks" "Острый" + "featured_mode_all_grapple" "Зацепер" + "featured_mode_all_phase" "Мир иной" + "featured_mode_all_ticks" "Крутые перцы" "featured_mode_tactikill" "Тактический удар" "featured_mode_amped_tacticals" "Усиленные тактики" "featured_mode_rocket_arena" "Ракетная Арена" "featured_mode_shotguns_snipers" "Вооружён и опасен" "iron_rules" "Правила Железного Титана" - "cp_amped_capture_points" "Усиленные точки опоры" - "coliseum_loadouts_enabled" "Выгрузка коллизея" + "cp_amped_capture_points" "Усиленные опорные пункты" + "coliseum_loadouts_enabled" "Экипировка Колизея" // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "Песочница" @@ -81,9 +81,9 @@ "PL_gg" "Гонка вооружений" "PL_gg_lobby" "Лобби гонки вооружений" - "PL_gg_desc" "Уничтожьте противника из всех видов оружия чтобы победить." - "PL_gg_hint" "Уничтожьте противника из всех видов оружия чтобы победить." - "PL_gg_abbr" "GG" + "PL_gg_desc" "Убейте по одному противнику из каждого вида оружия." + "PL_gg_hint" "Убейте по одному противнику из каждого вида оружия." + "PL_gg_abbr" "ГВ" "GAMEMODE_GG" "Гонка вооружений" "PL_tt" "Разборки Титанов" @@ -99,10 +99,10 @@ "PL_inf_hint" "Переживите инфекцию. Выжившие становятся заражёнными при убийстве." "PL_inf_abbr" "INF" "GAMEMODE_INF" "Заражение" - "INFECTION_YOU_ARE_INFECTED" "Вы были заражены!" + "INFECTION_YOU_ARE_INFECTED" "Вас заразили!" "INFECTION_KILL_SURVIVORS" "Заразите всех оставшихся выживших." "INFECTION_FIRST_INFECTED" "%s1 был заражён первым." - "INFECTION_LAST_SURVIVOR" "%s1 выжил последним!" + "INFECTION_LAST_SURVIVOR" "%s1 — последний выживший!" "INFECTION_KILL_LAST_SURVIVOR" "Зарази их, пока время не вышло!" "INFECTION_YOU_ARE_LAST_SURVIVOR" "Вы последний выживший!" "INFECTION_SURVIVE_LAST_SURVIVOR" "Выживите." @@ -116,19 +116,19 @@ "HIDEANDSEEK_YOU_ARE_SEEKER" "ВЫ ИЩЕТЕ" "HIDEANDSEEK_SEEKER_DESC" "Найдите прячущихся и ударьте их.\nВы появитесь через %s1 секунд(у)" "HIDEANDSEEK_YOU_ARE_HIDER" "ВЫ ПРЯЧЕТЕСЬ" - "HIDEANDSEEK_HIDER_DESC" "Спрятайтесь." + "HIDEANDSEEK_HIDER_DESC" "Спрячьтесь." "HIDEANDSEEK_SEEKERS_INCOMING" "ИЩУЩИЕ ВЫДВИГАЮТСЯ" "HIDEANDSEEK_DONT_GET_FOUND" "Не дайте себя найти!" "HIDEANDSEEK_GET_LAST_HIDER" "%s1 ПОСЛЕДНИЙ СПРЯТАВШИЙСЯ" "HIDEANDSEEK_YOU_ARE_LAST_HIDER" "ВЫ ПОСЛЕДНИЙ СПРЯТАВШИЙСЯ" - "HIDEANDSEEK_GOT_STIM" "Вас остановили! Не попадитесь!" + "HIDEANDSEEK_GOT_STIM" "Применён стим! Не попадитесь!" "hideandseek_balance_teams" "Автобаланс обеих сторон" "hideandseek_hiding_time" "Время спрятаться" // these are defined in r1_english but titan war is a shit name so i'm changing it to another one that was referenced in development - "GAMEMODE_fw" "Пограничная война" - "PL_fw" "Пограничная война" - "PL_fw_lobby" "Лобби пограничной войны" + "GAMEMODE_fw" "Война за Фронтир" + "PL_fw" "Война за Фронтир" + "PL_fw_lobby" "Лобби Войны за Фронтир" "PL_fw_desc" "Уничтожьте харвестер противника и защитите свой" "PL_fw_abbr" "FW" @@ -136,22 +136,22 @@ "PL_kr" "Усиленные гонки убийств" "PL_kr_lobby" "Лобби усиленных гонок убийств" - "PL_kr_desc" "Получайте убийства, чтобы увеличить продолжительность вашей гонки за убийствами. Соберите флаг, чтобы начать его. Установите рекорд убийств, чтобы победить." - "PL_kr_hint" "Получайте убийства, чтобы увеличить продолжительность вашей гонки за убийствами. Соберите флаг, чтобы начать его. Установите рекорд убийств, чтобы победить." + "PL_kr_desc" "Получайте убийства, чтобы увеличить продолжительность вашей гонки за убийствами. Соберите флаг, чтобы начать её. Установите рекорд убийств, чтобы победить." + "PL_kr_hint" "Получайте убийства, чтобы увеличить продолжительность вашей гонки за убийствами. Соберите флаг, чтобы начать её. Установите рекорд убийств, чтобы победить." "PL_kr_abbr" "KR" "SCOREBOARD_KR_RECORD" "Рекорд убийств" "KR_NEW_RACER" "%s1 усиленный гонщик за убийства" "KR_YOU_ARE_NEW_RACER" "Вы усиленный гонщик за убийства" "KR_YOU_SET_NEW_RECORD" "Установите новый рекорд убийств!" "KR_FLAG_INCOMING" "Флаг прибывает" - "KR_COLLECT_FLAG" "Возьмите его чтобы стать гонщиком за убиства!" + "KR_COLLECT_FLAG" "Возьмите его чтобы стать гонщиком за убийства!" "KR_ENEMY_KILLRACE_OVER" "Гонки убийств у %s1 закончились" "KR_YOUR_KILLRACE_OVER" "Ваши гонки убийств кончились" "KR_YOUR_KILLRACE_SCORE" "У вас %s1 убийств." - "GAMEMODE_fastball" "Фастболл" - "PL_fastball" "Фастболл" - "PL_fastball_lobby" "Лобби фастболла" + "GAMEMODE_fastball" "Фастбол" + "PL_fastball" "Фастбол" + "PL_fastball_lobby" "Лобби фастбола" "PL_fastball_desc" "Перманентная смерть. Взломайте панели управления чтобы побеждать в раундах и возродить своих членов команды." "PL_fastball_hint" "Перманентная смерть. Взломайте панели управления чтобы побеждать в раундах и возродить своих членов команды." "PL_fastball_abbr" "FB" @@ -161,20 +161,20 @@ "GAMEMODE_ctf_comp" "Соревновательное CTF" // mode settings - "MODE_SETTING_CATEGORY_PROMODE" "Продвинутое оружие" + "MODE_SETTING_CATEGORY_PROMODE" "Режим про" "MODE_SETTING_CATEGORY_BLEEDOUT" "Кровотечение пилота" "custom_air_accel_pilot" "Ускорение в воздухе" - "promode_enable" "Продвинутое оружие" - "fp_embark_enabled" "Отправления/Казни от первого лица" + "promode_enable" "Оружие из режима про" + "fp_embark_enabled" "Казни/посадки в титана от первого лица" "classic_rodeo" "Классическое родео" "oob_timer_enabled" "Таймер уничтожения за пределами карты" "riff_instagib" "Моментальная смерть при попадании" "riff_player_bleedout" "Кровотечение пилота" - "player_bleedout_forceHolster" "Использовать оружие из кобуры при кровотечении" + "player_bleedout_forceHolster" "Убирать оружие при кровотечении" "player_bleedout_forceDeathOnTeamBleedout" "Смерть при кровотечении во всей команде" - "player_bleedout_bleedoutTime" "Кремя кровотечения" + "player_bleedout_bleedoutTime" "Время кровотечения" "player_bleedout_firstAidTime" "Время оказания первой помощи" "player_bleedout_firstAidTimeSelf" "Время оказания помощи самому себе" "player_bleedout_firstAidHealPercent" "Процент здоровья после лечения" @@ -187,8 +187,8 @@ "PL_sp_coop_hint" "Сыграть в кампанию с друзьями" "PL_sp_coop_abbr" "SP" - "SP_TRAINING" "Тренировачная полоса пилотов" - "SP_TRAINING_CLASSIC_DESC" "Тренировачная имитация капитана Ластимозы." + "SP_TRAINING" "Полоса препятствий" + "SP_TRAINING_CLASSIC_DESC" "Симуляция капитана Ластимозы." "SP_CRASHSITE" "БT-7274" "SP_CRASHSITE_CLASSIC_DESC" "Джек Купер встречает BT-7274." @@ -200,7 +200,7 @@ "SP_BOOMTOWN_START_CLASSIC_DESC" "Подземная срезка приводит к неожиданным последствиям." "SP_HUB_TIMESHIFT" "Следствие и Причина" - "SP_HUB_TIMESHIFT_CLASSIC_DESC" "Странный феномен был обнаружен на местополжении Майора Андерсена." + "SP_HUB_TIMESHIFT_CLASSIC_DESC" "Странный феномен был обнаружен на местоположении Майора Андерсена." "SP_BEACON" "Маяк" "SP_BEACON_CLASSIC_DESC" "Купер и БТ пытаются известить оставшийся флот о планах IMC." @@ -211,7 +211,7 @@ "SP_S2S" "Ковчег" "SP_S2S_CLASSIC_DESC" "Купер и БТ перемещаются по кораблям, преследуя Ковчег." - "SP_SKYWAY_V1" "Сложенное оружие" + "SP_SKYWAY_V1" "Искажающее орудие" "SP_SKYWAY_V1_CLASSIC_DESC" "БT и Купер были захвачены Кубеном Блиском." // Better.Serverbrowser @@ -219,7 +219,7 @@ "PLAYERS_COLUMN" "Игроки" "MAP_COLUMN" "Карта" "GAMEMODE_COLUMN" "Режим игры" - "LATENCY_COLUMN" "Задержка" + "REGION_COLUMN" "Регион" "SEARCHBAR_LABEL" "Поиск:" "MAP_FILTER" "Карта" "GAMEMODE_FILTER" "Режим игры" @@ -229,7 +229,7 @@ "SERVER_DESCRIPTION" "Описание" "SERVER_MODS" "Моды" "CLEAR_FILTERS" "ОЧИСТИТЬ" - "JOIN_BUTTON" "ПРИСОЕДИНИТЬСЯ" + "JOIN_BUTTON" "ЗАЙТИ" "SWITCH_YES" "Да" "SWITCH_NO" "Нет" @@ -240,18 +240,132 @@ "TOTAL_SERVERS" "Серверов: ^C46C6C00%s1" // In-game chat - "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" - "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + "HUD_CHAT_WHISPER_PREFIX" "[ЛИЧНОЕ]" + "HUD_CHAT_SERVER_PREFIX" "[СЕРВЕР]" "NO_GAMESERVER_RESPONSE" "Игровой сервер не отвечает" - "BAD_GAMESERVER_RESPONSE" "Игровой сервер не дал правильного ответа" + "BAD_GAMESERVER_RESPONSE" "Игровой сервер вернул некорректный ответ" "UNAUTHORIZED_GAMESERVER" "Игровой сервер не авторизирован чтобы сделать данный запрос" - "UNAUTHORIZED_GAME" "Не удалось найти Titanfall 2 на этом аккаунте" + "UNAUTHORIZED_GAME" "Stryder не смог найти Titanfall 2 на этом аккаунте" "UNAUTHORIZED_PWD" "Неправильный пароль" - "STRYDER_RESPONSE" "Не удалось разобрать ответ stryder" + "STRYDER_RESPONSE" "Не удалось разобрать ответ Stryder" "PLAYER_NOT_FOUND" "Не удалось найти аккаунт игрока" - "INVALID_MASTERSERVER_TOKEN" "Срок действия жетона главного сервера истек или не является правильным" - "JSON_PARSE_ERROR" "Ошибка разбора ответа json" + "INVALID_MASTERSERVER_TOKEN" "Некорректный или истёкший токен главного сервера. Перезапустите EA App, чтобы обновить токен." + "JSON_PARSE_ERROR" "Ошибка разбора json-ответа" "UNSUPPORTED_VERSION" "Используемая вами версия больше не поддерживается" + "DISABLE" "Выключить" + "DIALOG_AUTHENTICATING_MASTERSERVER" "Аутентификация на главном сервере." + "WARNING" "Предупреждение" + "CORE_MOD_DISABLE_WARNING" "Выключение основных модов может сломать ваш клиент!" + "AUTHENTICATIONAGREEMENT_NO" "Вы выбрали не аутентифицироваться с Northstar-ом. Вы можете посмотреть соглашение в меню модов." + "NS_SERVERBROWSER_UNKNOWNMODE" "Неизвестный режим" + "SNS_BANKRUPT" "Банкрот!" + "MOD_SETTINGS" "Настройки модов" + "NORTHSTAR_BASE_SETTINGS" "Основные настройки Northstar" + "ONLY_HOST_MATCH_SETTINGS" "Только создатель матча может изменять настройки" + "ONLY_HOST_CAN_START_MATCH" "Только создатель матча может его начать" + "MATCH_COUNTDOWN_LENGTH" "Длительность обратного отсчёта частного матча" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Записывать в лог неизвестные команды" + "DISALLOWED_TACTICALS" "Запрещённое спецоружие" + "TACTICAL_REPLACEMENT" "Заменять запрещённое спецоружие на" + "DISALLOWED_WEAPONS" "Запрещённое оружие" + "REPLACEMENT_WEAPON" "Заменять запрещённое оружие на" + "SHOULD_RETURN_TO_LOBBY" "Возвращаться в лобби после матча" + "ARE_YOU_SURE" "Вы уверены?" + "WILL_RESET_ALL_SETTINGS" "ВСЕ настройки этой категории будут сброшены.\n\nЭто действие нельзя будет откатить." + "WILL_RESET_SETTING" "Это сбросит значение настройки %s1.\n\nЭто действие нельзя будет откатить." + "MOD_SETTINGS_SERVER" "Сервер" + "MOD_SETTINGS_RESET" "Сброс" + "MOD_SETTINGS_RESET_ALL" "Сбросить все" + "NO_RESULTS" "Нет результатов." + "NO_MODS" "Нечего настраивать! Загрузите моды с ^5588FF00northstar.thunderstore.io^0." + "respawnprotection" "Длит. защиты после возрождения" + "SNS_BANKRUPT_SUB" "Вас обнулил %s1" + "PL_hidden" "Невидимка" + "PL_hidden_lobby" "Невидимка — лобби" + "GAMEMODE_HIDDEN" "Невидимка" + "HIDDEN_YOU_ARE_HIDDEN" "Вы — Невидимка!" + "HIDDEN_KILL_SURVIVORS" "Убейте всех." + "aitdm_archer_grunts" "Пехотинцы со Стрельцами" + "PL_chamber" "Последний патрон" + "PL_chamber_lobby" "Последний патрон — лобби" + "PL_chamber_abbr" "ПАТРОН" + "GAMEMODE_CHAMBER" "Последний патрон" + "PL_sns" "Камни и палки" + "PL_sns_lobby" "Камни и палки — лобби" + "PL_sns_desc" "Все против всех. Убийства пульс. клинком и казни сбрасывают очки противника" + "PL_sns_abbr" "КИП" + "GAMEMODE_SNS" "Камни и палки" + "PL_hidden_hint" "Один из игроков невидим." + "PL_hidden_abbr" "НЕВИД" + "SCOREBOARD_BANKRUPTS" "Врагов обанкрочено" + "SNS_LEADER_BANKRUPT" "Лидер обанкрочен!" + "SNS_LEADER_BANKRUPT_SUB" "%s1 был обнулён игроком %s2" + "gg_kill_reward" "Множитель награды за убийство" + "gg_execution_reward" "Множитель награды за казнь" + "PL_tffa" "Все против всех на титанах" + "PL_tffa_lobby" "Все против всех на титанах — лобби" + "PL_tffa_desc" "Каждый пилот сам за себя. Уничтожьте всех вражеских титанов." + "PL_tffa_abbr" "ТВПВ" + "sns_wme_kill_value" "Очков за убийство Элитным ведомым" + "sns_offhand_kill_value" "Очков за убийство спецоружием" + "sns_reset_kill_value" "Очков за убийство пульс./казнь" + "sns_melee_kill_value" "Очков за убийство врукопашную" + "sns_softball_enabled" "Включить Софтбол" + "no_pilot_collision" "Столкновения между пилотами" + "SHOW" "Показать" + "SHOW_ALL" "Все" + "SHOW_ONLY_ENABLED" "Только включенные" + "SHOW_ONLY_NOT_REQUIRED" "Только необязательные" + "SHOW_ONLY_REQUIRED" "Только обязательные" + "HIDDEN_FIRST_HIDDEN" "%s1 — Невидимка." + "GAMEMODE_TFFA" "Все против всех на титанах" + "SHOW_ONLY_DISABLED" "Только выключенные" + "HIDE_LOCKED" "Скрыть недоступные" + "PL_chamber_desc" "Один выстрел — один труп. Заработайте ещё один патрон, убив врага первым." + "PL_chamber_hint" "Один выстрел — один труп. Заработайте ещё один патрон, убив врага первым." + "PL_hidden_desc" "Один из игроков невидим." + "PL_tffa_hint" "Каждый пилот сам за себя. Уничтожьте всех вражеских титанов." + "sns_softball_kill_value" "Очков за убийство Софтболом" + "sns_reset_pulse_blade_cooldown_on_pulse_blade_kill" "Сброс перезарядки пульс. клинка при убийстве им" + "gg_assist_reward" "Множитель награды за помощь в убийстве" + "TOGGLE_PROGRESSION" "Вкл/выкл прогресс" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% Вкл/выкл прогресс" + "PROGRESSION_TOGGLE_DISABLED_HEADER" "Включить прогресс?" + "PROGRESSION_ENABLED_HEADER" "Прогресс включён!" + "PROGRESSION_ENABLED_BODY" "^CCCC0000Прогресс включён.^\n\nНедоступных титанов, оружие, фракции, раскраски, и т.п. теперь нужно разблокировать, или купить за Заслуги.\n\nЭту настройку всегда можно изменить в лобби сетевой игры." + "PROGRESSION_DISABLED_HEADER" "Прогресс выключен!" + "PROGRESSION_DISABLED_BODY" "^CCCC0000Прогресс выключен.^\n\nВсе титаны, оружие, фракции, раскраски, и т.п. теперь доступны.\n\nЭту настройку всегда можно изменить в лобби сетевой игры." + "player_force_respawn" "Принудительное возрождение" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "Отключить прогресс?" + "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" "Ошибка аутентификации" + "MISSING_MOD" "Отсутствует мод \"%s1\" v%s2" + "MOD_NOT_VERIFIED" "(мод не был загружен автоматически, т.к. он не проверенный)" + "MOD_DL_DISABLED" "(автоматическая загрузка модов не включена)" + "DOWNLOADING_MOD_TITLE" "Загрузка мода" + "DOWNLOADING_MOD_TEXT" "Загружаем %s1 v%s2..." + "DOWNLOADING_MOD_TEXT_W_PROGRESS" "Загружаем %s1 v%s2...\n(%s3/%s4 МБ)" + "DOWNLOADING_MOD_TITLE_W_PROGRESS" "Загрузка мода (%s1%)" + "CHECKSUMING_TITLE" "Проверка целостности" + "MOD_REQUIRED_WARNING" " : Этот мод может автоматически включиться / отключиться при подключении к серверу" + "WRONG_MOD_VERSION" "Версии мода \"%s1\" не совпадают. На сервере: v%s2. У вас: v%s3" + "CHECKSUMING_TEXT" "Проверяем целостность %s1 v%s2..." + "EXTRACTING_MOD_TITLE" "Распаковка мода (%s1%)" + "EXTRACTING_MOD_TEXT" "Распаковываем %s1 v%s2...\n(%s3/%s4 МБ)" + "FAILED_DOWNLOADING" "Ошибка загрузки мода" + "FAILED_READING_ARCHIVE" "Ошибка чтения архива мода." + "FAILED_WRITING_TO_DISK" "Ошибка распаковки файлов мода." + "MOD_FETCHING_FAILED" "Ошибка скачивания мода с Thunderstore." + "MOD_CORRUPTED" "Файл архива мода повреждён: контрольная сумма не совпадает." + "NO_DISK_SPACE_AVAILABLE" "Недостаточно места на диске." + "MOD_FETCHING_FAILED_GENERAL" "Ошибка распаковки мода. Проверьте файл лога, чтобы узнать подробности." + "MANIFESTO_FETCHING_TEXT" "Скачиваем список проверенных модов..." + "MANIFESTO_FETCHING_TITLE" "Начало загрузки модов" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt b/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt index 8d2df53b..d4172232 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt @@ -9,10 +9,10 @@ "MENU_TITLE_MODS" "Mods" "RELOAD_MODS" "Recargar Mods" "WARNING" "Advertencia" - "CORE_MOD_DISABLE_WARNING" "Puedes romper el cliente si deshabilitas los mods principales!" + "CORE_MOD_DISABLE_WARNING" "¡Puedes romper el cliente si deshabilitas los mods principales!" "DISABLE" "Deshabilitar" - "DIALOG_TITLE_INSTALLED_NORTHSTAR" "Gracias por instalar Northstar!." + "DIALOG_TITLE_INSTALLED_NORTHSTAR" "¡Gracias por instalar Northstar!" "AUTHENTICATION_AGREEMENT_DIALOG_TEXT" "Para que Northstar funcione, necesita autentificarse con el servidor maestro Northstar. Esto requiere enviar tu token Origin al servidor maestro, no se guardará ni se usará para cualquier otro fin. Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mods en cualquier momento." "BACK_AUTHENTICATION_AGREEMENT" "Acuerdo de autentificación" @@ -26,7 +26,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "NS_SERVERBROWSER_NOSERVERS" "No se encontraron servidores" "NS_SERVERBROWSER_UNKNOWNMODE" "Modo desconocido" "NS_SERVERBROWSER_WAITINGFORSERVERS" "Esperando por servidores..." - "NS_SERVERBROWSER_CONNECTIONFAILED" "Connexión fallida!" + "NS_SERVERBROWSER_CONNECTIONFAILED" "¡Conexión fallida!" "REFRESH_SERVERS" "Recargar" "MENU_TITLE_CONNECT_PASSWORD" "Conectar con contraseña" @@ -36,7 +36,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "PRIVATE_MATCH_PAGE_NEXT" "Página siguiente" "MENU_MATCH_SETTINGS" "Configuración de partida" - "MENU_MATCH_SETTINGS_SUBMENU" "%s1 Configuraciones" + "MENU_MATCH_SETTINGS_SUBMENU" "Configuración de %s1" "PRIVATE_MATCH_SINGLEPLAYER_LEVEL" "%s1 (Un jugador)" @@ -46,16 +46,16 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo // mode settings "MODE_SETTING_CATEGORY_PILOT" "Piloto" "MODE_SETTING_CATEGORY_TITAN" "Titán" - "MODE_SETTING_CATEGORY_RIFF" "Riffs" + "MODE_SETTING_CATEGORY_RIFF" "Fragmento" "MODE_SETTING_CATEGORY_MATCH" "Partida" "classic_mp" "Multijugador Clasico" "run_epilogue" "Habilitar Epílogo" "scorelimit" "Limite de puntuación" - "roundscorelimit" "Puntaje limite (rondas)" - "timelimit" "Tiempo limite" - "roundtimelimit" "Tiempo limite (rondas)" - "respawnprotection" "Tiempo de proteccion en reaparición" + "roundscorelimit" "Límite de punataje (rondas)" + "timelimit" "Límite de tiempo" + "roundtimelimit" "Límite de tiempo (rondas)" + "respawnprotection" "Tiempo de protección en reaparición" "pilot_health_multiplier" "Multiplicador de salúd" "respawn_delay" "Retraso de aparición" @@ -73,7 +73,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "featured_mode_all_grapple" "Ataque a los titanes" "featured_mode_all_phase" "El otro lado" "featured_mode_all_ticks" "Picante" - "featured_mode_tactikill" "Eliminación tactica" + "featured_mode_tactikill" "Eliminación con tactica" "featured_mode_amped_tacticals" "Tacticas mejoradas" "featured_mode_rocket_arena" "Arena de cohetes" "featured_mode_shotguns_snipers" "Armado y peligroso" @@ -82,12 +82,14 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "cp_amped_capture_points" "Fortines cargados" "coliseum_loadouts_enabled" "Arsenales de coliseo" + "aitdm_archer_grunts" "Soldado Archer" + // northstar.custom localisation is just deciding not to work, so putting it here for now - "PL_sbox" "Sandbox" - "PL_sbox_lobby" "Vestíbulo de Sandbox" - "PL_sbox_desc" "como gmod pero peor" + "PL_sbox" "Custom" + "PL_sbox_lobby" "Vestíbulo de juego abierto" + "PL_sbox_desc" "Como \"gmod\" pero peor" "PL_sbox_abbr" "SBOX" - "GAMEMODE_SBOX" "Sandbox" + "GAMEMODE_SBOX" "CUstom" "PL_gg" "Carrera armamentística" "PL_gg_lobby" "Vestíbulo de Carrera armamentística" @@ -101,37 +103,37 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "PL_tt" "Titan Tag" "PL_tt_lobby" "Vestíbulo de Titan Tag" - "PL_tt_desc" "Obtén puntos en tu titán. Destruye un titán para obtener el tuyo." - "PL_tt_hint" "Obtén puntos en tu titán. Destruye un titán para obtener el tuyo." + "PL_tt_desc" "Obtén puntos estando en tu titán. Destruye un titán para obtener el tuyo." + "PL_tt_hint" "Obtén puntos estando en tu titán. Destruye un titán para obtener el tuyo." "PL_tt_abbr" "TT" "GAMEMODE_TT" "Titan Tag" "PL_chamber" "Uno en la recamara" "PL_chamber_lobby" "Vestíbulo de uno en la recamara" - "PL_chamber_desc" "Un disparo, Una eliminación. Obtén otra bala en tu cargador eliminando a alguien." - "PL_chamber_hint" "Un disparo, Una eliminación. Obtén otra bala en tu cargador eliminando a alguien." - "PL_chamber_abbr" "CHAMBER" - "GAMEMODE_CHAMBER" "Uno en la recamara" + "PL_chamber_desc" "Un disparo, una eliminación. Obtén otra bala en tu cargador eliminando a alguien." + "PL_chamber_hint" "Un disparo, una eliminación. Obtén otra bala en tu cargador eliminando a alguien." + "PL_chamber_abbr" "RECÁMARA" + "GAMEMODE_CHAMBER" "Uno en la recámara" "PL_hidden" "El escondido" "PL_hidden_lobby" "Vestíbulo de El escondido" "PL_hidden_desc" "Un jugador es invisible. El escondido caza." "PL_hidden_hint" "Un jugador es invisible. El escondido caza." - "PL_hidden_abbr" "HIDDEN" + "PL_hidden_abbr" "OCULTO" "GAMEMODE_HIDDEN" "El escondido" - "HIDDEN_YOU_ARE_HIDDEN" "Eres el escondido!" + "HIDDEN_YOU_ARE_HIDDEN" "¡Eres el escondido!" "HIDDEN_KILL_SURVIVORS" "Mata a todos los supervivientes." "HIDDEN_FIRST_HIDDEN" "%s1 es El Escondido." - "PL_sns" "Piedras y palos" - "PL_sns_lobby" "Vestíbulo de Piedras y palos" + "PL_sns" "Palos y Piedras" + "PL_sns_lobby" "Vestíbulo de Palos y Piedras" "PL_sns_desc" "Todos contra todos. Usa cuchillas de pulso y ejecucciones para reestablecer el puntaje del enemigo" "PL_sns_abbr" "SNS" - "GAMEMODE_SNS" "Piedras y palos" + "GAMEMODE_SNS" "Palos y Piedras" "SCOREBOARD_BANKRUPTS" "Eliminaciones de bancarrota" - "SNS_LEADER_BANKRUPT" "Lider de puntaje en bancarrota!" - "SNS_LEADER_BANKRUPT_SUB" "%s1 Fue reseteado por %s2" - "SNS_BANKRUPT" "Arruinado!" + "SNS_LEADER_BANKRUPT" "¡Lider de puntaje en bancarrota!" + "SNS_LEADER_BANKRUPT_SUB" "%s1 fue reseteado por %s2" + "SNS_BANKRUPT" "¡Arruinado!" "SNS_BANKRUPT_SUB" "Tu puntaje fue reseteado por %s1" "sns_wme_kill_value" "Valor por eliminacion con Wingman Elite" "sns_softball_kill_value" "Valor por eliminacion con Softball" @@ -150,7 +152,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "INFECTION_YOU_ARE_INFECTED" "Has sido infectado!" "INFECTION_KILL_SURVIVORS" "Infecta a todos los supervivientes restantes." "INFECTION_FIRST_INFECTED" "%s1 es el primer Infectado." - "INFECTION_LAST_SURVIVOR" "%s1 es el ultimo superviviente!" + "INFECTION_LAST_SURVIVOR" "¡%s1 es el ultimo superviviente!" "INFECTION_KILL_LAST_SURVIVOR" "Infectalo antes de que el tiempo se acabe!" "INFECTION_YOU_ARE_LAST_SURVIVOR" "Eres el ultimo superviviente!" "INFECTION_SURVIVE_LAST_SURVIVOR" "Sobrevive." @@ -184,7 +186,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "GAMEMODE_fw" "Guerra fronteriza" "PL_fw" "Guerra fronteriza" "PL_fw_lobby" "Vestíbulo de Guerra fronteriza" - "PL_fw_desc" "Destruye el cosechador del enemigo y protege el tuyo." + "PL_fw_desc" "Destruye el cosechador del enemigo y protege el tuyo" "PL_fw_abbr" "FW" "GAMEMODE_kr" "Carrera por muertes" @@ -203,8 +205,8 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "KR_YOUR_KILLRACE_OVER" "Tu carrera ha acabado" "KR_YOUR_KILLRACE_SCORE" "Has obtenido %s1 bajas." - "GAMEMODE_fastball" "Fastball" - "PL_fastball" "Fastball" + "GAMEMODE_fastball" "Lanzamiento" + "PL_fastball" "Lanzamiento" "PL_fastball_lobby" "Vestíbulo de Fastball" "PL_fastball_desc" "Muerte permanente. Piratea paneles de control para ganar rondas y hacer reaparecer a tus compañeros de equipo." "PL_fastball_hint" "Muerte permanente. Piratea paneles de control para ganar rondas y hacer reaparecer a tus compañeros de equipo." @@ -261,7 +263,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "SP_BEACON_CLASSIC_DESC" "Cooper y BT intentan contactar con lo que queda de la flota para alertar de los planes de IMC." "SP_TDAY" "Prueba de fuego" - "SP_TDAY_CLASSIC_DESC" "Las habilidades de Cooper al mando de su titán se ponen a prueba en una batalla total para capturar el Arca." + "SP_TDAY_CLASSIC_DESC" "Las habilidades de Cooper al mando de su titán se ponen a prueba en una batalla total para capturar el Arca" "SP_S2S" "El Arca" "SP_S2S_CLASSIC_DESC" "Cooper y BT van de nave en nave en busca del Arca." @@ -274,7 +276,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "PLAYERS_COLUMN" "Jugadores" "MAP_COLUMN" "Mapa" "GAMEMODE_COLUMN" "Modo de juego" - "LATENCY_COLUMN" "Latencia" + "REGION_COLUMN" "Región" "SEARCHBAR_LABEL" "Buscar:" "MAP_FILTER" "Mapa" "GAMEMODE_FILTER" "Modo de juego" @@ -282,7 +284,7 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "HIDE_EMPTY_FILTER" "Esconder servidores vacios" "HIDE_PROT_FILTER" "Esconder servidores protegidos" "SERVER_DESCRIPTION" "Descripción" - "SERVER_MODS" "Mods" + "SERVER_MODS" "Modificaciones" "CLEAR_FILTERS" "LIMPIAR" "JOIN_BUTTON" "UNIR" @@ -316,6 +318,40 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo "PLAYER_NOT_FOUND" "No se encontró la cuenta del jugador" "INVALID_MASTERSERVER_TOKEN" "Token de jugador expirado o invalido" "JSON_PARSE_ERROR" "Error procesando respuesta json" - "UNSUPPORTED_VERSION" "La versión que estas usando ya no esta soportada" + "UNSUPPORTED_VERSION" "La versión que estás usando ya no está siendo mantenida" + "MATCH_COUNTDOWN_LENGTH" "Duración cronometrada de la partida privada" + "ONLY_HOST_MATCH_SETTINGS" "Sólo el anfitrión puede cambiar las configuraciones de la partida" + "ONLY_HOST_CAN_START_MATCH" "Sólo el anfitrión puede iniciar la partida" + "DISALLOWED_WEAPONS" "Armas prohibidas" + "REPLACEMENT_WEAPON" "Arma de reemplazo" + "MOD_SETTINGS" "Configuración de Mods" + "LOG_UNKNOWN_CLIENTCOMMANDS" "Registrar comandos no reconocidos desde el cliente" + "DISALLOWED_TACTICALS" "Tácticas prohibidas" + "TACTICAL_REPLACEMENT" "Reemplazo de la táctica" + "SHOULD_RETURN_TO_LOBBY" "Regresar a la sala de espera después de la partida" + "ARE_YOU_SURE" "¿Segur@?" + "WILL_RESET_ALL_SETTINGS" "Esto reiniciará TODAS las opciones de ésta categoría.\n\nNo se podrá revertir el proceso." + "NORTHSTAR_BASE_SETTINGS" "Opciones de Northstar por defecto" + "NO_RESULTS" "No hay resultados." + "MOD_SETTINGS_RESET" "Reiniciar" + "SHOW_ONLY_NOT_REQUIRED" "Mostrar sólo mods opcionales" + "SHOW_ONLY_REQUIRED" "Mostrar sólo mods obligatorios" + "NO_MODS" "¡No hay configuraciones disponibles! Instala más mods desde ^5588FF00northstar.thunderstore.io^0." + "PROGRESSION_TOGGLE_DISABLED_HEADER" "¿Habilitar progreso?" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "¿Deshabilitar progresión?" + "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" + "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" + "PROGRESSION_TOGGLE_ENABLED_BODY" "Los Titanes, Armas, Facciones, Aspectos y otros serán desbloqueados y permanecerán utilizables.\n\nÉsta opción puede ser cambiada cuando quieras desde la sala de espera." + "PROGRESSION_ENABLED_BODY" "^CCCC0000El modo de progreso ha sido habilitado.^\n\nLos Titanes, Armas, Facciones, Aspectos y otros se desbloquearán al subir de nivel o por Logros.\n\nPuedes cambiar ésta opción cuando quieras en la sala de espera." + "PROGRESSION_DISABLED_BODY" "^CCCC0000El modo de progreso ha sido deshabilitado.^\n\nLos Titanes, Armas, Facciones, Aspectos y otros están desbloqueados y puedes utilizarlos cuando quieras.\n\nPuedes cambiar ésta opción cuando quieras desde la sala de espera." + "WILL_RESET_SETTING" "Ésta acción reiniciará %s1 a su valor por defecto.\n\nNo se podrá revertir el proceso." + "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000El progreso puede ser habilitado desde ahora^\n\nNorthstar ahora es compatible con el progreso normal del juego, esto significa que puedes elegir desbloquear Armas, Aspectos, Titanes y otros a través de desafíos y subiendo de nivel.\n\nPuedes habilitar el progreso normal del juego en la opción ubicada al final de la pantalla de la sala de espera.\n\nÉsta opción puede ser cambiada en cualquier momento." + "player_force_respawn" "Reaparición Forzada" + "MOD_REQUIRED_WARNING" " : Esta modificacion puede ser desactivada al entrar a un servidor" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt b/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt index 5e6721a9..500f8a96 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt @@ -82,6 +82,8 @@ "cp_amped_capture_points" "強化據點" "coliseum_loadouts_enabled" "競技場裝備" + "aitdm_archer_grunts" "射手飛彈步兵" + // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "沙盒" "PL_sbox_lobby" "沙盒大廳" @@ -125,7 +127,7 @@ "PL_sns" "冷兵器" "PL_sns_lobby" "冷兵器大廳" - "PL_sns_desc" "模擬十字弓和飛斧的作戰模式。使用脈衝刀及處決擊殺來重置敵人的分數。" + "PL_sns_desc" "无规则. 使用脈衝刀及處決擊殺來重置敵人的分數" "PL_sns_abbr" "SNS" "GAMEMODE_SNS" "冷兵器" "SCOREBOARD_BANKRUPTS" "破產次數" @@ -153,7 +155,7 @@ "INFECTION_LAST_SURVIVOR" "%s1是最後的倖存者!" "INFECTION_KILL_LAST_SURVIVOR" "在時間用盡前感染他!" "INFECTION_YOU_ARE_LAST_SURVIVOR" "你是最後的倖存者!" - "INFECTION_SURVIVE_LAST_SURVIVOR" "倖存" + "INFECTION_SURVIVE_LAST_SURVIVOR" "最後幸存者." "PL_tffa" "泰坦混戰" "PL_tffa_lobby" "泰坦混戰大廳" @@ -236,45 +238,45 @@ "player_bleedout_aiBleedingPlayerMissChance" "倒地時AI的失誤率" // coop stuff - "PL_sp_coop" "(UNFINISHED) Singleplayer Coop" - "PL_sp_coop_lobby" "Singleplayer Coop Lobby" - "PL_sp_coop_desc" "Play through the singleplayer campaign with friends" - "PL_sp_coop_hint" "Play through the singleplayer campaign with friends" + "PL_sp_coop" "(未完成) 單人合作" + "PL_sp_coop_lobby" "單人合作模式大廳" + "PL_sp_coop_desc" "與朋友一起遊玩單人戰役" + "PL_sp_coop_hint" "與朋友一起遊玩單人戰役" "PL_sp_coop_abbr" "SP" - "SP_TRAINING" "The Pilot's Gauntlet" - "SP_TRAINING_CLASSIC_DESC" "Captain Lastimosa's training simulation." + "SP_TRAINING" "鐵御的試煉" + "SP_TRAINING_CLASSIC_DESC" "拉絲提莫沙上尉的模擬訓練." "SP_CRASHSITE" "BT-7274" - "SP_CRASHSITE_CLASSIC_DESC" "Jack Cooper meets BT-7274." + "SP_CRASHSITE_CLASSIC_DESC" "傑克庫博預見BT-7274." - "SP_SEWERS1" "Blood and Rust" - "SP_SEWERS1_CLASSIC_DESC" "Cooper and BT set out to rendezvous with Major Anderson." + "SP_SEWERS1" "鮮血與鐵鏽" + "SP_SEWERS1_CLASSIC_DESC" "庫博和BT一起出發前往與安德森上尉回合." - "SP_BOOMTOWN_START" "Into the Abyss" - "SP_BOOMTOWN_START_CLASSIC_DESC" "An underground shortcut yields unexpected consequences." + "SP_BOOMTOWN_START" "踏入虛空" + "SP_BOOMTOWN_START_CLASSIC_DESC" "一個地下捷徑造成了不可預見的後果." - "SP_HUB_TIMESHIFT" "Effect and Cause" - "SP_HUB_TIMESHIFT_CLASSIC_DESC" "A strange phenomenon is discovered at Major Anderson's coordinates." + "SP_HUB_TIMESHIFT" "因果報應" + "SP_HUB_TIMESHIFT_CLASSIC_DESC" "在安德森上尉的坐標處發現了奇異的現象." - "SP_BEACON" "The Beacon" - "SP_BEACON_CLASSIC_DESC" "Cooper and BT attempt to inform the remaining fleet of the IMC's plans." + "SP_BEACON" "信號台" + "SP_BEACON_CLASSIC_DESC" "庫博和BT嘗試將IMC的計劃通知給剩餘反抗軍艦隊." - "SP_TDAY" "Trial by Fire" - "SP_TDAY_CLASSIC_DESC" "Cooper's Titan skills are put to the test in an all-out battle to capture the Ark" + "SP_TDAY" "烈火審判" + "SP_TDAY_CLASSIC_DESC" "庫博驾馭泰坦的技術在爭奪聖櫃的全面戰爭中得到考驗" - "SP_S2S" "The Ark" - "SP_S2S_CLASSIC_DESC" "Cooper and BT go ship to ship in pursuit of the Ark." + "SP_S2S" "聖櫃" + "SP_S2S_CLASSIC_DESC" "庫博和BT在艦艇中穿梭追尋聖櫃." - "SP_SKYWAY_V1" "The Fold Weapon" - "SP_SKYWAY_V1_CLASSIC_DESC" "BT and Cooper are captured by Kuben Blisk." + "SP_SKYWAY_V1" "折疊時空武器" + "SP_SKYWAY_V1_CLASSIC_DESC" "BT和庫博被庫本布里斯克擒拿." // Better.Serverbrowser "SERVERS_COLUMN" "伺服器" "PLAYERS_COLUMN" "玩家" "MAP_COLUMN" "地圖" "GAMEMODE_COLUMN" "遊戲模式" - "LATENCY_COLUMN" "延遲" + "REGION_COLUMN" "地區" "SEARCHBAR_LABEL" "搜尋:" "MAP_FILTER" "地圖" "GAMEMODE_FILTER" "遊戲模式" @@ -308,8 +310,8 @@ "HUD_CHAT_SERVER_PREFIX" "[伺服器]" // In-game chat - "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" - "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + "HUD_CHAT_WHISPER_PREFIX" "[悄悄話]" + "HUD_CHAT_SERVER_PREFIX" "[伺服器]" "NO_GAMESERVER_RESPONSE" "無法連接到遊戲伺服器'" "BAD_GAMESERVER_RESPONSE" "遊戲伺服器回應無效" @@ -321,5 +323,38 @@ "INVALID_MASTERSERVER_TOKEN" "主伺服器token過期或無效" "JSON_PARSE_ERROR" "讀取json回應時發生錯誤" "UNSUPPORTED_VERSION" "您的遊戲版本過低" + "NORTHSTAR_BASE_SETTINGS" "北极星基础设置" + "ONLY_HOST_CAN_START_MATCH" "只有服主可以開始對局" + "MATCH_COUNTDOWN_LENGTH" "私人對局倒計時時間" + "DISALLOWED_TACTICALS" "禁用的技能" + "TACTICAL_REPLACEMENT" "替換的技能" + "NO_RESULTS" "無結果." + "LOG_UNKNOWN_CLIENTCOMMANDS" "登記未知客戶端指令" + "SHOULD_RETURN_TO_LOBBY" "對局結束後返回大廳" + "ARE_YOU_SURE" "確定?" + "WILL_RESET_SETTING" "這將會重置 %s1 的設置為默認值.\n\n此操作不可復原." + "MOD_SETTINGS_SERVER" "服務器" + "MOD_SETTINGS_RESET" "重置" + "MOD_SETTINGS_RESET_ALL" "重置所有" + "SHOW_ONLY_NOT_REQUIRED" "僅展示非必需模組" + "SHOW_ONLY_REQUIRED" "僅展示必須模組" + "MOD_SETTINGS" "模组设置" + "ONLY_HOST_MATCH_SETTINGS" "只有服主可以修改私人對局設置" + "DISALLOWED_WEAPONS" "禁用的武器" + "REPLACEMENT_WEAPON" "替换的武器" + "WILL_RESET_ALL_SETTINGS" "這將會重置所有屬於改條目的設置.\n\n此操作不可復原." + "NO_MODS" "無可用模組! 前往 ^5588FF00northstar.thunderstore.io^0 下載更多." + "player_force_respawn" "強制重生" + "PROGRESSION_TOGGLE_DISABLED_HEADER" "啟用個人進度?" + "PROGRESSION_ENABLED_HEADER" "個人進度已開啟!" + "PROGRESSION_TOGGLE_DISABLED_BODY" "泰坦,武器, 陣營,皮膚以及其他一切需要解鎖的物品將通過升級或是使用點數購買來進行解鎖。.\n\n您可以隨時在多人大廳中更改此項。\n\n^CC000000警告:如果您已經裝備了尚未解鎖的物品,它們將會被重置!" + "PROGRESSION_TOGGLE_ENABLED_BODY" "泰坦,武器,陣營,皮膚及所有其他一切需要解鎖的物品都將隨時可以進行解鎖並使用。\n\n您可以隨時在多人大廳中更改此項。" + "TOGGLE_PROGRESSION" "遊戲進度" + "Y_BUTTON_TOGGLE_PROGRESSION" "%[Y_BUTTON|]% 遊戲進度" + "PROGRESSION_TOGGLE_ENABLED_HEADER" "停用個人進度?" + "PROGRESSION_DISABLED_HEADER" "個人進度已關閉!" + "PROGRESSION_DISABLED_BODY" "^CCCC0000個人進度已停用^\n\n泰坦,武器,陣營,皮膚及所有其他一切需要解鎖的物品將隨時可以進行解鎖並使用。\n\n您可以隨時在多人大廳中更改此項。" + "PROGRESSION_ENABLED_BODY" "^CCCC0000個人進度已啟用^\n\n泰坦,武器, 陣營,皮膚以及其他一切需要解鎖的物品將通過升級或是使用點數購買來進行解鎖。.\n\n您可以隨時在多人大廳中更改此項。" + "PROGRESSION_ANNOUNCEMENT_BODY" "^CCCC0000現在可以隨時開啟個人進度!^\n\nNorthstar 現在支持類似官服的進度系統, 这意味着你可以选择通过升级和完成挑战来解锁武器、皮肤、泰坦等。\n\n您可以通過多人大廳底部的“遊戲進度”按鈕來進行開啟。\n\n您可以隨時在多人大廳中更改此項。" } } diff --git a/Northstar.Client/mod/resource/ui/menus/mod_settings.menu b/Northstar.Client/mod/resource/ui/menus/mod_settings.menu new file mode 100644 index 00000000..2fed2bd1 --- /dev/null +++ b/Northstar.Client/mod/resource/ui/menus/mod_settings.menu @@ -0,0 +1,511 @@ +"resource/ui/menus/mods_browse.menu" +{ + "menu" + { + "ControlName" "Frame" + "xpos" "0" + "ypos" "0" + "zpos" "3" + "wide" "f0" + "tall" "f0" + "autoResize" "1" + "visible" "1" + "enabled" "1" + "pinCorner" "0" + "PaintBackgroundType" "0" + "infocus_bgcolor_override" "0 0 0 0" + "outoffocus_bgcolor_override" "0 0 0 0" + "Vignette" + { + "ControlName" "ImagePanel" + "InheritProperties" "MenuVignette" + } + "Title" + { + "ControlName" "Label" + "InheritProperties" "MenuTitle" + "labelText" "#MOD_SETTINGS" + } + "ImgTopBar" + { + "ControlName" "ImagePanel" + "InheritProperties" "MenuTopBar" + } + "DarkenBackground" + { + "ControlName" "Label" + "classname" "ConnectingHUD" + "xpos" "0" + "ypos" "0" + "zpos" "99" + "wide" "%100" + "tall" "%100" + "labelText" "" + "bgcolor_override" "0 0 0 0" + "visible" "0" + "paintbackground" "1" + } + "ButtonRowAnchor" + { + "ControlName" "Label" + "labelText" "" + "pin_to_sibling" "DarkenBackground" + "pin_to_sibling_corner" "TOP_LEFT" + "pin_corner_to_sibling" "BOTTOM_LEFT" + "xpos" "-150" + "ypos" "-200" + } + "FilterButtonsRowAnchor" + { + "ControlName" "Label" + "pin_to_sibling" "LabelDetails" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "pin_corner_to_sibling" "TOP_LEFT" + "labelText" "" + "ypos" "12" + } + "NoResultLabel" + { + "ControlName" "Label" + "xpos" "0" + ypos "0" + wide "1200" + tall "675" + //auto_tall_tocontents 1 + visible "1" + enabled "1" + //auto_wide_tocontents 1 + labelText "No results." + textAlignment "center" + //auto_wide_tocontents "1" + //auto_tall_tocontents "1" + //fgcolor_override "255 255 255 255" + //bgcolor_override "0 0 0 200" + font Default_41 + + pin_to_sibling ButtonRowAnchor + pin_to_sibling_corner TOP_LEFT + pin_corner_to_sibling TOP_LEFT + } + // pain // + "BtnMod1" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "pin_to_sibling" "ButtonRowAnchor" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_LEFT" + "navUp" "BtnMod15" + "navDown" "BtnMod2" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "scriptID" "0" + } + "BtnMod2" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "pin_to_sibling" "BtnMod1" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod1" + "navDown" "BtnMod3" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "scriptID" "1" + } + "BtnMod3" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "2" + "pin_to_sibling" "BtnMod2" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod2" + "navDown" "BtnMod4" + } + "BtnMod4" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "3" + "pin_to_sibling" "BtnMod3" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod3" + "navDown" "BtnMod5" + } + "BtnMod5" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "4" + "pin_to_sibling" "BtnMod4" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod4" + "navDown" "BtnMod6" + } + "BtnMod6" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "5" + "pin_to_sibling" "BtnMod5" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod5" + "navDown" "BtnMod7" + } + "BtnMod7" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "6" + "pin_to_sibling" "BtnMod6" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod6" + "navDown" "BtnMod8" + } + "BtnMod8" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "7" + "pin_to_sibling" "BtnMod7" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod7" + "navDown" "BtnMod9" + } + "BtnMod9" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "8" + "pin_to_sibling" "BtnMod8" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod8" + "navDown" "BtnMod10" + } + "BtnMod10" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "9" + "pin_to_sibling" "BtnMod9" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod9" + "navDown" "BtnMod11" + } + "BtnMod11" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "10" + "pin_to_sibling" "BtnMod10" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod10" + "navDown" "BtnMod12" + } + "BtnMod12" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "11" + "pin_to_sibling" "BtnMod11" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod11" + "navDown" "BtnMod13" + } + "BtnMod13" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "12" + "pin_to_sibling" "BtnMod12" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod12" + "navDown" "BtnMod14" + } + "BtnMod14" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "13" + "pin_to_sibling" "BtnMod13" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod13" + "navDown" "BtnMod15" + } + "BtnMod15" + { + "ControlName" "CNestedPanel" + "classname" "ModButton" + "tall" "45" + "wide" "1200" + "controlSettingsFile" "resource/UI/menus/panels/mod_setting.res" + "classname" "ModButton" + "scriptID" "14" + "pin_to_sibling" "BtnMod14" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + "navUp" "BtnMod14" + "navDown" "BtnMod1" + } + // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + "FilterPanel" + { + "ControlName" "RuiPanel" + "wide" "1220" + "tall" "112" + //"xpos" "-8" + "classname" "FilterPanelChild" + "rui" "ui/knowledgebase_panel.rpak" + "visible" "1" + "zpos" "-1" + "pin_to_sibling" "FilterButtonsRowAnchor" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "LabelDetails" + { + "ControlName" "RuiPanel" + "tall" "695" + "wide" "1220" + "xpos" "10" + "ypos" "10" + "pin_to_sibling" "ButtonRowAnchor" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_LEFT" + "rui" "ui/knowledgebase_panel.rpak" + "wrap" "1" + "visible" "1" + "zpos" "-1" + } + "BtnSearchLabel" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + "labelText" "#SEARCHBAR_LABEL" + "textAlignment" "west" + "classname" "FilterPanelChild" + "wide" "500" + "xpos" "-23" + "ypos" "-16" + "wrap" "1" + "visible" "1" + "zpos" "0" + "pin_to_sibling" "FilterButtonsRowAnchor" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "BtnModsSearch" + { + "ControlName" "TextEntry" + "classname" "FilterPanelChild" + "zpos" "100" // This works around input weirdness when the control is constructed by code instead of VGUI blackbox. + "xpos" "-400" + "ypos" "-5" + "wide" "390" + "tall" "30" + "textHidden" "0" + "editable" "1" + "font" "Default_21" + "allowRightClickMenu" "0" + "allowSpecialCharacters" "1" + "unicode" "1" + "pin_to_sibling" "BtnSearchLabel" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_RIGHT" + } + "BtnFiltersClear" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + "labelText" "#CLEAR_FILTERS" + "classname" "FilterPanelChild" + "wide" "100" + "xpos" "0" + "ypos" "0" + "zpos" "90" + "scriptID" "999" + "pin_to_sibling" "BtnSearchLabel" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_RIGHT" + } + // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + "BtnModListUpArrow" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + // labelText "A"F + "wide" "40" + "tall" "40" + "xpos" "2" + "ypos" "0" + "image" "vgui/hud/white" + "drawColor" "255 255 255 128" + "pin_to_sibling" "LabelDetails" + "pin_corner_to_sibling" "TOP_RIGHT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "BtnModListUpArrowPanel" + { + "ControlName" "RuiPanel" + "wide" "40" + "tall" "40" + "xpos" "2" + "ypos" "0" + "rui" "ui/knowledgebase_panel.rpak" + "visible" "1" + "zpos" "-1" + "pin_to_sibling" "LabelDetails" + "pin_corner_to_sibling" "TOP_RIGHT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "BtnModListDownArrow" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + // labelText "V" + "wide" "40" + "tall" "40" + "xpos" "2" + "ypos" "-655" + "image" "vgui/hud/white" + "drawColor" "255 255 255 128" + "pin_to_sibling" "LabelDetails" + "pin_corner_to_sibling" "TOP_RIGHT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "BtnModListDownArrowPanel" + { + "ControlName" "RuiPanel" + "wide" "40" + "tall" "40" + "xpos" "2" + "ypos" "-655" + "rui" "ui/knowledgebase_panel.rpak" + "visible" "1" + "zpos" "-1" + "pin_to_sibling" "LabelDetails" + "pin_corner_to_sibling" "TOP_RIGHT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "BtnModListSlider" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + // labelText "V" + "wide" "40" + "tall" "420" + "xpos" "2" + "ypos" "-40" + "zpos" "0" + "image" "vgui/hud/white" + "drawColor" "255 255 255 128" + "pin_to_sibling" "LabelDetails" + "pin_corner_to_sibling" "TOP_RIGHT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "BtnModListSliderPanel" + { + "ControlName" "RuiPanel" + "wide" "40" + "tall" "420" + "xpos" "2" + "ypos" "-40" + "rui" "ui/knowledgebase_panel.rpak" + "visible" "1" + "zpos" "-1" + "pin_to_sibling" "LabelDetails" + "pin_corner_to_sibling" "TOP_RIGHT" + "pin_to_sibling_corner" "TOP_LEFT" + } + // sh_menu_models.gnut has a global function which gets called when + // left mouse button gets called while hovering and has mouse + // deltaX; deltaY which we can yoink for ourselfes + "MouseMovementCapture" + { + "ControlName" "CMouseMovementCapturePanel" + "wide" "40" + "tall" "604" + "xpos" "2" + "ypos" "-40" + "zpos" "1" + "pin_to_sibling" "LabelDetails" + "pin_corner_to_sibling" "TOP_RIGHT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "ButtonTooltip" + { + "ControlName" "CNestedPanel" + "InheritProperties" "ButtonTooltip" + } + // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + "FooterButtons" + { + "ControlName" "CNestedPanel" + "InheritProperties" "FooterButtons" + } + } +} diff --git a/Northstar.Client/mod/resource/ui/menus/modlist.menu b/Northstar.Client/mod/resource/ui/menus/modlist.menu index ffe9a257..bd350a33 100644 --- a/Northstar.Client/mod/resource/ui/menus/modlist.menu +++ b/Northstar.Client/mod/resource/ui/menus/modlist.menu @@ -1,4 +1,4 @@ -resource/ui/menus/mods_browse.menu +resource/ui/menus/modlist.menu { menu { @@ -18,497 +18,654 @@ resource/ui/menus/mods_browse.menu Vignette { - ControlName ImagePanel - InheritProperties MenuVignette + ControlName ImagePanel + InheritProperties MenuVignette } Title { - ControlName Label - InheritProperties MenuTitle - labelText "#MENU_TITLE_MODS" + ControlName Label + InheritProperties MenuTitle + labelText "#MENU_TITLE_MODS" } ImgTopBar { - ControlName ImagePanel - InheritProperties MenuTopBar + ControlName ImagePanel + InheritProperties MenuTopBar } - + ButtonRowAnchor { - ControlName Label - labelText "" + ControlName Label + labelText "" - xpos 120 - ypos 160 + xpos 120 + ypos 160 } - + FilterButtonsRowAnchor { - ControlName Label - labelText "" + ControlName Label + labelText "" - xpos 90 - ypos 848 + xpos 90 + ypos 848 } - + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// PANELS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - BtnMod1 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 0 - navUp BtnMod15 - navDown BtnMod2 - - pin_to_sibling ButtonRowAnchor - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - } - BtnMod2 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 1 - pin_to_sibling BtnMod1 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod1 - navDown BtnMod3 - } - BtnMod3 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 2 - pin_to_sibling BtnMod2 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod2 - navDown BtnMod4 - } - BtnMod4 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 3 - pin_to_sibling BtnMod3 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - //ypos 11 - navUp BtnMod3 - navDown BtnMod5 - } - BtnMod5 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 4 - pin_to_sibling BtnMod4 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod4 - navDown BtnMod6 - } - BtnMod6 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 5 - pin_to_sibling BtnMod5 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod5 - navDown BtnMod7 - } - BtnMod7 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 6 - pin_to_sibling BtnMod6 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod6 - navDown BtnMod8 - } - BtnMod8 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 7 - pin_to_sibling BtnMod7 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod7 - navDown BtnMod9 - } - BtnMod9 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 8 - pin_to_sibling BtnMod8 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod8 - navDown BtnMod10 - } - BtnMod10 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 9 - pin_to_sibling BtnMod9 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod9 - navDown BtnMod11 - } - BtnMod11 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 10 - pin_to_sibling BtnMod10 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod10 - navDown BtnMod12 - } - BtnMod12 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 11 - pin_to_sibling BtnMod11 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod11 - navDown BtnMod13 - } - BtnMod13 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 12 - pin_to_sibling BtnMod12 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod12 - navDown BtnMod14 - } - BtnMod14 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 13 - pin_to_sibling BtnMod13 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod13 - navDown BtnMod15 - } - BtnMod15 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 14 - pin_to_sibling BtnMod14 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod14 - navDown BtnMod1 - } - BtnMod16 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 15 - pin_to_sibling BtnMod15 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod15 - navDown BtnMod17 - } - BtnMod17 - { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModButton - scriptID 16 - pin_to_sibling BtnMod16 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMod16 - navDown BtnMod18 + Panel1 + { + ControlName CNestedPanel + classname ModSelectorPanel + scriptID 1 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling ButtonRowAnchor + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel2 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 2 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel1 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel3 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 3 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel2 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel4 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 4 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel3 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel5 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 5 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel4 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel6 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 6 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel5 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel7 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 7 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel6 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel8 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 8 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel7 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel9 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 9 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel8 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel10 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 10 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel9 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel11 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 11 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel10 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel12 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 12 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel11 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } + Panel13 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 13 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel12 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel14 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 14 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel13 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel15 + { + ControlName "CNestedPanel" + classname ModSelectorPanel + scriptID 15 + + controlSettingsFile "resource/ui/menus/panels/modlist_settings.res" + wide %100 + tall 45 + + pin_to_sibling Panel14 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +// FILTERS +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + FilterPanel { - ControlName RuiPanel - wide 800 - tall 112 - xpos -8 - classname FilterPanelChild - - rui "ui/knowledgebase_panel.rpak" + ControlName RuiPanel + classname FilterPanelChild + + wide 800 + tall 112 + xpos -8 + zpos -1 - visible 1 - zpos -1 + rui "ui/knowledgebase_panel.rpak" + visible 1 - pin_to_sibling FilterButtonsRowAnchor - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT + pin_to_sibling FilterButtonsRowAnchor + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT } - + BtnSearchLabel { - ControlName RuiButton - InheritProperties RuiSmallButton - labelText "#SEARCHBAR_LABEL" - textAlignment west - classname FilterPanelChild - - wide 500 - xpos -23 - ypos -16 - - wrap 1 - visible 1 - zpos 0 - - pin_to_sibling FilterButtonsRowAnchor - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - } - + ControlName RuiButton + InheritProperties RuiSmallButton + classname FilterPanelChild + + labelText #SEARCHBAR_LABEL + textAlignment west + + wide 500 + xpos -23 + ypos -16 + zpos 0 + wrap 1 + visible 1 + + + + pin_to_sibling FilterButtonsRowAnchor + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + } + BtnModsSearch { - ControlName TextEntry - classname FilterPanelChild - zpos 100 // This works around input weirdness when the control is constructed by code instead of VGUI blackbox. - xpos -400 - ypos -5 - wide 390 - tall 30 - textHidden 0 - editable 1 - font Default_21 - allowRightClickMenu 0 - allowSpecialCharacters 0 - unicode 0 - - pin_to_sibling BtnSearchLabel - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_RIGHT + ControlName TextEntry + classname FilterPanelChild + + zpos 100 // This works around input weirdness when the control is constructed by code instead of VGUI blackbox. + xpos -400 + ypos -5 + wide 390 + tall 30 + + textHidden 0 // Why? + editable 1 + font Default_21 + + allowRightClickMenu 0 + allowSpecialCharacters 0 + unicode 1 + + pin_to_sibling BtnSearchLabel + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_RIGHT } - + SwtBtnShowFilter { - ControlName RuiButton - InheritProperties SwitchButton - labelText "#SHOW" - ConVar "filter_mods" - classname FilterPanelChild + ControlName RuiButton + InheritProperties SwitchButton + classname FilterPanelChild + + labelText "#SHOW" + ConVar "filter_mods" wide 500 - + list { - "#SHOW_ALL" 0 - "#SHOW_ONLY_ENABLED" 1 - "#SHOW_ONLY_DISABLED" 2 + "#SHOW_ALL" 0 + "#SHOW_ONLY_ENABLED" 1 + "#SHOW_ONLY_DISABLED" 2 + "#SHOW_ONLY_NOT_REQUIRED" 3 + "#SHOW_ONLY_REQUIRED" 4 } - - pin_to_sibling BtnSearchLabel - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT + + pin_to_sibling BtnSearchLabel + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - + + BtnListReverse + { + ControlName RuiButton + InheritProperties SwitchButton + classname FilterPanelChild + + xpos -15 + ypos -15 + + labelText "Reverse" + ConVar "modlist_reverse" + wide 260 + + list + { + "low first" 0 + "high first" 1 + } + + pin_to_sibling FilterPanel + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_RIGHT + } + BtnFiltersClear { - ControlName RuiButton - InheritProperties RuiSmallButton - labelText "#CLEAR_FILTERS" - classname FilterPanelChild - wide 100 - xpos -15 - ypos -55 - zpos 90 - - scriptID 999 - - pin_to_sibling FilterPanel - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner BOTTOM_RIGHT + ControlName RuiButton + InheritProperties RuiSmallButton + classname FilterPanelChild + + labelText "#CLEAR_FILTERS" + wide 100 + xpos -15 + ypos -55 + zpos 90 + + pin_to_sibling FilterPanel + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner BOTTOM_RIGHT } - + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// MOD INFO +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + ModButtonsPanel + { + ControlName RuiPanel + classname FilterPanelChild + + wide 950 + tall 112 + + rui "ui/knowledgebase_panel.rpak" + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP + pin_to_sibling_corner BOTTOM + } + + HideCVButton + { + ControlName RuiButton + InheritProperties SwitchButton + + labelText "ConVars" + ConVar "modlist_show_convars" + wide 300 + + list + { + "Hidden" 0 + "Shown" 1 + } + + pin_to_sibling ModButtonsPanel + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + } + + ModPageButton + { + ControlName RuiButton + InheritProperties RuiSmallButton + + textAlignment west + visible 0 + + pin_to_sibling HideCVButton + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + WarningLegendImage + { + ControlName RuiPanel + + rui ui/basic_image.rpak + wide 30 + tall 30 + xpos -10 + ypos -5 + visible 0 + + pin_to_sibling ModButtonsPanel + pin_corner_to_sibling BOTTOM_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + WarningLegendLabel + { + ControlName Label + + labelText "#MOD_REQUIRED_WARNING" + auto_wide_tocontents 1 + tall 50 + visible 0 + + pin_to_sibling WarningLegendImage + pin_corner_to_sibling LEFT + pin_to_sibling_corner RIGHT + } + LabelDetails { - ControlName RuiPanel - xpos 900 - ypos 160 - tall 800 - wide 950 - rui "ui/knowledgebase_panel.rpak" - wrap 1 - visible 1 - zpos 1 + ControlName RuiPanel + + xpos 900 + ypos 160 + zpos 1 + + tall 688 + wide 950 + rui "ui/knowledgebase_panel.rpak" + wrap 1 + visible 1 } - + + ModEnabledBar + { + ControlName RuiPanel + + rui ui/basic_image.rpak + wide 950 + tall 7 + zpos 2 + visible 0 + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SLIDER //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + BtnModListUpArrow { - ControlName RuiButton - InheritProperties RuiSmallButton - //labelText "A" - wide 40 - tall 40 - xpos 2 - ypos 2 - - image "vgui/hud/white" - drawColor "255 255 255 128" - - pin_to_sibling LabelDetails - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner TOP_LEFT - } - + ControlName RuiButton + InheritProperties RuiSmallButton + + wide 40 + tall 40 + xpos 2 + ypos 2 + + image "vgui/hud/white" + drawColor "255 255 255 128" + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + BtnModListUpArrowPanel { - ControlName RuiPanel - wide 40 - tall 40 - xpos 2 - ypos 2 - - rui "ui/knowledgebase_panel.rpak" - - visible 1 - zpos -1 - - pin_to_sibling LabelDetails - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner TOP_LEFT - } - + ControlName RuiPanel + + wide 40 + tall 40 + xpos 2 + ypos 2 + + rui "ui/knowledgebase_panel.rpak" + visible 1 + zpos -1 + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + BtnModListDownArrow { - ControlName RuiButton - InheritProperties RuiSmallButton - //labelText "V" - wide 40 - tall 40 - xpos 2 - ypos -646 - - image "vgui/hud/white" - drawColor "255 255 255 128" - - pin_to_sibling LabelDetails - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner TOP_LEFT - } - + ControlName RuiButton + InheritProperties RuiSmallButton + + wide 40 + tall 40 + xpos 2 + ypos -646 + + image "vgui/hud/white" + drawColor "255 255 255 128" + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + BtnModListDownArrowPanel { - ControlName RuiPanel - wide 40 - tall 40 - xpos 2 - ypos -646 - - rui "ui/knowledgebase_panel.rpak" - - visible 1 - zpos -1 - - pin_to_sibling LabelDetails - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner TOP_LEFT - } - + ControlName RuiPanel + + wide 40 + tall 40 + xpos 2 + ypos -646 + zpos -1 + + rui "ui/knowledgebase_panel.rpak" + visible 1 + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + BtnModListSlider { - ControlName RuiButton - InheritProperties RuiSmallButton - //labelText "V" - wide 40 - tall 604 - xpos 2 - ypos -40 - zpos 0 - - image "vgui/hud/white" - drawColor "255 255 255 128" - - pin_to_sibling LabelDetails - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner TOP_LEFT - } - + ControlName RuiButton + InheritProperties RuiSmallButton + + wide 40 + tall 604 + xpos 2 + ypos -40 + zpos 0 + + image "vgui/hud/white" + drawColor "255 255 255 128" + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + BtnModListSliderPanel { - ControlName RuiPanel - wide 40 - tall 604 - xpos 2 - ypos -40 - - rui "ui/knowledgebase_panel.rpak" - - visible 1 - zpos -1 - - pin_to_sibling LabelDetails - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner TOP_LEFT - } - + ControlName RuiPanel + + wide 40 + tall 604 + xpos 2 + ypos -40 + zpos -1 + + rui "ui/knowledgebase_panel.rpak" + visible 1 + + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + // sh_menu_models.gnut has a global function which gets called when // left mouse button gets called while hovering and has mouse // deltaX; deltaY which we can yoink for ourselfes MouseMovementCapture { - ControlName CMouseMovementCapturePanel - wide 40 - tall 604 - xpos 2 - ypos -40 - zpos 1 - - pin_to_sibling LabelDetails - pin_corner_to_sibling TOP_RIGHT - pin_to_sibling_corner TOP_LEFT + ControlName CMouseMovementCapturePanel + + wide 40 + tall 604 + xpos 2 + ypos -40 + zpos 1 + + pin_to_sibling LabelDetails + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// FooterButtons { - ControlName CNestedPanel - InheritProperties FooterButtons + ControlName CNestedPanel + InheritProperties FooterButtons } } } diff --git a/Northstar.Client/mod/resource/ui/menus/panels/mod_setting.res b/Northstar.Client/mod/resource/ui/menus/panels/mod_setting.res new file mode 100644 index 00000000..92dce922 --- /dev/null +++ b/Northstar.Client/mod/resource/ui/menus/panels/mod_setting.res @@ -0,0 +1,183 @@ +"resource/ui/menus/panels/mod_setting.res" +{ + "FULL" + { + "ControlName" "Label" + "classname" "ConnectingHUD" + "xpos" "0" + "ypos" "0" + "zpos" "99" + "wide" "1200" + "tall" "45" + "labelText" "" + "bgcolor_override" "0 0 0 0" + "visible" "0" + "paintbackground" "1" + } + "BtnMod" + { + "ControlName" "Label" + "InheritProperties" "RuiSmallButton" + "labelText" "Mod" + //"auto_wide_tocontents" "1" + "navRight" "EnumSelectButton" + "navLeft" "TextEntrySetting" + "wide" "390" + "tall" "45" + } + // we're getting to the top of this :) + "TopLine" + { + "ControlName" "ImagePanel" + "InheritProperties" "MenuTopBar" + "ypos" "0" + "wide" "%100" + "pin_to_sibling" "BtnMod" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_LEFT" + } + "ModTitle" + { + "ControlName" "Label" + "InheritProperties" "RuiSmallButton" + "labelText" "Mod" + "font" "DefaultBold_43" + //"auto_wide_tocontents" "1" + "zpos" "-999" + "textAlignment" "center" + "navRight" "EnumSelectButton" + "navLeft" "TextEntrySetting" + "wide" "1200" + "tall" "45" + + } + "Slider" + { + "ControlName" "SliderControl" + //"InheritProperties" "RuiSmallButton" + minValue 0.0 + maxValue 2.0 + stepSize 0.05 + "pin_to_sibling" "BtnMod" + "pin_corner_to_sibling" "TOP_LEFT" + "pin_to_sibling_corner" "TOP_RIGHT" + "navRight" "ResetModToDefault" + "navLeft" "TextEntrySetting" + //isValueClampedToStepSize 1 + BtnDropButton + { + ControlName RuiButton + //InheritProperties WideButton + style SliderButton + "wide" "320" + "tall" "45" + "labelText" "" + "auto_wide_tocontents" "0" + } + "wide" "320" + "tall" "45" + } + "EnumSelectButton" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + "style" "DialogListButton" + "labelText" "" + "zpos" "4" + "wide" "225" + "tall" "45" + //"xpos" "10" + "scriptID" "0" + "pin_to_sibling" "FULL" + "pin_corner_to_sibling" "RIGHT" + "pin_to_sibling_corner" "RIGHT" + "navLeft" "ResetModToDefault" + "navRight" "TextEntrySetting" + } + "ResetModToDefault" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + "labelText" "" + "zpos" "0" + "xpos" "10" + "wide" "45" + "tall" "45" + "scriptID" "0" + "pin_to_sibling" "EnumSelectButton" + "pin_corner_to_sibling" "RIGHT" + "pin_to_sibling_corner" "LEFT" + "navLeft" "Slider" + "navRight" "TextEntrySetting" + } + "ResetModImage" + { + "ControlName" "ImagePanel" + "image" "vgui/reset" + "scaleImage" "1" + "drawColor" "180 180 180 255" // vanilla label color + "visible" "0" + "wide" "30" + "tall" "30" + "enabled" "0" + + "pin_to_sibling" "ResetModToDefault" + "pin_corner_to_sibling" "CENTER" + "pin_to_sibling_corner" "CENTER" + } + "OpenCustomMenu" + { + "ControlName" "RuiButton" + "InheritProperties" "RuiSmallButton" + "labelText" "Open" + //"auto_wide_tocontents" "1" + "zpos" "4" + "wide" "1200" + "textAlignment" "center" + //"font" "Default_41" + //"xpos" "10" + "tall" "40" + "scriptID" "0" + "visible" "0" + "pin_to_sibling" "FULL" + "pin_corner_to_sibling" "RIGHT" + "pin_to_sibling_corner" "RIGHT" + "navLeft" "TextEntrySetting" + "navRight" "TextEntrySetting" + } + "TextEntrySetting" + { + "ControlName" "TextEntry" + "classname" "MatchSettingTextEntry" + //"xpos" "-35" + //"ypos" "-5" + "zpos" "100" // This works around input weirdness when the control is constructed by code instead of VGUI blackbox. + "wide" "160" + "tall" "30" + "scriptID" "0" + "textHidden" "0" + "editable" "1" + // NumericInputOnly 1 + "font" "Default_21" + "allowRightClickMenu" "0" + "allowSpecialCharacters" "1" + "unicode" "0" + "pin_to_sibling" "EnumSelectButton" + "pin_corner_to_sibling" "CENTER" + "pin_to_sibling_corner" "CENTER" + "navLeft" "EnumSelectButton" + "navRight" "EnumSelectButton" + } + // we're getting to the bottom of this :) + "BottomLine" + { + "ControlName" "ImagePanel" + "InheritProperties" "MenuTopBar" + "ypos" "5" + "wide" "%100" + //"tall" "0" + "pin_to_sibling" "FULL" + "pin_corner_to_sibling" "BOTTOM_LEFT" + "pin_to_sibling_corner" "BOTTOM_LEFT" + } +} diff --git a/Northstar.Client/mod/resource/ui/menus/panels/modlist_settings.res b/Northstar.Client/mod/resource/ui/menus/panels/modlist_settings.res new file mode 100644 index 00000000..cd596238 --- /dev/null +++ b/Northstar.Client/mod/resource/ui/menus/panels/modlist_settings.res @@ -0,0 +1,79 @@ +resource/ui/menus/panels/modlist_setting.res +{ + BtnMod + { + ControlName RuiButton + InheritProperties RuiSmallButton + classname ModButton + labelText "please show up" + + pin_to_sibling ControlBox + pin_corner_to_sibling LEFT + pin_to_sibling_corner RIGHT + } + + Header + { + ControlName Label + wide 400 + labelText "labelText" + + pin_to_sibling ControlBox + pin_corner_to_sibling LEFT + pin_to_sibling_corner RIGHT + } + + ControlBox + { + ControlName RuiPanel + classname ControlBox + + tall 30 + wide 5 + ypos 5 + rui "ui/basic_image.rpak" + + pin_corner_to_sibling LEFT + pin_to_sibling_corner LEFT + } + + BottomLine + { + ControlName ImagePanel + InheritProperties MenuTopBar + ypos 0 + wide %50 + + pin_to_sibling BtnMod + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + WarningImage + { + ControlName RuiPanel + + rui ui/basic_image.rpak + wide 30 + tall 30 + visible 0 + + pin_to_sibling BtnMod + pin_corner_to_sibling LEFT + pin_to_sibling_corner RIGHT + } + + EnabledImage + { + ControlName RuiPanel + + rui ui/basic_image.rpak + wide 30 + tall 30 + visible 0 + + pin_to_sibling BtnMod + pin_corner_to_sibling RIGHT + pin_to_sibling_corner LEFT + } +} diff --git a/Northstar.Client/mod/resource/ui/menus/server_browser.menu b/Northstar.Client/mod/resource/ui/menus/server_browser.menu index 89fb951d..4a84a714 100644 --- a/Northstar.Client/mod/resource/ui/menus/server_browser.menu +++ b/Northstar.Client/mod/resource/ui/menus/server_browser.menu @@ -419,6 +419,252 @@ resource/ui/menus/mods_browse.menu pin_corner_to_sibling TOP_LEFT pin_to_sibling_corner BOTTOM_LEFT } + + // Region + BtnServerRegionTab + { + ControlName RuiButton + InheritProperties RuiSmallButton + labelText "#REGION_COLUMN" + wide 110 + xpos -4 + ypos -1 + + scriptID 999 + + pin_to_sibling BtnServerPasswordProtectedTab + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_RIGHT + navDown BtnServer1 + navRight BtnServerNameTab + navUp BtnFiltersClear + } + + BtnServerRegion1 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer1 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion2 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer2 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion3 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer3 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion4 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer4 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion5 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer5 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion6 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer6 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion7 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer7 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion8 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer8 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion9 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer9 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion10 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer10 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion11 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer11 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion12 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer12 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion13 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer13 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion14 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer14 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + BtnServerRegion15 + { + ControlName Label + labelText "" + classname Serverregion + textAlignment center + wide 110 + tall 44 + ypos -42 + xpos 0 + + pin_to_sibling BtnServer15 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } // Name BtnServerNameTab @@ -427,16 +673,16 @@ resource/ui/menus/mods_browse.menu InheritProperties RuiSmallButton labelText "#SERVERS_COLUMN" wide 600 - xpos -4 - ypos -1 + xpos 4 scriptID 999 - pin_to_sibling BtnServerPasswordProtectedTab + pin_to_sibling BtnServerRegionTab pin_corner_to_sibling TOP_LEFT pin_to_sibling_corner TOP_RIGHT navUp BtnFiltersClear navDown BtnServer1 + navLeft BtnServerRegionTab navRight BtnServerPlayersTab } @@ -448,8 +694,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 interactive false @@ -465,8 +711,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer2 pin_corner_to_sibling TOP_LEFT @@ -480,8 +726,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer3 pin_corner_to_sibling TOP_LEFT @@ -495,8 +741,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer4 pin_corner_to_sibling TOP_LEFT @@ -510,8 +756,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer5 pin_corner_to_sibling TOP_LEFT @@ -525,8 +771,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer6 pin_corner_to_sibling TOP_LEFT @@ -540,8 +786,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer7 pin_corner_to_sibling TOP_LEFT @@ -555,8 +801,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer8 pin_corner_to_sibling TOP_LEFT @@ -570,8 +816,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer9 pin_corner_to_sibling TOP_LEFT @@ -585,8 +831,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer10 pin_corner_to_sibling TOP_LEFT @@ -600,8 +846,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer11 pin_corner_to_sibling TOP_LEFT @@ -615,8 +861,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer12 pin_corner_to_sibling TOP_LEFT @@ -630,8 +876,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer13 pin_corner_to_sibling TOP_LEFT @@ -645,8 +891,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer14 pin_corner_to_sibling TOP_LEFT @@ -660,8 +906,8 @@ resource/ui/menus/mods_browse.menu classname ServerName wide 586 tall 44 - ypos -44 - xpos -14 + ypos -42 + xpos -122 pin_to_sibling BtnServer15 pin_corner_to_sibling TOP_LEFT @@ -697,8 +943,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer1 pin_corner_to_sibling TOP_LEFT @@ -712,8 +958,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer2 pin_corner_to_sibling TOP_LEFT @@ -727,8 +973,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer3 pin_corner_to_sibling TOP_LEFT @@ -742,8 +988,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer4 pin_corner_to_sibling TOP_LEFT @@ -757,8 +1003,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer5 pin_corner_to_sibling TOP_LEFT @@ -772,8 +1018,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer6 pin_corner_to_sibling TOP_LEFT @@ -787,8 +1033,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer7 pin_corner_to_sibling TOP_LEFT @@ -802,8 +1048,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer8 pin_corner_to_sibling TOP_LEFT @@ -817,8 +1063,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer9 pin_corner_to_sibling TOP_LEFT @@ -832,8 +1078,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer10 pin_corner_to_sibling TOP_LEFT @@ -847,8 +1093,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer11 pin_corner_to_sibling TOP_LEFT @@ -862,8 +1108,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer12 pin_corner_to_sibling TOP_LEFT @@ -877,8 +1123,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer13 pin_corner_to_sibling TOP_LEFT @@ -892,8 +1138,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer14 pin_corner_to_sibling TOP_LEFT @@ -907,8 +1153,8 @@ resource/ui/menus/mods_browse.menu textAlignment center wide 104 tall 44 - ypos -44 - xpos -600 + ypos -42 + xpos -718 pin_to_sibling BtnServer15 pin_corner_to_sibling TOP_LEFT @@ -944,8 +1190,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer1 pin_corner_to_sibling TOP_LEFT @@ -959,8 +1205,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer2 pin_corner_to_sibling TOP_LEFT @@ -974,8 +1220,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer3 pin_corner_to_sibling TOP_LEFT @@ -989,8 +1235,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer4 pin_corner_to_sibling TOP_LEFT @@ -1004,8 +1250,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer5 pin_corner_to_sibling TOP_LEFT @@ -1019,8 +1265,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer6 pin_corner_to_sibling TOP_LEFT @@ -1034,8 +1280,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer7 pin_corner_to_sibling TOP_LEFT @@ -1049,8 +1295,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer8 pin_corner_to_sibling TOP_LEFT @@ -1064,8 +1310,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer9 pin_corner_to_sibling TOP_LEFT @@ -1079,8 +1325,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer10 pin_corner_to_sibling TOP_LEFT @@ -1094,8 +1340,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer11 pin_corner_to_sibling TOP_LEFT @@ -1109,8 +1355,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer12 pin_corner_to_sibling TOP_LEFT @@ -1124,8 +1370,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer13 pin_corner_to_sibling TOP_LEFT @@ -1139,8 +1385,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer14 pin_corner_to_sibling TOP_LEFT @@ -1154,8 +1400,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -709 + ypos -42 + xpos -828 pin_to_sibling BtnServer15 pin_corner_to_sibling TOP_LEFT @@ -1178,7 +1424,7 @@ resource/ui/menus/mods_browse.menu pin_to_sibling_corner TOP_RIGHT navDown BtnServer1 navLeft BtnServerMapTab - navRight BtnServerLatencyTab + navRight BtnServerJoin navUp BtnFiltersClear } @@ -1190,8 +1436,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer1 pin_corner_to_sibling TOP_LEFT @@ -1205,8 +1451,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer2 pin_corner_to_sibling TOP_LEFT @@ -1220,8 +1466,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer3 pin_corner_to_sibling TOP_LEFT @@ -1235,8 +1481,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer4 pin_corner_to_sibling TOP_LEFT @@ -1250,8 +1496,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer5 pin_corner_to_sibling TOP_LEFT @@ -1265,8 +1511,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer6 pin_corner_to_sibling TOP_LEFT @@ -1280,8 +1526,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer7 pin_corner_to_sibling TOP_LEFT @@ -1295,8 +1541,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer8 pin_corner_to_sibling TOP_LEFT @@ -1310,8 +1556,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer9 pin_corner_to_sibling TOP_LEFT @@ -1325,8 +1571,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer10 pin_corner_to_sibling TOP_LEFT @@ -1340,8 +1586,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer11 pin_corner_to_sibling TOP_LEFT @@ -1355,8 +1601,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer12 pin_corner_to_sibling TOP_LEFT @@ -1370,8 +1616,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer13 pin_corner_to_sibling TOP_LEFT @@ -1385,8 +1631,8 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer14 pin_corner_to_sibling TOP_LEFT @@ -1400,366 +1646,120 @@ resource/ui/menus/mods_browse.menu wide 140 textAlignment center tall 44 - ypos -44 - xpos -860 + ypos -42 + xpos -972 pin_to_sibling BtnServer15 pin_corner_to_sibling TOP_LEFT pin_to_sibling_corner BOTTOM_LEFT } - // Latency - BtnServerLatencyTab - { - ControlName RuiButton - InheritProperties RuiSmallButton - labelText "#LATENCY_COLUMN" - wide 110 - xpos 4 - - scriptID 999 - - pin_to_sibling BtnServerGamemodeTab - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_RIGHT - navDown BtnServer1 - navLeft BtnServerGamemodeTab - navRight BtnServerJoin - navUp BtnFiltersClear - } - - BtnServerLatency1 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - - pin_to_sibling BtnServer1 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency2 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - - pin_to_sibling BtnServer2 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency3 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 + // Dividers: - pin_to_sibling BtnServer3 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency4 + // Y + YDivider0 { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 + ControlName ImagePanel + wide 2 + tall 641 + visible 1 + image "vgui/hud/white" + drawColor "160 157 149 255" + scaleImage 1 + xpos 3 + ypos -1 - pin_to_sibling BtnServer4 + pin_to_sibling BtnServerNameTab pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT + pin_to_sibling_corner TOP_LEFT } - BtnServerLatency5 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - pin_to_sibling BtnServer5 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency6 + YDivider1 { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 + ControlName ImagePanel + wide 2 + tall 641 + visible 1 + image "vgui/hud/white" + drawColor "160 157 149 255" + scaleImage 1 + xpos 3 + ypos -1 - pin_to_sibling BtnServer6 + pin_to_sibling BtnServerPlayersTab pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT + pin_to_sibling_corner TOP_LEFT } - BtnServerLatency7 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - pin_to_sibling BtnServer7 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency8 + YDivider2 { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 + ControlName ImagePanel + wide 2 + tall 641 + visible 1 + image "vgui/hud/white" + drawColor "160 157 149 255" + scaleImage 1 + xpos 3 + ypos -1 - pin_to_sibling BtnServer8 + pin_to_sibling BtnServerMapTab pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT + pin_to_sibling_corner TOP_LEFT } - BtnServerLatency9 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - pin_to_sibling BtnServer9 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency10 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - - pin_to_sibling BtnServer10 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency11 + YDivider3 { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 + ControlName ImagePanel + wide 2 + tall 641 + visible 1 + image "vgui/hud/white" + drawColor "160 157 149 255" + scaleImage 1 + xpos 3 + ypos -1 - pin_to_sibling BtnServer11 + pin_to_sibling BtnServerGamemodeTab pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT + pin_to_sibling_corner TOP_LEFT } - BtnServerLatency12 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - pin_to_sibling BtnServer12 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency13 + YDivider4 { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 + ControlName ImagePanel + wide 2 + tall 641 + visible 1 + image "vgui/hud/white" + drawColor "160 157 149 255" + scaleImage 1 + xpos 3 + ypos -1 - pin_to_sibling BtnServer13 + pin_to_sibling BtnServerRegionTab pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT + pin_to_sibling_corner TOP_LEFT } - BtnServerLatency14 - { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 - pin_to_sibling BtnServer14 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - BtnServerLatency15 + // X + XDivider0 { - ControlName Label - labelText "" - classname Serverlatency - textAlignment center - wide 110 - tall 44 - ypos -44 - xpos -1006 + ControlName ImagePanel + wide 1150 + tall 2 + visible 1 + image "vgui/hud/white" + drawColor "160 157 149 255" + scaleImage 1 + ypos 3 + xpos 37 - pin_to_sibling BtnServer15 - pin_corner_to_sibling TOP_LEFT + pin_to_sibling BtnServerRegionTab + pin_corner_to_sibling BOTTOM_LEFT pin_to_sibling_corner BOTTOM_LEFT } - // Dividers: - - // Y - YDivider0 - { - ControlName ImagePanel - wide 2 - tall 641 - visible 1 - image "vgui/hud/white" - drawColor "160 157 149 255" - scaleImage 1 - xpos 3 - ypos -1 - - pin_to_sibling BtnServerNameTab - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - } - - YDivider1 - { - ControlName ImagePanel - wide 2 - tall 641 - visible 1 - image "vgui/hud/white" - drawColor "160 157 149 255" - scaleImage 1 - xpos 3 - ypos -1 - - pin_to_sibling BtnServerPlayersTab - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - } - - YDivider2 - { - ControlName ImagePanel - wide 2 - tall 641 - visible 1 - image "vgui/hud/white" - drawColor "160 157 149 255" - scaleImage 1 - xpos 3 - ypos -1 - - pin_to_sibling BtnServerMapTab - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - } - - YDivider3 - { - ControlName ImagePanel - wide 2 - tall 641 - visible 1 - image "vgui/hud/white" - drawColor "160 157 149 255" - scaleImage 1 - xpos 3 - ypos -1 - - pin_to_sibling BtnServerGamemodeTab - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - } - - YDivider4 - { - ControlName ImagePanel - wide 2 - tall 641 - visible 1 - image "vgui/hud/white" - drawColor "160 157 149 255" - scaleImage 1 - xpos 3 - ypos -1 - - pin_to_sibling BtnServerLatencyTab - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT - } - - // X - XDivider0 - { - ControlName ImagePanel - wide 1150 - tall 2 - visible 1 - image "vgui/hud/white" - drawColor "160 157 149 255" - scaleImage 1 - ypos 3 - xpos 37 - - pin_to_sibling BtnServerNameTab - pin_corner_to_sibling BOTTOM_LEFT - pin_to_sibling_corner BOTTOM_LEFT - } - // List: BtnServerDummmyTop { ControlName RuiButton @@ -2082,7 +2082,7 @@ resource/ui/menus/mods_browse.menu wide 40 tall 562 xpos 2 - ypos -40 + ypos -42 zpos 0 image "vgui/hud/white" @@ -2099,7 +2099,7 @@ resource/ui/menus/mods_browse.menu wide 40 tall 562 xpos 2 - ypos -40 + ypos -42 rui "ui/control_options_description.rpak" @@ -2120,7 +2120,7 @@ resource/ui/menus/mods_browse.menu wide 40 tall 562 xpos 2 - ypos -40 + ypos -42 zpos 1 pin_to_sibling ServerDetailsPanel @@ -2197,7 +2197,7 @@ resource/ui/menus/mods_browse.menu font Default_21 allowRightClickMenu 0 allowSpecialCharacters 0 - unicode 0 + unicode 1 pin_to_sibling BtnSearchLabel pin_corner_to_sibling TOP_LEFT diff --git a/Northstar.Client/mod/scripts/kb_act.lst b/Northstar.Client/mod/scripts/kb_act.lst deleted file mode 100644 index ace98222..00000000 --- a/Northstar.Client/mod/scripts/kb_act.lst +++ /dev/null @@ -1,54 +0,0 @@ -"blank" "==========================" -"blank" "NORTHSTAR" -"blank" "==========================" -"toggleconsole" "Toggle Developer Console" -"blank" "==========================" -"blank" "#KEY_BINDINGS_HEADER_ACTIONS" -"blank" "==========================" -"+attack" "#FIRE" -"+zoom" "#AIM_MODIFIER" -"+toggle_zoom" "#TOGGLE_AIM_MODIFIER" -"+reload" "#RELOAD" -"+weaponCycle" "#SWITCH_WEAPONS_PILOT" -"weaponSelectPrimary0" "#SWITCH_TO_WEAPON1" -"weaponSelectPrimary1" "#SWITCH_TO_WEAPON2" -"weaponSelectPrimary2" "#SWITCH_TO_WEAPON3" -"+melee" "#MELEE" -"+offhand0" "#ORDNANCE_GRENADE" -"+offhand1" "#TACTICAL_ABILITY" -"+offhand2" "#TITAN_UTILITY_BIND" -"+use" "#USE_DISEMBARK" -"+scriptCommand1" "#DISABLE_EJECT_SAFETY_TITAN" -"+ability 1" "#SWITCH_TITAN_AI_MODE_PILOT" -"+ability 6" "#KEYBINDING_MENU_BURN_CARD" -"titan_loadout_select" "#TITAN_LOADOUT_SELECT" -"blank" "==========================" -"blank" "#KEY_BINDINGS_HEADER_MOVEMENT" -"blank" "==========================" -"+forward" "#MOVE_FORWARD" -"+back" "#MOVE_BACK" -"+moveleft" "#MOVE_LEFT" -"+moveright" "#MOVE_RIGHT" -"+speed" "#SPRINT" -"+ability 3" "#JUMP_PILOT_DASH_TITAN" -"+duck" "#CROUCH" -"+toggle_duck" "#TOGGLE_CROUCH" -"blank" "==========================" -"blank" "#KEY_BINDINGS_HEADER_COMMUNICATION" -"blank" "==========================" -"+pushtotalk" "#PUSH_TO_TALK_KEY" -"say" "#CHAT_MESSAGE" -"say_team" "#TEAM_CHAT_MESSAGE" -"blank" "==========================" -"blank" "#KEY_BINDINGS_HEADER_SCOREBOARD" -"blank" "==========================" -"+showscores" "#TOGGLE_SCOREBOARD" -"scoreboard_toggle_focus" "#SCOREBOARD_FOCUS" -"scoreboard_up" "#SCOREBOARD_SCROLL_UP" -"scoreboard_down" "#SCOREBOARD_SCROLL_DOWN" -"scoreboard_profile" "#SCOREBOARD_VIEW_PROFILE" -"scoreboard_mute" "#SCOREBOARD_MUTE" -"blank" "==========================" -"blank" "#KEY_BINDINGS_HEADER_MISCELLANEOUS" -"blank" "==========================" -"jpeg" "#SCREENSHOT" diff --git a/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut b/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut index 66a40cb0..db4865ee 100644 --- a/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut +++ b/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut @@ -1,7 +1,10 @@ untyped global function AddCallback_OnReceivedSayTextMessage -global function NSSetupChathooksClient + +// this is global due to squirrel bridge v3 making native not be able to find non-global funcs properly +// temp fix (surely it will get replaced), do not use this function please (although there isnt rly a downside to it?) +global function CHudChat_ProcessMessageStartThread global struct ClClient_MessageStruct { string message @@ -11,6 +14,7 @@ global struct ClClient_MessageStruct { bool isDead bool isWhisper bool shouldBlock + bool noServerTag } struct { @@ -18,6 +22,10 @@ struct { } NsCustomCallbacksClient void function OnReceivedMessage(ClClient_MessageStruct localMessage) { + + if ( IsWatchingReplay() && localMessage.player == null ) + return + if (localMessage.player != null) { foreach (callbackFunc in NsCustomCallbacksClient.OnReceivedSayTextMessageCallbacks) @@ -29,6 +37,7 @@ void function OnReceivedMessage(ClClient_MessageStruct localMessage) { localMessage.isDead = returnStruct.isDead localMessage.isWhisper = returnStruct.isWhisper localMessage.shouldBlock = localMessage.shouldBlock || returnStruct.shouldBlock + localMessage.noServerTag = returnStruct.noServerTag } } @@ -39,7 +48,13 @@ void function OnReceivedMessage(ClClient_MessageStruct localMessage) { NSChatWriteRaw(1, "\n") - if (localMessage.player == null) NSChatWrite(1, "\x1b[95m") + if (localMessage.player == null) + { + if (!localMessage.noServerTag || localMessage.isWhisper) + { + NSChatWrite(1, "\x1b[95m") + } + } else { bool isFriendly = localMessage.player.GetTeam() == GetLocalClientPlayer().GetTeam() @@ -54,15 +69,18 @@ void function OnReceivedMessage(ClClient_MessageStruct localMessage) { if (localMessage.player == null) { - NSChatWriteRaw(1, Localize("#HUD_CHAT_SERVER_PREFIX") + " ") + if (!localMessage.noServerTag) + { + NSChatWriteRaw(1, Localize("#HUD_CHAT_SERVER_PREFIX") + " ") + } } - else { + else + { NSChatWriteRaw(1, localMessage.playerName) NSChatWriteRaw(1, ": ") } - NSChatWrite(1, "\x1b[0m") - + if (localMessage.player != null || !localMessage.noServerTag || localMessage.isWhisper) NSChatWrite(1, "\x1b[0m") NSChatWrite(1, localMessage.message) } @@ -87,16 +105,19 @@ void function CHudChat_OnReceivedSayTextMessageCallback(int fromPlayerIndex, str fromPlayerName = fromPlayer.GetPlayerNameWithClanTag() } + // Null player + isTeam == true: Server with no tag. + if (messageType == 0 || messageType == 1) { ClClient_MessageStruct localMessage localMessage.message = message localMessage.player = fromPlayer localMessage.playerName = fromPlayerName - localMessage.isTeam = isTeam + localMessage.isTeam = fromPlayer != null && isTeam localMessage.isDead = isDead localMessage.isWhisper = false localMessage.shouldBlock = false + localMessage.noServerTag = fromPlayer == null && isTeam OnReceivedMessage(localMessage) return } @@ -107,10 +128,11 @@ void function CHudChat_OnReceivedSayTextMessageCallback(int fromPlayerIndex, str localMessage.message = message localMessage.player = fromPlayer localMessage.playerName = fromPlayerName - localMessage.isTeam = isTeam + localMessage.isTeam = fromPlayer != null && isTeam localMessage.isDead = isDead localMessage.isWhisper = true localMessage.shouldBlock = false + localMessage.noServerTag = fromPlayer == null && isTeam OnReceivedMessage(localMessage) return } @@ -120,7 +142,3 @@ void function AddCallback_OnReceivedSayTextMessage( ClClient_MessageStruct funct { NsCustomCallbacksClient.OnReceivedSayTextMessageCallbacks.append(callbackFunc) } - -void function NSSetupChathooksClient() { - getroottable().rawset("CHudChat_ProcessMessageStartThread", CHudChat_ProcessMessageStartThread) -} diff --git a/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut b/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut new file mode 100644 index 00000000..3560fd56 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut @@ -0,0 +1,63 @@ +global enum eDiscordGameState +{ + LOADING = 0 + MAINMENU + LOBBY + INGAME +} + +global struct GameStateStruct { + + string map + string mapDisplayname + + string playlist + string playlistDisplayname + + int currentPlayers + int maxPlayers + int ownScore + int otherHighestScore + int maxScore + float timeEnd +} + +global struct UIPresenceStruct { + int gameState +} + +global struct RequiredModInfo +{ + string name + string version +} + +global struct ServerInfo +{ + int index + string id + string name + string description + string map + string playlist + int playerCount + int maxPlayerCount + bool requiresPassword + string region + array< RequiredModInfo > requiredMods +} + +global struct MasterServerAuthResult +{ + bool success + string errorCode + string errorMessage +} + +global struct ModInstallState +{ + int status + int progress + int total + float ratio +} diff --git a/Northstar.Client/mod/scripts/vscripts/client/cl_gamestate.gnut b/Northstar.Client/mod/scripts/vscripts/client/cl_gamestate.gnut index 93be01ea..1baeae9f 100644 --- a/Northstar.Client/mod/scripts/vscripts/client/cl_gamestate.gnut +++ b/Northstar.Client/mod/scripts/vscripts/client/cl_gamestate.gnut @@ -1105,8 +1105,16 @@ void function DisplayPostMatchTop3() RuiSetBool( rui, "isFriendly" + i, localTeam == players[i].GetTeam() ) } } + + if ( GetConVarBool( "hud_takesshots" ) ) + thread TakeScoreboardScreenshot_Delayed() } +void function TakeScoreboardScreenshot_Delayed() +{ + wait 1.5 + GetLocalClientPlayer().ClientCommand( "jpeg" ) +} float function GetGameStartTime() { diff --git a/Northstar.Client/mod/scripts/vscripts/client/cl_minimap.gnut b/Northstar.Client/mod/scripts/vscripts/client/cl_minimap.gnut new file mode 100644 index 00000000..4237a0be --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/client/cl_minimap.gnut @@ -0,0 +1,942 @@ +global function ClMinimap_Init
+
+global function ClientCodeCallback_MinimapEntitySpawned
+
+global function Minimap_AddLayer
+global function Minimap_AddCustomLayer
+
+global function RegisterMinimapPackage
+
+global function Minimap_SetZoomScale
+global function Minimap_SetSizeScale
+global function Minimap_GetZoomScale
+global function Minimap_GetSizeScale
+global function Minimap_IsUsingLargeMinimap
+
+global function Minimap_Ping
+global function ServerCallback_PingMinimap
+
+global function Minimap_EnableDraw
+global function Minimap_DisableDraw
+
+#if DEV
+global function DumpMinimapHandles
+#endif
+
+struct {
+ var minimap_base
+ var minimap_wedges
+
+ int activeMinimapObjectCount
+
+ var minimap_you
+ var minimap_jammed_layer
+
+ var minimap_indicator
+
+ #if DEV
+ table< int, entity > minimapHandles
+ #endif
+
+ array<var> minimapOtherRuis
+
+ float threatMaxDist
+
+ float minimapZoomScale = 1
+ float minimapSizeScale = 1
+
+ bool minimapEnabled = true
+} file
+
+
+struct MinmapPackage
+{
+ asset minimapAsset = $""
+ void functionref( entity, var ) initFunction
+}
+
+table< string, array<MinmapPackage> > minimapAssetMap = {}
+
+const int OF_IS_VISIBLE = 1 << 0
+const int OF_TEAM_SAME = 1 << 1
+const int OF_TEAM_ENEMY = 1 << 2
+const int OF_IN_OUR_PARTY = 1 << 3
+const int OF_IS_OWNED_BY_US = 1 << 4
+const int OF_IS_PLAYER = 1 << 5
+const int OF_IS_NPC = 1 << 6
+const int OF_IS_TITAN = 1 << 7
+const int OF_ORIENT_UP = 1 << 8
+const int OF_NO_TEAM_COLOR = 1 << 9
+
+
+void function RegisterMinimapPackage( string entityClassname, int customStateIndex, asset minimapAsset, void functionref( entity, var ) initFunction )
+{
+ Assert ( (entityClassname in minimapAssetMap), "minimap is not currently setup to handle this type of entity: " + entityClassname )
+
+ MinmapPackage minimapPackage
+ minimapPackage.minimapAsset = minimapAsset
+ minimapPackage.initFunction = initFunction
+
+ switch ( entityClassname )
+ {
+ case "npc_soldier":
+ case "npc_spectre":
+ case "npc_stalker":
+ case "npc_drone":
+ case "npc_frag_drone":
+ case "npc_super_spectre":
+ case "npc_turret_sentry":
+ Assert( customStateIndex > 0 && customStateIndex < eMinimapObject_npc.COUNT )
+ minimapAssetMap[entityClassname].resize( eMinimapObject_npc.COUNT )
+ minimapAssetMap[entityClassname][customStateIndex] = minimapPackage
+ break
+ case "npc_titan":
+ Assert( customStateIndex > 0 && customStateIndex < eMinimapObject_npc_titan.COUNT )
+ minimapAssetMap[entityClassname].resize( eMinimapObject_npc_titan.COUNT )
+ minimapAssetMap[entityClassname][customStateIndex] = minimapPackage
+ break
+
+ case "prop_script":
+ Assert( customStateIndex > 0 && customStateIndex < eMinimapObject_prop_script.COUNT )
+ minimapAssetMap[entityClassname].resize( eMinimapObject_prop_script.COUNT )
+ minimapAssetMap[entityClassname][customStateIndex] = minimapPackage
+ break
+
+ case "info_hardpoint":
+ Assert( customStateIndex > 0 && customStateIndex < eMinimapObject_info_hardpoint.COUNT )
+ minimapAssetMap[entityClassname].resize( eMinimapObject_info_hardpoint.COUNT )
+ minimapAssetMap[entityClassname][customStateIndex] = minimapPackage
+ break
+
+ default:
+ Assert( false, "minimap is not currently setup to handle this type of entity: " + entityClassname )
+ }
+}
+
+void function RegisterDefaultMinimapPackage( string entityClassname, asset minimapAsset, void functionref( entity, var ) initFunction )
+{
+ Assert ( !(entityClassname in minimapAssetMap) )
+
+ MinmapPackage minimapPackage
+ minimapPackage.minimapAsset = minimapAsset
+ minimapPackage.initFunction = initFunction
+
+ minimapAssetMap[entityClassname] <- [minimapPackage]
+}
+
+void function ClMinimap_Init()
+{
+ RegisterDefaultMinimapPackage( "player", $"ui/minimap_player.rpak", MinimapPackage_PlayerInit )
+ RegisterDefaultMinimapPackage( "npc_titan", $"ui/minimap_object.rpak", MinimapPackage_NPCTitanInit )
+ RegisterDefaultMinimapPackage( "npc_soldier", $"ui/minimap_object.rpak", MinimapPackage_NPCHumanSizedInit )
+ RegisterDefaultMinimapPackage( "npc_spectre", $"ui/minimap_object.rpak", MinimapPackage_NPCHumanSizedInit )
+ RegisterDefaultMinimapPackage( "npc_stalker", $"ui/minimap_object.rpak", MinimapPackage_NPCHumanSizedInit )
+ RegisterDefaultMinimapPackage( "npc_super_spectre", $"ui/minimap_object.rpak", MinimapPackage_NPCHumanSizedInit )
+ RegisterDefaultMinimapPackage( "npc_drone_rocket", $"ui/minimap_object.rpak", MinimapPackage_NPCHumanSizedInit )
+ RegisterDefaultMinimapPackage( "npc_frag_drone", $"ui/minimap_object.rpak", MinimapPackage_NPCHumanSizedInit )
+ RegisterDefaultMinimapPackage( "npc_drone", $"ui/minimap_object.rpak", MinimapPackage_NPCHumanSizedInit )
+ RegisterDefaultMinimapPackage( "npc_dropship", $"ui/minimap_object.rpak", MinimapPackage_NPCDropShipInit )
+ RegisterDefaultMinimapPackage( "npc_turret_sentry", $"ui/minimap_object.rpak", MinimapPackage_NPCSentryTurretInit )
+ RegisterDefaultMinimapPackage( "prop_script", $"", MinimapPackage_DummyInit )
+ RegisterDefaultMinimapPackage( "item_titan_battery", $"ui/minimap_fw_battery.rpak", MinimapPackage_BatteryInit )
+ RegisterDefaultMinimapPackage( "item_flag", $"ui/minimap_object.rpak", MinimapPackage_FlagInit )
+ RegisterDefaultMinimapPackage( "item_bomb", $"ui/minimap_object.rpak", MinimapPackage_LTSBomb )
+ RegisterDefaultMinimapPackage( "info_hardpoint", $"", MinimapPackage_DummyInit )
+ RegisterDefaultMinimapPackage( "item_powerup", $"ui/minimap_object.rpak", MinimapPackage_PowerUp )
+
+ RegisterMinimapPackage( "npc_titan", eMinimapObject_npc_titan.AT_BOUNTY_BOSS, $"ui/minimap_object.rpak", MinimapPackage_BossTitanInit )
+
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.AT_DROPZONE_A, $"ui/minimap_obj_area.rpak", MinimapPackage_ATAreaInit )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.AT_DROPZONE_B, $"ui/minimap_obj_area.rpak", MinimapPackage_ATAreaInit )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.AT_DROPZONE_C, $"ui/minimap_obj_area.rpak", MinimapPackage_ATAreaInit )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.AT_BANK, $"ui/minimap_object.rpak", MinimapPackage_ATBank )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FW_BUILDSITE, $"ui/minimap_fw_build_site.rpak", MinimapPackage_FWBuildSite )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FW_BUILDSITE_TURRET, $"ui/minimap_fw_build_site.rpak", MinimapPackage_FWBuildSite )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FW_BUILDSITE_SHIELDED, $"ui/minimap_fw_build_site.rpak", MinimapPackage_FWBuildSite )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FD_HARVESTER, $"ui/minimap_obj_area.rpak", MinimapPackage_FDHarvester )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FD_LOADOUT_CHEST, $"ui/minimap_obj_area.rpak", MinimapPackage_FDLoadoutChest )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FD_BATTERY_EXCHANGE, $"ui/minimap_obj_area.rpak", MinimapPackage_FDBatteryExchange )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.BOOST_STORE, $"ui/minimap_obj_area.rpak", MinimapPackage_BoostStore )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FD_MORTAR_POSITION, $"ui/minimap_mortar_spectre.rpak", MinimapPackage_MortarPosition )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.ARC_TRAP, $"ui/minimap_obj_area.rpak", MinimapPackage_ArcTrap )
+
+ //RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FW_CAMP_A, $"ui/minimap_fw_camp.rpak", MinimapPackage_FWCampA )
+ //RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FW_CAMP_B, $"ui/minimap_fw_camp.rpak", MinimapPackage_FWCampB )
+ //RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.FW_CAMP_C, $"ui/minimap_fw_camp.rpak", MinimapPackage_FWCampC )
+
+ RegisterMinimapPackage( "info_hardpoint", eMinimapObject_info_hardpoint.HARDPOINT_A, $"ui/minimap_obj_area.rpak", MinimapPackage_HardpointA )
+ RegisterMinimapPackage( "info_hardpoint", eMinimapObject_info_hardpoint.HARDPOINT_B, $"ui/minimap_obj_area.rpak", MinimapPackage_HardpointB )
+ RegisterMinimapPackage( "info_hardpoint", eMinimapObject_info_hardpoint.HARDPOINT_C, $"ui/minimap_obj_area.rpak", MinimapPackage_HardpointC )
+
+ //if ( IsPlayingDemo() )
+ {
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.SPAWNZONE_IMC, $"ui/minimap_obj_area.rpak", MinimapPackage_SpawnZoneAreaInit )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.SPAWNZONE_MIL, $"ui/minimap_obj_area.rpak", MinimapPackage_SpawnZoneAreaInit )
+ }
+ //else
+ //{
+ // RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.SPAWNZONE_IMC, $"", MinimapPackage_SpawnZoneAreaInit )
+ // RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.SPAWNZONE_MIL, $"", MinimapPackage_SpawnZoneAreaInit )
+ //}
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.LTS_SITE_A, $"ui/minimap_object.rpak", MinimapPackage_LTSBombSiteA )
+ RegisterMinimapPackage( "prop_script", eMinimapObject_prop_script.LTS_SITE_B, $"ui/minimap_object.rpak", MinimapPackage_LTSBombSiteB )
+ /*
+ {
+ MinmapPackage atAreaPacakage
+ atAreaPacakage.minimapAsset = $"ui/minimap_obj_area.rpak"
+ atAreaPacakage.initFunction = MinimapPackage_ATAreaInit
+ MinmapPackage spawnZonePacakage
+ spawnZonePacakage.minimapAsset = $"ui/minimap_obj_area.rpak"
+ spawnZonePacakage.initFunction = MinimapPackage_SpawnZoneAreaInit
+ MinmapPackage fwBuildSitePackage
+ fwBuildSitePackage.minimapAsset = $"ui/minimap_fw_build_site.rpak"
+ fwBuildSitePackage.initFunction = MinimapPackage_FWBuildSite
+ MinmapPackage fwCampAPackage
+ fwCampAPackage.minimapAsset = $"ui/minimap_fw_camp.rpak"
+ fwCampAPackage.initFunction = MinimapPackage_FWCampA
+ MinmapPackage fwCampBPackage
+ fwCampBPackage.minimapAsset = $"ui/minimap_fw_camp.rpak"
+ fwCampBPackage.initFunction = MinimapPackage_FWCampB
+ MinmapPackage fwCampCPackage
+ fwCampCPackage.minimapAsset = $"ui/minimap_fw_camp.rpak"
+ fwCampCPackage.initFunction = MinimapPackage_FWCampC
+ minimapAssetMap["prop_script"] <-[blankPackage, atAreaPacakage, atAreaPacakage, atAreaPacakage, spawnZonePacakage, spawnZonePacakage,
+ fwCampAPackage, fwCampBPackage, fwCampCPackage,
+ fwBuildSitePackage, fwBuildSitePackage, fwBuildSitePackage ]
+ }
+*/
+
+ AddCreateCallback( "player", OnPlayerCreate )
+
+ float threatMaxDist = Minimap_GetFloatForKey( "threatMaxDist" )
+ float threatDistNear = Minimap_GetFloatForKey( "threatNearDist" )
+ float threatDistFar = Minimap_GetFloatForKey( "threatFarDist" )
+
+ if ( GameRules_GetGameMode() == FORT_WAR )
+ file.threatMaxDist = max( threatMaxDist, 2200 )
+ else
+ file.threatMaxDist = max( threatMaxDist, 1800 )
+
+ file.minimap_base = CreateCockpitRui( $"ui/minimap_base.rpak", MINIMAP_Z_BASE )
+
+ RuiSetFloat( file.minimap_base, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( file.minimap_base, "minimapSizeScale", file.minimapSizeScale )
+
+ file.minimap_wedges = CreateCockpitRui( $"ui/minimap_wedges.rpak", MINIMAP_Z_THREAT_WEDGES )
+
+ RuiSetFloat( file.minimap_wedges, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( file.minimap_wedges, "minimapSizeScale", file.minimapSizeScale )
+ RuiSetBool( file.minimap_wedges, "isVisible", file.minimapZoomScale == 1.0 )
+
+ file.minimap_you = CreateCockpitRui( $"ui/minimap_you.rpak", MINIMAP_Z_YOU )
+
+ RuiSetFloat( file.minimap_you, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( file.minimap_you, "minimapSizeScale", file.minimapSizeScale )
+
+ file.minimap_jammed_layer = null
+
+ file.minimap_indicator = CreateCockpitRui( $"ui/minimap_indicator.rpak", -1 )
+
+ RuiSetFloat( file.minimap_indicator, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( file.minimap_indicator, "minimapSizeScale", file.minimapSizeScale )
+
+ StatusEffect_RegisterEnabledCallback( eStatusEffect.minimap_jammed, MinimapJammed_Enabled )
+ StatusEffect_RegisterDisabledCallback( eStatusEffect.minimap_jammed, MinimapJammed_Disabled )
+ RegisterSignal( "LoopRadarJammerSounds" )
+}
+
+#if DEV
+void function DumpMinimapHandles()
+{
+ int index = 0
+ foreach ( handle, ent in file.minimapHandles )
+ {
+ printt( index, handle, ent )
+ ++index
+ }
+}
+#endif
+
+
+void function Minimap_DisableDraw()
+{
+ file.minimapEnabled = false
+
+ RuiSetDrawGroup( file.minimap_base, RUI_DRAW_NONE )
+ RuiSetDrawGroup( file.minimap_wedges, RUI_DRAW_NONE )
+ RuiSetDrawGroup( file.minimap_you, RUI_DRAW_NONE )
+ RuiSetDrawGroup( file.minimap_indicator, RUI_DRAW_NONE )
+
+ foreach ( var rui in file.minimapOtherRuis )
+ {
+ RuiSetDrawGroup( rui, RUI_DRAW_NONE )
+ }
+}
+
+void function Minimap_EnableDraw()
+{
+ file.minimapEnabled = true
+
+ RuiSetDrawGroup( file.minimap_base, RUI_DRAW_COCKPIT )
+ RuiSetDrawGroup( file.minimap_wedges, RUI_DRAW_COCKPIT )
+ RuiSetDrawGroup( file.minimap_you, RUI_DRAW_COCKPIT )
+ RuiSetDrawGroup( file.minimap_indicator, RUI_DRAW_COCKPIT )
+
+ foreach ( var rui in file.minimapOtherRuis )
+ {
+ RuiSetDrawGroup( rui, RUI_DRAW_COCKPIT )
+ }
+}
+
+
+void function ClientCodeCallback_MinimapEntitySpawned( entity ent )
+{
+ foreach ( callbackFunc in clGlobal.onMinimapEntSpawnedCallbacks )
+ {
+ callbackFunc( ent )
+ }
+
+ if ( ent == GetLocalViewPlayer() )
+ return
+
+ thread AddMinimapObject( ent )
+}
+
+
+asset function GetMinimapAsset( string className, int customState )
+{
+ if ( !(className in minimapAssetMap) )
+ return $""
+
+ if ( customState > minimapAssetMap[className].len() - 1 )
+ return $""
+
+ return minimapAssetMap[className][customState].minimapAsset
+}
+
+
+void function AddMinimapObject( entity ent ) //TODO: If we want radar jammer boost to hide friendly players we need to be able to get the rui handles back.
+{
+ Assert( IsValid( ent ) )
+
+ string className = expect string( ent.GetSignifierName() )
+ int customState = ent.Minimap_GetCustomState()
+
+ asset minimapAsset = GetMinimapAsset( className, customState )
+ if ( minimapAsset == $"" )
+ {
+ return
+ }
+
+ int zOrder = ent.Minimap_GetZOrder()
+ entity viewPlayer = GetLocalViewPlayer()
+
+ ent.SetDoDestroyCallback( true )
+
+ #if DEV
+ int eHandle = ent.Dev_GetEncodedEHandle()
+
+ {
+ array< int > eHandlesToRemove
+ foreach ( eHandleIter, entIter in file.minimapHandles )
+ {
+ if ( !IsValid( entIter ) )
+ {
+ eHandlesToRemove.append( eHandleIter )
+ }
+ }
+
+ foreach ( eHandleIter in eHandlesToRemove )
+ {
+ delete file.minimapHandles[eHandleIter]
+ }
+ }
+
+ if ( eHandle in file.minimapHandles )
+ {
+ // Should have been removed in above loop
+ Assert( IsValid( file.minimapHandles[eHandle] ) )
+
+ DumpMinimapHandles()
+ Assert( false, "Duplicate minimap entity added - " + ent )
+ }
+
+ file.minimapHandles[eHandle] <- ent
+ #endif
+
+ var rui = CreateCockpitRui( minimapAsset, MINIMAP_Z_BASE + zOrder )
+
+ //RuiTrackGameTime( rui, "lastFireTime", ent, RUI_TRACK_LAST_FIRED_TIME )
+
+ RuiTrackFloat3( rui, "playerPos", viewPlayer, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiTrackFloat3( rui, "playerAngles", viewPlayer, RUI_TRACK_EYEANGLES_FOLLOW )
+
+ RuiTrackFloat3( rui, "objectPos", ent, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiTrackFloat3( rui, "objectAngles", ent, RUI_TRACK_EYEANGLES_FOLLOW )
+ RuiTrackInt( rui, "objectFlags", ent, RUI_TRACK_MINIMAP_FLAGS )
+ RuiTrackInt( rui, "customState", ent, RUI_TRACK_MINIMAP_CUSTOM_STATE )
+ RuiSetFloat( rui, "displayDist", file.threatMaxDist )
+ RuiSetFloat( rui, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( rui, "minimapSizeScale", file.minimapSizeScale )
+
+ minimapAssetMap[className][customState].initFunction( ent, rui )
+
+ file.minimapOtherRuis.append( rui )
+
+ RuiSetDrawGroup( rui, file.minimapEnabled ? RUI_DRAW_COCKPIT : RUI_DRAW_NONE )
+ OnThreadEnd(
+ function() : ( rui )
+ {
+ file.minimapOtherRuis.removebyvalue( rui )
+ RuiDestroy( rui )
+ }
+ )
+
+ ent.EndSignal( "OnDestroy" )
+
+ if ( ent.IsPlayer() )
+ {
+ while ( IsValid( ent ) )
+ {
+ WaitSignal( ent, "SettingsChanged", "OnDeath" )
+ }
+ }
+ else
+ {
+ ent.WaitSignal( "OnDestroy" )
+ }
+}
+
+
+void function Minimap_PingCount( vector origin, float radius, float duration, vector color, int count, bool reverse = false )
+{
+ float delay = duration / count
+
+ while ( count )
+ {
+ count--
+
+ Minimap_Ping( origin, radius, delay + (delay * 0.25), color, reverse )
+ wait delay
+ }
+}
+
+
+void function Minimap_Ping( vector origin, float radius, float duration, vector color, bool reverse = false )
+{
+ entity viewPlayer = GetLocalViewPlayer()
+ int zOrder = viewPlayer.Minimap_GetZOrder()
+
+ if ( !file.minimapEnabled )
+ return
+
+ var rui = CreateCockpitRui( $"ui/minimap_ping.rpak", MINIMAP_Z_BASE + zOrder )
+
+ RuiTrackFloat3( rui, "playerPos", viewPlayer, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiTrackFloat3( rui, "playerAngles", viewPlayer, RUI_TRACK_EYEANGLES_FOLLOW )
+
+ RuiSetFloat3( rui, "objColor", color )
+ RuiSetFloat3( rui, "objectPos", origin )
+ RuiSetFloat3( rui, "objectAngles", <0,0,0> )
+
+ RuiSetFloat( rui, "objectRadius", radius / ( file.threatMaxDist * file.minimapZoomScale ) )
+
+ RuiSetFloat( rui, "displayDist", file.threatMaxDist )
+ RuiSetFloat( rui, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( rui, "minimapSizeScale", file.minimapSizeScale )
+
+ RuiSetGameTime( rui, "startTime", Time() )
+ RuiSetGameTime( rui, "endTime", Time() + duration )
+
+ RuiSetBool( rui, "reverse", reverse )
+}
+
+
+
+var function Minimap_AddLayer( asset layerImage, bool isFriendly )
+{
+ entity player = GetLocalViewPlayer()
+
+ var rui = CreateCockpitRui( $"ui/minimap_layer.rpak", MINIMAP_Z_LAYER )
+
+ RuiTrackFloat3( rui, "playerPos", player, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiTrackFloat3( rui, "playerAngles", player, RUI_TRACK_EYEANGLES_FOLLOW )
+
+ asset mapImage = Minimap_GetAssetForKey( "minimap" )
+ float mapCornerX = Minimap_GetFloatForKey( "pos_x" )
+ float mapCornerY = Minimap_GetFloatForKey( "pos_y" )
+ float displayDist = Minimap_GetFloatForKey( "displayDist" )
+ float threatDistNear = Minimap_GetFloatForKey( "threatNearDist" )
+ float threatDistFar = Minimap_GetFloatForKey( "threatFarDist" )
+
+ float mapScale = Minimap_GetFloatForKey( "scale" )
+
+ RuiSetImage( rui, "layerImage", layerImage )
+ RuiSetFloat3( rui, "mapCorner", <mapCornerX, mapCornerY, 0> )
+ RuiSetFloat( rui, "displayDist", file.threatMaxDist )
+ RuiSetFloat( rui, "mapScale", mapScale )
+ RuiSetFloat( rui, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( rui, "minimapSizeScale", file.minimapSizeScale )
+
+ RuiSetBool( rui, "isFriendly", isFriendly )
+
+ return rui
+}
+
+var function Minimap_AddCustomLayer( asset ruiAsset, int sortKey = MINIMAP_Z_LAYER )
+{
+ entity player = GetLocalViewPlayer()
+
+ var rui = CreateCockpitRui( ruiAsset, sortKey )
+
+ RuiTrackFloat3( rui, "playerPos", player, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiTrackFloat3( rui, "playerAngles", player, RUI_TRACK_EYEANGLES_FOLLOW )
+
+ asset mapImage = Minimap_GetAssetForKey( "minimap" )
+ float mapCornerX = Minimap_GetFloatForKey( "pos_x" )
+ float mapCornerY = Minimap_GetFloatForKey( "pos_y" )
+ float displayDist = Minimap_GetFloatForKey( "displayDist" )
+ float threatDistNear = Minimap_GetFloatForKey( "threatNearDist" )
+ float threatDistFar = Minimap_GetFloatForKey( "threatFarDist" )
+
+ float mapScale = Minimap_GetFloatForKey( "scale" )
+
+ RuiSetFloat3( rui, "mapCorner", <mapCornerX, mapCornerY, 0> )
+ RuiSetFloat( rui, "displayDist", file.threatMaxDist )
+ RuiSetFloat( rui, "mapScale", mapScale )
+ RuiSetFloat( rui, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( rui, "minimapSizeScale", file.minimapSizeScale )
+
+ return rui
+}
+
+
+void function OnPlayerCreate( entity player )
+{
+ if ( player != GetLocalViewPlayer() )
+ return
+
+ RuiTrackFloat3( file.minimap_base, "playerPos", player, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiTrackFloat3( file.minimap_base, "playerAngles", player, RUI_TRACK_EYEANGLES_FOLLOW )
+
+ RuiTrackInt( file.minimap_indicator, "indicatorId", player, RUI_TRACK_SCRIPT_NETWORK_VAR_INT, GetNetworkedVariableIndex( "indicatorId" ) )
+
+ asset mapImage = Minimap_GetAssetForKey( "minimap" )
+ float mapCornerX = Minimap_GetFloatForKey( "pos_x" )
+ float mapCornerY = Minimap_GetFloatForKey( "pos_y" )
+ float displayDist = Minimap_GetFloatForKey( "displayDist" )
+ float threatDistNear = Minimap_GetFloatForKey( "threatNearDist" )
+ float threatDistFar = Minimap_GetFloatForKey( "threatFarDist" )
+
+ float mapScale = Minimap_GetFloatForKey( "scale" )
+
+ RuiSetImage( file.minimap_base, "mapImage", mapImage )
+ RuiSetFloat3( file.minimap_base, "mapCorner", <mapCornerX, mapCornerY, 0> )
+ RuiSetFloat( file.minimap_base, "displayDist", file.threatMaxDist )
+ RuiSetFloat( file.minimap_base, "mapScale", mapScale )
+
+ RuiTrackFloat3( file.minimap_wedges, "playerPos", player, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiTrackFloat3( file.minimap_wedges, "playerAngles", player, RUI_TRACK_EYEANGLES_FOLLOW )
+ RuiSetFloat3( file.minimap_wedges, "distances", <threatDistNear / file.threatMaxDist, 1.0 - (threatDistFar / file.threatMaxDist), 1.0> )
+ RuiSetBool( file.minimap_wedges, "isVisible", file.minimapZoomScale == 1.0 )
+
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeCenter", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_CENTER )
+
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid0", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_N )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid1", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_NE )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid2", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_E )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid3", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_SE )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid4", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_S )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid5", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_SW )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid6", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_W )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeMid7", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_NEAR_NW )
+
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter0", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_N )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter1", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_NE )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter2", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_E )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter3", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_SE )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter4", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_S )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter5", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_SW )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter6", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_W )
+ RuiTrackGameTime( file.minimap_wedges, "lastFireTimeOuter7", player, RUI_TRACK_MINIMAP_THREAT_SECTOR, MOTS_FAR_NW )
+
+
+ RuiSetFloat( file.minimap_wedges, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( file.minimap_wedges, "minimapSizeScale", file.minimapSizeScale )
+
+ RuiSetFloat( file.minimap_base, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( file.minimap_base, "minimapSizeScale", file.minimapSizeScale )
+
+ RuiTrackInt( file.minimap_you, "objectFlags", player, RUI_TRACK_MINIMAP_FLAGS )
+ RuiTrackInt( file.minimap_you, "customState", player, RUI_TRACK_MINIMAP_CUSTOM_STATE )
+
+}
+
+
+void function MinimapPackage_DummyInit( entity ent, var rui )
+{
+
+}
+
+void function MinimapPackage_PlayerInit( entity ent, var rui )
+{
+ RuiTrackGameTime( rui, "lastFireTime", ent, RUI_TRACK_LAST_FIRED_TIME )
+ if ( !IsFFAGame() ) //JFS: Too much work to get FFA to work correctly with Minimap logic, so disabling it for FFA
+ {
+ RuiTrackFloat( rui, "sonarDetectedFrac", ent, RUI_TRACK_STATUS_EFFECT_SEVERITY, eStatusEffect.sonar_detected )
+ RuiTrackFloat( rui, "maphackDetectedFrac", ent, RUI_TRACK_STATUS_EFFECT_SEVERITY, eStatusEffect.maphack_detected )
+ }
+}
+
+void function MinimapPackage_NPCTitanInit( entity ent, var rui )
+{
+ entity player = GetLocalClientPlayer()
+
+ RuiSetBool( rui, "useTeamColor", false )
+
+ RuiTrackGameTime( rui, "lastFireTime", ent, RUI_TRACK_LAST_FIRED_TIME )
+ if ( !IsFFAGame() ) //JFS: Too much work to get FFA to work correctly with Minimap logic, so disabling it for FFA
+ RuiTrackFloat( rui, "sonarDetectedFrac", ent, RUI_TRACK_STATUS_EFFECT_SEVERITY, eStatusEffect.sonar_detected )
+}
+
+void function MinimapPackage_NPCHumanSizedInit( entity ent, var rui )
+{
+ entity player = GetLocalClientPlayer()
+
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/minimap/compass_icon_small_dot" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"" )
+
+ //if ( ent == GetLocalClientPlayer().GetPetTitan() )
+ //{
+ // RuiSetBool( rui, "useTeamColor", false )
+ // RuiSetFloat3( rui, "iconColor", TEAM_COLOR_YOU / 255.0 )
+ //}
+ RuiTrackGameTime( rui, "lastFireTime", ent, RUI_TRACK_LAST_FIRED_TIME )
+ //if ( !IsFFAGame() ) //JFS: Too much work to get FFA to work correctly with Minimap logic, so disabling it for FFA
+ // RuiTrackFloat( rui, "sonarDetectedFrac", ent, RUI_TRACK_STATUS_EFFECT_SEVERITY, eStatusEffect.sonar_detected )
+}
+
+void function MinimapPackage_NPCDropShipInit( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/scoreboard/status_evac" )
+}
+
+void function MinimapPackage_NPCSentryTurretInit( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"" )
+}
+
+void function MinimapPackage_BossTitanInit( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/gametype_icons/bounty_hunt/bh_titan" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"rui/hud/gametype_icons/bounty_hunt/bh_titan" )
+ RuiSetBool( rui, "useTeamColor", false )
+}
+
+void function MinimapPackage_BatteryInit( entity ent, var rui )
+{
+ entity player = GetLocalViewPlayer()
+ RuiTrackInt( rui, "batteryCount", player, RUI_TRACK_SCRIPT_NETWORK_VAR_INT, GetNetworkedVariableIndex( "batteryCount" ) )
+ RuiSetBool( rui, "useTeamColor", false )
+ RuiTrackFloat( rui, "batteryCarried", ent, RUI_TRACK_STATUS_EFFECT_SEVERITY, eStatusEffect.battery_carried )
+}
+
+void function MinimapPackage_ATAreaInit( entity ent, var rui )
+{
+ RuiTrackFloat( rui, "objectRadius", ent, RUI_TRACK_MINIMAP_SCALE )
+}
+
+void function MinimapPackage_ATBank( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/gametype_icons/bounty_hunt/bh_bank_icon" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"rui/hud/gametype_icons/bounty_hunt/bh_bank_icon" )
+ RuiSetBool( rui, "useTeamColor", false )
+}
+
+void function MinimapPackage_SpawnZoneAreaInit( entity ent, var rui )
+{
+ RuiTrackFloat( rui, "objectRadius", ent, RUI_TRACK_MINIMAP_SCALE )
+ if ( !IsPlayingDemo() )
+ {
+ RuiSetImage( rui, "centerImage", $"" ) // hide diamond
+ RuiSetImage( rui, "clampedImage", $"rui/hud/gametype_icons/obj_foreground_diamond" )
+ }
+}
+
+void function MinimapPackage_FWBuildSite( entity ent, var rui )
+{
+ entity player = GetLocalViewPlayer()
+ RuiTrackInt( rui, "batteryCount", player, RUI_TRACK_SCRIPT_NETWORK_VAR_INT, GetNetworkedVariableIndex( "batteryCount" ) )
+ //RuiTrackFloat( rui, "objectRadius", ent, RUI_TRACK_MINIMAP_SCALE )
+}
+
+void function MinimapPackage_HardpointA( entity ent, var rui )
+{
+ RuiSetFloat( rui, "objectRadius", 0.001 )
+}
+
+void function MinimapPackage_HardpointB( entity ent, var rui )
+{
+ RuiSetFloat( rui, "objectRadius", 0.001 )
+}
+
+void function MinimapPackage_HardpointC( entity ent, var rui )
+{
+ RuiSetFloat( rui, "objectRadius", 0.001 )
+}
+
+void function MinimapPackage_FDHarvester( entity ent, var rui )
+{
+ RuiSetImage( rui, "centerImage", $"rui/hud/gametype_icons/fd/coop_harvester" )
+ RuiSetImage( rui, "clampedImage", $"rui/hud/gametype_icons/fd/coop_harvester" )
+ RuiSetFloat( rui, "objectRadius", 0.01 )
+ RuiSetBool( rui, "useOverrideColor", true )
+ RuiSetColorAlpha( rui, "overrideColor", <1.0,1.0,1.0>, 1.0 )
+}
+
+void function MinimapPackage_FDLoadoutChest( entity ent, var rui )
+{
+ RuiSetImage( rui, "centerImage", $"rui/hud/gametype_icons/fd/coop_ammo_locker_icon" )
+ RuiSetImage( rui, "clampedImage", $"rui/hud/gametype_icons/fd/coop_ammo_locker_icon" )
+ RuiSetFloat( rui, "objectRadius", 0.01 )
+ RuiSetBool( rui, "useOverrideColor", true )
+ RuiSetColorAlpha( rui, "overrideColor", <1.0,1.0,1.0>, 1.0 )
+}
+
+void function MinimapPackage_FDBatteryExchange( entity ent, var rui )
+{
+ RuiSetImage( rui, "centerImage", $"rui/hud/gametype_icons/bounty_hunt/bh_bank_icon" )
+ RuiSetImage( rui, "clampedImage", $"rui/hud/gametype_icons/bounty_hunt/bh_bank_icon" )
+ RuiSetFloat( rui, "objectRadius", 0.01 )
+ RuiSetBool( rui, "useOverrideColor", true )
+ RuiSetColorAlpha( rui, "overrideColor", <1.0,1.0,1.0>, 1.0 )
+}
+
+void function MinimapPackage_BoostStore( entity ent, var rui )
+{
+ RuiSetImage( rui, "centerImage", $"rui/hud/gametype_icons/bounty_hunt/bh_bonus_icon" )
+ RuiSetImage( rui, "clampedImage", $"rui/hud/gametype_icons/bounty_hunt/bh_bonus_icon" )
+ RuiSetFloat( rui, "objectRadius", 0.01 )
+ RuiSetBool( rui, "useOverrideColor", true )
+ RuiSetColorAlpha( rui, "overrideColor", <1.0,1.0,1.0>, 1.0 )
+}
+
+void function MinimapPackage_MortarPosition( entity ent, var rui )
+{
+ RuiSetImage( rui, "bgImage", $"rui/hud/gametype_icons/fd/fd_icon_spectre_mortar_bg" )
+ RuiSetImage( rui, "centerImage", $"rui/hud/gametype_icons/fd/fd_icon_spectre_mortar" )
+ RuiSetImage( rui, "clampedImage", $"rui/hud/gametype_icons/fd/fd_icon_spectre_mortar" )
+ RuiTrackFloat( rui, "arcPercent", ent, RUI_TRACK_SHIELD_FRACTION )
+}
+
+void function MinimapPackage_ArcTrap( entity ent, var rui )
+{
+ RuiSetImage( rui, "centerImage", $"rui/hud/minimap/compass_icon_arc_trap" )
+ RuiSetImage( rui, "clampedImage", $"" )
+ RuiTrackFloat( rui, "objectRadius", ent, RUI_TRACK_MINIMAP_SCALE )
+}
+
+void function MinimapPackage_FWCampA( entity ent, var rui )
+{
+ RuiTrackInt( rui, "alertLevel", null, RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL_INT, GetNetworkedVariableIndex( "fwCampAlertA" ) )
+ RuiTrackFloat( rui, "objectRadius", ent, RUI_TRACK_MINIMAP_SCALE )
+}
+
+void function MinimapPackage_FWCampB( entity ent, var rui )
+{
+ RuiTrackInt( rui, "alertLevel", null, RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL_INT, GetNetworkedVariableIndex( "fwCampAlertB" ) )
+ RuiTrackFloat( rui, "objectRadius", ent, RUI_TRACK_MINIMAP_SCALE )
+}
+
+void function MinimapPackage_FWCampC( entity ent, var rui )
+{
+ RuiTrackInt( rui, "alertLevel", null, RUI_TRACK_SCRIPT_NETWORK_VAR_GLOBAL_INT, GetNetworkedVariableIndex( "fwCampAlertC" ) )
+ RuiTrackFloat( rui, "objectRadius", ent, RUI_TRACK_MINIMAP_SCALE )
+}
+
+void function MinimapPackage_LTSBombSiteA( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/gametype_icons/last_titan_standing/bomb_site_a_attacking" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"rui/hud/gametype_icons/last_titan_standing/bomb_site_a_attacking" )
+}
+
+void function MinimapPackage_LTSBombSiteB( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/gametype_icons/last_titan_standing/bomb_site_b_attacking" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"rui/hud/gametype_icons/last_titan_standing/bomb_site_b_attacking" )
+}
+
+void function MinimapPackage_LTSBomb( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/gametype_icons/last_titan_standing/bomb_neutral" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"rui/hud/gametype_icons/last_titan_standing/bomb_neutral" )
+ RuiSetBool( rui, "useTeamColor", false )
+}
+
+void function MinimapPackage_FlagInit( entity ent, var rui )
+{
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/gametype_icons/ctf/ctf_flag_neutral" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"rui/hud/gametype_icons/ctf/ctf_flag_neutral" )
+ RuiSetBool( rui, "useTeamColor", true )
+}
+
+void function MinimapPackage_PowerUp( entity ent, var rui )
+{
+ //Battery spawners are the only power ups in use atm. This would need to be updated if we use them differently.
+ RuiSetImage( rui, "defaultIcon", $"rui/hud/battery/battery_capture_friendly" )
+ RuiSetImage( rui, "clampedDefaultIcon", $"rui/hud/battery/battery_capture_friendly" )
+ RuiSetBool( rui, "useTeamColor", false )
+}
+
+
+void function MinimapJammed_Enabled( entity ent, int statusEffect, bool actuallyChanged )
+{
+ if ( !actuallyChanged )
+ return
+
+ if ( ent != GetLocalClientPlayer() )
+ return
+
+ thread LoopRadarJammerSounds( ent )
+ thread FadeOutStaticSoundAfterDelay( ent, BURN_METER_RADAR_JAMMER_PULSE_DURATION - BURN_METER_RADAR_JAMMER_EASE_OFF_TIME )
+
+ if ( file.minimap_jammed_layer != null )
+ RuiDestroy( file.minimap_jammed_layer )
+
+ file.minimap_jammed_layer = Minimap_AddCustomLayer( $"ui/minimap_jammer_layer.rpak", MINIMAP_Z_YOU + 1 )
+ if ( actuallyChanged )
+ RuiSetGameTime( file.minimap_jammed_layer, "startTime", Time() )
+
+ RuiSetFloat( file.minimap_jammed_layer, "minimapZoomScale", file.minimapZoomScale )
+ RuiSetFloat( file.minimap_jammed_layer, "minimapSizeScale", file.minimapSizeScale )
+ RuiTrackFloat( file.minimap_jammed_layer, "scriptAlphaVar", ent, RUI_TRACK_STATUS_EFFECT_SEVERITY, statusEffect )
+
+ RuiTrackFloat( file.minimap_wedges, "scriptInverseAlphaVar", ent, RUI_TRACK_STATUS_EFFECT_SEVERITY, statusEffect )
+
+}
+
+void function MinimapJammed_Disabled( entity ent, int statusEffect, bool actuallyChanged )
+{
+ if ( !actuallyChanged )
+ return
+
+ if ( ent != GetLocalClientPlayer() )
+ return
+
+ clGlobal.levelEnt.Signal( "LoopRadarJammerSounds" )
+
+ if ( file.minimap_jammed_layer != null )
+ {
+ RuiDestroy( file.minimap_jammed_layer )
+ file.minimap_jammed_layer = null
+ }
+}
+
+void function LoopRadarJammerSounds( entity ent )
+{
+ clGlobal.levelEnt.Signal( "LoopRadarJammerSounds" )
+ clGlobal.levelEnt.EndSignal( "LoopRadarJammerSounds" )
+ ent.EndSignal( "OnDeath" )
+
+ OnThreadEnd(
+ function() : ( ent )
+ {
+ StopSoundOnEntity( ent, "HUD_Boost_Card_Radar_Jammer_RedTextBeep_1P" )
+ }
+ )
+
+ float currentTime = Time()
+ float fractionalComponent = currentTime - floor( currentTime )
+ float timeToWait
+ if ( fractionalComponent <= 0.5 )
+ timeToWait = 0.5 - fractionalComponent
+ else
+ timeToWait = 1.5 - fractionalComponent
+
+ wait ( timeToWait ) //Red text flashes in with regards to game time, so we need to wait till the appropriate time (0.5) to play the next sound
+
+ while( true )
+ {
+ if ( IsValid( ent ) )
+ EmitSoundOnEntity( ent, "HUD_Boost_Card_Radar_Jammer_RedTextBeep_1P" )
+
+ wait 1.0 //This is dependent on the rui logic, and will need to be changed if the rui logic changes
+ }
+}
+
+void function FadeOutStaticSoundAfterDelay( entity ent, float delay )
+{
+ EmitSoundOnEntity( ent, "HUD_Boost_Card_Radar_Jammer_Signal_Static_1P" )
+
+ ent.EndSignal( "OnDeath" )
+
+ OnThreadEnd(
+ function() : ( ent )
+ {
+ clGlobal.levelEnt.Signal( "LoopRadarJammerSounds" ) //stop red text beeping sounds
+ if ( IsValid( ent ) )
+ StopSoundOnEntity( ent, "HUD_Boost_Card_Radar_Jammer_Signal_Static_1P" )
+
+ }
+ )
+ wait delay
+}
+void function Minimap_SetZoomScale( float scale )
+{
+ file.minimapZoomScale = scale
+ if(file.minimap_you != null)
+ RuiSetFloat( file.minimap_you, "minimapZoomScale", file.minimapZoomScale )
+ if(file.minimap_indicator != null)
+ RuiSetFloat( file.minimap_indicator, "minimapZoomScale", file.minimapZoomScale )
+ if(file.minimap_base != null)
+ RuiSetFloat( file.minimap_base, "minimapZoomScale", file.minimapZoomScale )
+
+ if ( file.minimap_wedges != null )
+ {
+ RuiSetBool( file.minimap_wedges, "isVisible", file.minimapZoomScale == 1.0 )
+ RuiSetFloat( file.minimap_wedges, "minimapZoomScale", file.minimapZoomScale )
+ }
+ foreach ( var rui in file.minimapOtherRuis )
+ {
+ RuiSetFloat( rui, "minimapZoomScale", file.minimapZoomScale )
+ }
+}
+
+void function Minimap_SetSizeScale( float scale )
+{
+ file.minimapSizeScale = scale
+ if(file.minimap_base != null)
+ RuiSetFloat( file.minimap_base, "minimapSizeScale", file.minimapSizeScale )
+ if(file.minimap_indicator != null)
+ RuiSetFloat( file.minimap_indicator, "minimapSizeScale", file.minimapSizeScale )
+ if(file.minimap_you != null)
+ RuiSetFloat( file.minimap_you, "minimapSizeScale", file.minimapSizeScale )
+ if(file.minimap_wedges != null)
+ RuiSetFloat( file.minimap_wedges, "minimapSizeScale", file.minimapSizeScale )
+ foreach ( var rui in file.minimapOtherRuis )
+ {
+ RuiSetFloat( rui, "minimapSizeScale", file.minimapSizeScale )
+ }
+
+}
+float function Minimap_GetZoomScale()
+{
+ return file.minimapZoomScale
+}
+float function Minimap_GetSizeScale()
+{
+ return file.minimapSizeScale
+}
+bool function Minimap_IsUsingLargeMinimap()
+{
+ return file.minimapSizeScale > 1.0
+}
+
+void function ServerCallback_PingMinimap( float originX, float originY, float originZ, float radius, float duration, float colorR, float colorG, float colorB, int count, bool reverse )
+{
+ if ( count > 1 )
+ thread Minimap_PingCount( <originX, originY, originZ>, radius, duration, <colorR, colorG, colorB>, count, reverse )
+ else
+ Minimap_Ping( <originX, originY, originZ>, radius, duration, <colorR, colorG, colorB>, reverse )
+}
diff --git a/Northstar.Client/mod/scripts/vscripts/client/cl_titan_cockpit.nut b/Northstar.Client/mod/scripts/vscripts/client/cl_titan_cockpit.nut new file mode 100644 index 00000000..8261b3fd --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/client/cl_titan_cockpit.nut @@ -0,0 +1,1676 @@ +untyped + +global function ClTitanCockpit_Init + +global function ServerCallback_TitanEMP +global function ServerCallback_TitanCockpitBoot +global function TitanCockpit_DamageFeedback +global function TitanCockpit_AddPlayer +global function RegisterTitanBindings +global function GetTitanBindings +global function DeregisterTitanBindings +global function ServerCallback_TitanEmbark +global function ServerCallback_TitanDisembark +global function PlayerPressed_EjectEnable // so can be called directly for debugging +global function PlayerPressed_Eject // so can be called directly for debugging +global function TitanCockpit_IsBooting +global function ServerCallback_TitanCockpitEMP +global function TitanCockpit_EMPFadeScale +global function TitanCockpit_DoEMP +global function TitanEMP_Internal +global function ServerCallback_EjectConfirmed +global function LinkCoreHint + +global function AddTitanCockpitManagedRUI +global function UpdateTitanCockpitVisibility +global function TitanCockpitDestroyRui +global function TitanCockpitDoomedThink +global function PlayerEjects +global function IsDisplayingEjectInterface +global function FlashCockpitLight +global function PlayCockpitSparkFX + +global function FlashCockpitHealth + +global function UpdateEjectHud_SetButtonPressTime +global function UpdateEjectHud_SetButtonPressCount + +global function SetUnlimitedDash + +// Added by northstar +global function AddCommonEjectMessage +global function AddRareEjectMessage + +#if MP +global function NetworkedVarChangedCallback_UpdateVanguardRUICoreStatus +global function DisplayFrontierRank +#endif +struct TitanCockpitManagedRUI +{ + bool exists = false + var functionref() create + void functionref() destroy + bool functionref() shouldCreate + int drawGroup = RUI_DRAW_COCKPIT +} + +const TITAN_ALARM_SOUND = "titan_alarm" +const TITAN_NUCLEAR_DEATH_ALARM = "titan_nuclear_death_alarm" +const TITAN_EJECT_BOOST = "titan_eject_boost" +const TITAN_EJECT_ASCENT = "player_eject_windrush" +const TITAN_EJECT_APEX = "player_eject_apex_wind" +const TITAN_EJECT_DESCENT = "player_fallingdescent_windrush" + +const EJECT_MIN_VELOCITY = 200.0 +const EJECT_MAX_VELOCITY = 1000.0 + +struct +{ + var coreHintRui + var cockpitRui + var cockpitLowerRui + var cockpitAdditionalRui + array<TitanCockpitManagedRUI> titanCockpitManagedRUIs + + string lastPilotSettings + + bool isFirstBoot = true + var scorchHotstreakRui + // Added by northstar + array<string> moddedRareEjectMessages + array<string> moddedCommonEjectMessages +} file + +function ClTitanCockpit_Init() +{ + if ( reloadingScripts ) + return + + RegisterSignal( "DisembarkCheck" ) + RegisterSignal( "Rumble_Forward_End" ) + RegisterSignal( "Rumble_Back_End" ) + RegisterSignal( "Rumble_Left_End" ) + RegisterSignal( "Rumble_Right_End" ) + RegisterSignal( "EMP" ) + RegisterSignal( "Ejecting" ) + RegisterSignal( "TitanEMP_Internal" ) + RegisterSignal( "TitanUnDoomed" ) + RegisterSignal( "MonitorPlayerEjectAnimBeingStuck" ) + RegisterSignal( "DisplayFrontierRank" ) + + PrecacheParticleSystem( $"xo_cockpit_spark_01" ) + + if ( !IsModelViewer() && !IsLobby() ) + { + AddCreateCallback( "titan_cockpit", TitanCockpitInit ) + } + + if ( !reloadingScripts ) + { + level.cockpitGeoRef <- null + } + + AddPlayerFunc( TitanCockpit_AddPlayer ) + + AddCinematicEventFlagChangedCallback( CE_FLAG_TITAN_3P_CAM, CinematicEventFlagChanged ) + AddCinematicEventFlagChangedCallback( CE_FLAG_INTRO, CinematicEventFlagChanged ) + + AddCallback_PlayerClassChanged( UpdateLastPlayerSettings ) + + AddTitanCockpitManagedRUI( Scorch_CreateHotstreakBar, Scorch_DestroyHotstreakBar, Scorch_ShouldCreateHotstreakBar, RUI_DRAW_COCKPIT ) //RUI_DRAW_HUD +} + +void function UpdateLastPlayerSettings( entity player ) +{ + if ( IsPilot( player ) ) + file.lastPilotSettings = player.GetPlayerSettings() +} + +TitanBindings function GetTitanBindings() +{ + TitanBindings Table + Table.PlayerPressed_Eject = PlayerPressed_Eject + Table.PlayerPressed_EjectEnable = PlayerPressed_EjectEnable + return Table +} + +bool function RegisterTitanBindings( entity player, TitanBindings bind ) +{ + if ( player != GetLocalViewPlayer() ) + return false + + if ( player != GetLocalClientPlayer() ) + return false + + RegisterConCommandTriggeredCallback( "+useAndReload", bind.PlayerPressed_Eject ) + RegisterConCommandTriggeredCallback( "+use", bind.PlayerPressed_Eject ) + + RegisterConCommandTriggeredCallback( "+scriptCommand1", bind.PlayerPressed_EjectEnable ) + + return true +} + +void function DeregisterTitanBindings( TitanBindings bind ) +{ + DeregisterConCommandTriggeredCallback( "+useAndReload", bind.PlayerPressed_Eject ) + DeregisterConCommandTriggeredCallback( "+use", bind.PlayerPressed_Eject ) + + if ( GetMapName() != "" ) + { + DeregisterConCommandTriggeredCallback( "+scriptCommand1", bind.PlayerPressed_EjectEnable ) + } +} + + +void function TitanCockpit_AddPlayer( entity player ) +{ + if ( IsModelViewer() ) + return + + player.s.lastCockpitDamageSoundTime <- 0 + player.s.inTitanCockpit <- false + player.s.lastDialogTime <- 0 + player.s.titanCockpitDialogActive <- false + player.s.titanCockpitDialogAliasList <- [] + + player.s.hitVectors <- [] +} + +void function TitanCockpitInit( entity cockpit ) +{ + entity player = GetLocalViewPlayer() + Assert( player.GetCockpit() == cockpit ) + + cockpit.s.ejectStartTime <- 0 // placed here to fix http://bugzilla.respawn.net/show_bug.cgi?id=156786 + + if ( !IsAlive( player ) ) + return + + if ( !IsTitanCockpitModelName( cockpit.GetModelName() ) || IsWatchingThirdPersonKillReplay() ) + { + player.s.inTitanCockpit = false + return + } + + if ( !player.s.inTitanCockpit ) + TitanEmbarkDSP( 0.5 ) + + player.s.inTitanCockpit = true + + // code aint callin this currently + CodeCallback_PlayerInTitanCockpit( GetLocalViewPlayer(), GetLocalViewPlayer() ) + + // move this + array<entity> targets = GetClientEntArrayBySignifier( "info_target" ) + foreach ( target in targets ) + { + if ( target.GetTargetName() != "cockpit_geo_ref" ) + continue + + level.cockpitGeoRef = target + } + + entity cockpitParent = expect entity( level.cockpitGeoRef ) + + if ( !IsValid( cockpitParent ) ) + cockpitParent = GetLocalViewPlayer() + + cockpit.s.empInfo <- {} + cockpit.s.empInfo["xOffset"] <- 0 + cockpit.s.empInfo["yOffset"] <- 0 + cockpit.s.empInfo["startTime"] <- 0 + cockpit.s.empInfo["duration"] <- 0 + cockpit.s.empInfo["sub_count"] <- 0 + cockpit.s.empInfo["sub_start"] <- 0 + cockpit.s.empInfo["sub_duration"] <- 0 + cockpit.s.empInfo["sub_pause"] <- 0 + cockpit.s.empInfo["sub_alpha"] <- 0 + + cockpit.s.cockpitType <- 1 + cockpit.s.FOV <- 70 + + cockpit.e.body = CreateCockpitBody( cockpit, player, cockpitParent ) + + thread TitanCockpitAnimThink( cockpit, cockpit.e.body ) + + if ( player.IsTitan() && IsAlive( player ) ) // pilot with titan cockpit gets thrown from titan + thread TitanCockpitDoomedThink( cockpit, player ) + + SetCockpitLightingEnabled( 0, true ) + ShowRUIHUD( cockpit ) +} + +//bind r "script_client ReloadScripts();script_client GetLocalViewPlayer().GetCockpit().Destroy()" +void function ShowRUIHUD( entity cockpit ) +{ + // update topo positions + int cameraAttachId = cockpit.LookupAttachment( "CAMERA" ) + vector cameraOrigin = cockpit.GetAttachmentOrigin( cameraAttachId ) + + int lowerScreenAttachId = cockpit.LookupAttachment( "COCKPIT_HUD_BOTTOM" ) + vector lowerScreenOrigin = cockpit.GetAttachmentOrigin( lowerScreenAttachId ) + vector lowerScreenAngles = cockpit.GetAttachmentAngles( lowerScreenAttachId ) + + int instrument1AttachId = cockpit.LookupAttachment( "COCKPIT_OBJ_1" ) + vector instrument1Origin = cockpit.GetAttachmentOrigin( instrument1AttachId ) + vector instrument1Angles = cockpit.GetAttachmentAngles( instrument1AttachId ) + + lowerScreenOrigin = lowerScreenOrigin - cameraOrigin + vector lowerScreenPosition = <lowerScreenOrigin.x, lowerScreenOrigin.y + TITAN_COCKPIT_LOWER_RUI_SCREEN_SQUARE_SIZE * .5, lowerScreenOrigin.z + (TITAN_COCKPIT_LOWER_RUI_SCREEN_SQUARE_SIZE) * .5> + + instrument1Origin = instrument1Origin - cameraOrigin + vector instrument1Position = <instrument1Origin.x, instrument1Origin.y, instrument1Origin.z> + vector instrument1RightVector = AnglesToRight( instrument1Angles ) * -1 + vector instrument1DownVector = AnglesToUp( instrument1Angles ) * -1 + + RuiTopology_UpdatePos( clGlobal.topoTitanCockpitLowerHud, lowerScreenPosition, <0, -TITAN_COCKPIT_LOWER_RUI_SCREEN_SQUARE_SIZE, 0>, <0, 0, -(TITAN_COCKPIT_LOWER_RUI_SCREEN_SQUARE_SIZE * TITAN_COCKPIT_LOWER_RUI_SCREEN_HEIGHT_SCALE)> ) + RuiTopology_UpdatePos( clGlobal.topoTitanCockpitInstrument1, instrument1Position - (instrument1RightVector * TITAN_COCKPIT_INSTRUMENT1_RUI_SCREEN_SQUARE_SIZE * 0.5) - (instrument1DownVector * TITAN_COCKPIT_INSTRUMENT1_RUI_SCREEN_SQUARE_SIZE * 0.5), instrument1RightVector * TITAN_COCKPIT_INSTRUMENT1_RUI_SCREEN_SQUARE_SIZE, instrument1DownVector * TITAN_COCKPIT_INSTRUMENT1_RUI_SCREEN_SQUARE_SIZE ) + + // create ruis + entity player = GetLocalViewPlayer() + + #if SP + file.coreHintRui = CreateTitanCockpitRui( $"ui/core_hint.rpak" ) + #endif + + file.cockpitRui = CreateTitanCockpitRui( $"ui/ajax_cockpit_base.rpak" ) + RuiTrackFloat3( file.cockpitRui, "playerOrigin", player, RUI_TRACK_ABSORIGIN_FOLLOW ) + RuiTrackFloat3( file.cockpitRui, "playerEyeAngles", player, RUI_TRACK_EYEANGLES_FOLLOW ) + RuiTrackFloat( file.cockpitRui, "healthFrac", player, RUI_TRACK_HEALTH ) + RuiTrackFloat( file.cockpitRui, "shieldFrac", player, RUI_TRACK_SHIELD_FRACTION ) + RuiTrackFloat( file.cockpitRui, "dashFrac", player, RUI_TRACK_PLAYER_SUIT_POWER ) + RuiSetFloat( file.cockpitRui, "ejectManualTimeOut", EJECT_FADE_TIME ) + RuiSetFloat( file.cockpitRui, "ejectButtonTimeOut", TITAN_EJECT_MAX_PRESS_DELAY ) + RuiSetGameTime( file.cockpitRui, "ejectManualStartTime", -60.0 ) + RuiSetGameTime( file.cockpitRui, "ejectButtonPressTime", -60.0 ) + #if MP + string titanName = GetTitanCharacterName( player ) + if ( titanName == "vanguard" ) + { + RuiSetString( file.cockpitRui, "titanInfo1", GetVanguardCoreString( player, 1 ) ) + RuiSetString( file.cockpitRui, "titanInfo2", GetVanguardCoreString( player, 2 ) ) + RuiSetString( file.cockpitRui, "titanInfo3", GetVanguardCoreString( player, 3 ) ) + RuiSetString( file.cockpitRui, "titanInfo4", GetVanguardCoreString( player, 4 ) ) + } + + file.cockpitAdditionalRui = CreateTitanCockpitRui( $"ui/ajax_cockpit_fd.rpak" ) + RuiSetFloat( file.cockpitAdditionalRui, "ejectManualTimeOut", EJECT_FADE_TIME ) + RuiSetFloat( file.cockpitAdditionalRui, "ejectButtonTimeOut", TITAN_EJECT_MAX_PRESS_DELAY ) + RuiSetGameTime( file.cockpitAdditionalRui, "ejectManualStartTime", -60.0 ) + + RuiSetDrawGroup( file.cockpitAdditionalRui, RUI_DRAW_NONE ) + #endif + +#if SP + bool ejectIsAllowed = false +#else + bool ejectIsAllowed = !TitanEjectIsDisabled() +#endif + RuiSetBool( file.cockpitRui, "ejectIsAllowed", ejectIsAllowed ) + + string playerSettings = GetLocalViewPlayer().GetPlayerSettings() + float health = player.GetPlayerModHealth() + float healthPerSegment = GetPlayerSettingsFieldForClassName_HealthPerSegment( playerSettings ) + RuiSetInt( file.cockpitRui, "numHealthSegments", int( health / healthPerSegment ) ) + RuiTrackFloat( file.cockpitRui, "cockpitColor", player, RUI_TRACK_STATUS_EFFECT_SEVERITY, eStatusEffect.cockpitColor ) + + file.cockpitLowerRui = CreateTitanCockpitLowerRui( $"ui/ajax_cockpit_lower.rpak" ) + RuiTrackFloat( file.cockpitLowerRui, "dashFrac", player, RUI_TRACK_PLAYER_SUIT_POWER ) + RuiTrackFloat3( file.cockpitLowerRui, "playerEyeAngles", player, RUI_TRACK_EYEANGLES_FOLLOW ) + RuiTrackFloat( file.cockpitLowerRui, "cockpitColor", player, RUI_TRACK_STATUS_EFFECT_SEVERITY, eStatusEffect.cockpitColor ) + + var instrument1Rui = CreateTitanCockpitInstrument1Rui( $"ui/ajax_cockpit_insturment1.rpak" ) + RuiTrackFloat3( instrument1Rui, "playerEyeAngles", player, RUI_TRACK_EYEANGLES_FOLLOW ) + + int numDashPips = int( floor( 100 / GetSettingsForPlayer_DodgeTable( GetLocalViewPlayer() )["dodgePowerDrain"] ) ) + RuiSetInt( file.cockpitRui, "numDashSegments", numDashPips ) + RuiSetInt( file.cockpitLowerRui, "numDashSegments", numDashPips ) + + thread CockpitDoomedThink( cockpit ) + thread TitanCockpitDestroyRuisOnDeath( cockpit ) + thread TitanCockpitHealthChangedThink( cockpit, player ) + + #if MP + if ( GetCurrentPlaylistVarInt( "aegis_upgrades", 0 ) == 1 && !IsSpectating() && !IsWatchingKillReplay() ) + thread DisplayFrontierRank( file.isFirstBoot ) + #endif + file.isFirstBoot = false + + UpdateTitanCockpitVisibility() +} + +#if MP +void function DisplayFrontierRank( bool isFirstBoot = true ) +{ + GetLocalClientPlayer().Signal( "DisplayFrontierRank" ) + GetLocalClientPlayer().EndSignal( "DisplayFrontierRank" ) + + wait 2.0 + + TitanLoadoutDef titanLoadout = GetTitanLoadoutFromPersistentData( GetLocalClientPlayer(), GetPersistentSpawnLoadoutIndex( GetLocalClientPlayer(), "titan" ) ) + string titanClass = titanLoadout.titanClass + + array<ItemDisplayData> titanUpgrades = FD_GetUpgradesForTitanClass( titanClass ) + int maxActiveIndex + foreach ( index, item in titanUpgrades ) + { + RuiSetImage( file.cockpitAdditionalRui, "upgradeIcon" + (index + 1), item.image ) + RuiSetString( file.cockpitAdditionalRui, "upgradeName" + (index + 1), item.name ) + + if ( !IsSubItemLocked( GetLocalClientPlayer(), item.ref, item.parentRef ) ) + maxActiveIndex++ + } + + RuiSetDrawGroup( file.cockpitAdditionalRui, RUI_DRAW_COCKPIT ) + + bool firstBootDisplay + if ( GameRules_GetGameMode() == FD ) + firstBootDisplay = isFirstBoot || !GetGlobalNetBool( "FD_waveActive" ) + else + firstBootDisplay = isFirstBoot + + RuiSetBool( file.cockpitAdditionalRui, "isFirstBoot", firstBootDisplay ) + RuiSetImage( file.cockpitAdditionalRui, "titanIcon", GetIconForTitanClass( titanClass ) ) + RuiSetInt( file.cockpitAdditionalRui, "titanRank", FD_TitanGetLevel( GetLocalClientPlayer(), titanClass ) ) + RuiSetInt( file.cockpitAdditionalRui, "maxActiveIndex", maxActiveIndex ) + RuiSetGameTime( file.cockpitAdditionalRui, "updateTime", Time() ) + + EmitSoundOnEntity( GetLocalClientPlayer(), "UI_InGame_FD_MetaUpgradeAnnouncement" ) + + if ( firstBootDisplay ) + { + wait 2.0 + + for ( int index = 0; index < maxActiveIndex; index++ ) + { + EmitSoundOnEntity( GetLocalClientPlayer(), "UI_InGame_FD_MetaUpgradeTextAppear" ) + + wait 0.85 + + EmitSoundOnEntity( GetLocalClientPlayer(), "UI_InGame_FD_MetaUpgradeBarFill" ) + + wait 0.15 + } + } + else + { + wait 0.5 + + for ( int index = 0; index < maxActiveIndex; index++ ) + { + EmitSoundOnEntity( GetLocalClientPlayer(), "UI_InGame_FD_MetaUpgradeBarFill" ) + wait 0.05 + } + } +} + +string function GetVanguardCoreString( entity player, int index ) +{ + Assert( player.IsTitan() ) + + if ( !IsConnected() ) //Persistence isn't available when we disconnect + return "" + + if ( player != GetLocalClientPlayer() ) //Client Persistence doesn't know about other players. + return "" + + TitanLoadoutDef loadout = GetActiveTitanLoadout( player ) + + entity soul = player.GetTitanSoul() + if ( !IsValid( soul ) ) + return "" + + if ( index == 1 ) + { + if ( soul.GetTitanSoulNetInt( "upgradeCount" ) >= 1 ) + { + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE1_TITLE" ), Localize( GetItemName( loadout.passive4 ) ) ) + } + else + { + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE1_TITLE" ), Localize( "#UPGRADE_IN_PROGRESS" ) ) + } + } + if ( index == 2 ) + { + if ( soul.GetTitanSoulNetInt( "upgradeCount" ) >= 2 ) + { + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE2_TITLE" ), Localize( GetItemName( loadout.passive5 ) ) ) + } + else + { + if ( soul.GetTitanSoulNetInt( "upgradeCount" ) >= 1 ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE2_TITLE" ), Localize( "#UPGRADE_IN_PROGRESS" ) ) + else + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE2_TITLE" ), Localize( "#UPGRADE_NOT_INSTALLED" ) ) + } + } + if ( index == 3 ) + { + if ( soul.GetTitanSoulNetInt( "upgradeCount" ) >= 3 ) + { + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE3_TITLE" ), Localize( GetItemName( loadout.passive6 ) ) ) + } + else + { + if ( soul.GetTitanSoulNetInt( "upgradeCount" ) >= 2 ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE3_TITLE" ), Localize( "#UPGRADE_IN_PROGRESS" ) ) + else + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE3_TITLE" ), Localize( "#UPGRADE_NOT_INSTALLED" ) ) + } + } + if ( index == 4 ) + { + printt( loadout.passive4 ) + if ( loadout.passive4 == "pas_vanguard_core1" ) // Arc Rounds + { + entity offhandWeapon = player.GetOffhandWeapon( OFFHAND_RIGHT ) + if ( IsValid( offhandWeapon ) && ( offhandWeapon.HasMod( "missile_racks" ) || offhandWeapon.HasMod( "upgradeCore_MissileRack_Vanguard" ) ) ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE4_TITLE" ), Localize( "#GEAR_VANGUARD_CORE2" ) ) + offhandWeapon = player.GetOffhandWeapon( OFFHAND_LEFT ) + if ( IsValid( offhandWeapon ) && ( offhandWeapon.HasMod( "energy_transfer" ) || offhandWeapon.HasMod( "energy_field_energy_transfer" ) ) ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE4_TITLE" ), Localize( "#GEAR_VANGUARD_CORE3" ) ) + } + else if ( loadout.passive4 == "pas_vanguard_core2" ) // Missile Racks + { + entity weapon = player.GetMainWeapons()[0] + if ( IsValid( weapon ) && ( weapon.HasMod( "arc_rounds" ) || weapon.HasMod( "arc_rounds_with_battle_rifle" ) ) ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE4_TITLE" ), Localize( "#GEAR_VANGUARD_CORE1" ) ) + entity offhandWeapon = player.GetOffhandWeapon( OFFHAND_LEFT ) + if ( IsValid( offhandWeapon ) && ( offhandWeapon.HasMod( "energy_transfer" ) || offhandWeapon.HasMod( "energy_field_energy_transfer" ) ) ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE4_TITLE" ), Localize( "#GEAR_VANGUARD_CORE3" ) ) + } + else if ( loadout.passive4 == "pas_vanguard_core3" ) // Energy Transfer + { + entity weapon = player.GetMainWeapons()[0] + if ( IsValid( weapon ) && ( weapon.HasMod( "arc_rounds" ) || weapon.HasMod( "arc_rounds_with_battle_rifle" ) ) ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE4_TITLE" ), Localize( "#GEAR_VANGUARD_CORE1" ) ) + entity offhandWeapon = player.GetOffhandWeapon( OFFHAND_RIGHT ) + if ( IsValid( offhandWeapon ) && ( offhandWeapon.HasMod( "missile_racks" ) || offhandWeapon.HasMod( "upgradeCore_MissileRack_Vanguard" ) ) ) + return Localize( "#TITAN_UPGRADE_STATUS_N_N", Localize( "#TITAN_UPGRADE4_TITLE" ), Localize( "#GEAR_VANGUARD_CORE2" ) ) + } + return "" + } + + unreachable +} +#endif + +void function SetUnlimitedDash( bool active ) +{ + if ( file.cockpitLowerRui == null ) + return + + RuiSetBool( file.cockpitLowerRui, "hasUnlimitedDash", active ) +} + +void function UpdateEjectHud_SetManualEjectStartTime( entity player ) +{ + float timeNow = Time() + player.p.ejectEnableTime = timeNow + + if ( file.cockpitRui != null ) + RuiSetGameTime( file.cockpitRui, "ejectManualStartTime", timeNow ) + + if ( file.cockpitAdditionalRui != null ) + RuiSetGameTime( file.cockpitAdditionalRui, "ejectManualStartTime", timeNow ) +} + +void function UpdateEjectHud_SetButtonPressTime( entity player ) +{ + float timeNow = Time() + player.p.ejectPressTime = timeNow + + if ( file.cockpitRui != null ) + RuiSetGameTime( file.cockpitRui, "ejectButtonPressTime", timeNow ) + + //if ( file.cockpitAdditionalRui != null ) + // RuiSetGameTime( file.cockpitAdditionalRui, "ejectButtonPressTime", timeNow ) +} + +void function UpdateEjectHud_SetButtonPressCount( entity player, int buttonCount ) +{ + player.p.ejectPressCount = buttonCount + + if ( file.cockpitRui != null ) + RuiSetInt( file.cockpitRui, "ejectButtonCount", buttonCount ) + + //if ( file.cockpitAdditionalRui != null ) + // RuiSetInt( file.cockpitAdditionalRui, "ejectButtonCount", buttonCount ) +} + +void function UpdateTitanCockpitVisibility() +{ + entity player = GetLocalViewPlayer() + if ( !IsValid( player ) ) + return + + if ( Tone_ShouldCreateTrackerHud( player ) ) + thread Tone_HudThink( player ) + else + player.Signal( "StopToneHud" ) + + foreach ( managedRUI in file.titanCockpitManagedRUIs ) + { + bool shouldCreate = managedRUI.shouldCreate() + if ( !managedRUI.exists && shouldCreate ) + { + var rui = managedRUI.create() + + bool found = false + foreach ( cockpitRui in player.p.titanCockpitRUIs ) + { + if ( cockpitRui.rui == rui ) + found = true + } + if ( !found ) + { + TitanCockpitRUI tcRUI + tcRUI.rui = rui + tcRUI.drawGroup = managedRUI.drawGroup + player.p.titanCockpitRUIs.append( tcRUI ) + } + + managedRUI.exists = true + } + else if ( managedRUI.exists && !shouldCreate ) + { + managedRUI.destroy() + managedRUI.exists = false + } + } + + bool isVisible = true + + int ceFlags = player.GetCinematicEventFlags() + if ( (ceFlags & CE_FLAG_INTRO) || (ceFlags & CE_FLAG_TITAN_3P_CAM) ) + isVisible = false + if ( clGlobal.isSoloDialogMenuOpen ) + isVisible = false + + for ( int i = player.p.titanCockpitRUIs.len() - 1; i >= 0; i-- ) + { + TitanCockpitRUI tcRUI = player.p.titanCockpitRUIs[ i ] + RuiSetDrawGroup( tcRUI.rui, isVisible ? tcRUI.drawGroup : RUI_DRAW_NONE ) + } +} + +void function AddTitanCockpitManagedRUI( var functionref() createFunc, void functionref() destroyFunc, bool functionref() shouldCreateFunc, int drawGroup ) +{ + TitanCockpitManagedRUI managedRUI + managedRUI.create = createFunc + managedRUI.destroy = destroyFunc + managedRUI.shouldCreate = shouldCreateFunc + managedRUI.drawGroup = drawGroup + + file.titanCockpitManagedRUIs.append( managedRUI ) +} + +void function CinematicEventFlagChanged( entity player ) +{ + UpdateTitanCockpitVisibility() +} + +void function CockpitDoomedThink( entity cockpit ) +{ + entity player = GetLocalViewPlayer() + cockpit.EndSignal( "OnDestroy" ) + + while ( IsAlive( player ) ) + { + entity soul = player.GetTitanSoul() + if ( !IsValid( soul ) ) //Defensive fix for bug 227087. Assumption is that the cockpit is likely to be destroyed soon if the soul is invalid. + return + if ( !soul.IsDoomed() ) + player.WaitSignal( "Doomed" ) + + SetCockpitUIDoomedState( true ) + + if ( !IsValid( soul ) ) //Defensive fix for bug 227087. Assumption is that the cockpit is likely to be destroyed soon if the soul is invalid. + return + if ( soul.IsDoomed() ) + player.WaitSignal( "TitanUnDoomed" ) + + SetCockpitUIDoomedState( false ) + } +} + +void function SetCockpitUIEjectingState( bool state ) +{ + if ( file.cockpitRui != null ) + RuiSetBool( file.cockpitRui, "isEjecting", state ) + + if ( file.cockpitAdditionalRui != null ) + RuiSetBool( file.cockpitAdditionalRui, "isEjecting", state ) + + if ( file.cockpitLowerRui != null ) + { + RuiSetBool( file.cockpitLowerRui, "isEjecting", state ) + if ( state ) + RuiSetString( file.cockpitLowerRui, "ejectPrompt", Localize( RollRandomEjectString() ) ) + else + RuiSetString( file.cockpitLowerRui, "ejectPrompt", "" ) + } +} + +void function SetCockpitUIDoomedState( bool state ) +{ + if ( file.cockpitRui != null ) + RuiSetBool( file.cockpitRui, "isDoomed", state ) + + if ( file.cockpitAdditionalRui != null ) + RuiSetBool( file.cockpitAdditionalRui, "isDoomed", state ) +} + +void function TitanCockpitDestroyRui( var ruiToDestroy ) +{ + if ( ruiToDestroy == null ) + return + + entity player = GetLocalViewPlayer() + + for ( int i = player.p.titanCockpitRUIs.len() - 1; i >= 0; i-- ) + { + TitanCockpitRUI tcRUI = player.p.titanCockpitRUIs[ i ] + if ( tcRUI.rui == ruiToDestroy ) + { + RuiDestroy( tcRUI.rui ) + player.p.titanCockpitRUIs.remove( i ) + } + } +} + +void function TitanCockpitDestroyRuisOnDeath( entity cockpit ) +{ + entity player = GetLocalViewPlayer() + + OnThreadEnd( + function() : ( cockpit ) + { + foreach ( managedRUI in file.titanCockpitManagedRUIs ) + { + if ( managedRUI.exists ) + { + managedRUI.destroy() + managedRUI.exists = false + } + } + + entity player = GetLocalViewPlayer() + for ( int i = player.p.titanCockpitRUIs.len() - 1; i >= 0; i-- ) + { + RuiDestroy( player.p.titanCockpitRUIs[ i ].rui ) + player.p.titanCockpitRUIs.remove( i ) + } + + player = GetLocalClientPlayer() + if ( IsValid( player ) ) + player.Signal( "DisplayFrontierRank" ) + file.cockpitAdditionalRui = null + file.cockpitRui = null + file.cockpitLowerRui = null + file.coreHintRui = null + } + ) + + player.EndSignal( "OnDeath" ) + cockpit.EndSignal( "OnDestroy" ) + WaitForever() +} + +function CockpitBodyThink( cockpit, cockpitBody ) +{ + cockpitBody.EndSignal( "OnDestroy" ) + + cockpit.WaitSignal( "OnDestroy" ) + + cockpitBody.Destroy() +} + + +entity function CreateCockpitBody( entity cockpit, entity player, entity cockpitParent ) +{ + #if SP + string bodySettings = DEFAULT_PILOT_SETTINGS + #else + string bodySettings = file.lastPilotSettings + if ( bodySettings == "" || bodySettings == "spectator" ) + bodySettings = Loadouts_GetSetFileForRequestedClass( player ) + if ( bodySettings == "" ) + bodySettings = "pilot_base" + #endif + + asset bodyModelName = GetPlayerSettingsAssetForClassName( bodySettings, "armsmodel" ) + #if DEV + if ( bodySettings == "" ) + { + CodeWarning( "Couldn't find armsmodel for set file: " + bodySettings ) + } + #endif + + entity cockpitBody = CreateClientSidePropDynamic( cockpitParent.GetOrigin(), Vector( 0, 0, 0 ), bodyModelName ) + cockpitBody.EnableRenderWithCockpit() + cockpitBody.SetOrigin( cockpit.GetOrigin() ) + cockpitBody.SetParent( cockpit ) + + thread CockpitBodyThink( cockpit, cockpitBody ) + + return cockpitBody +} + +function TitanEmbarkDSP( transitionTime ) +{ +} + +function TitanDisembarkDSP( transitionTime ) +{ +} + +function TitanCockpit_EMPFadeScale( entity cockpit, elapsedMod = 0 ) +{ + local fadeInTime = 0.0 + local fadeOutTime = 1.5 + local elapsedTime = Time() - cockpit.s.empInfo.startTime + elapsedTime += elapsedMod + + // ToDo: + // Fade in/out from last frames amount so it doesnt pop + // Make strength var to control max fade ( less strength returns max of like 0.5 ) + + //------------------------ + // EMP effect is finished + //------------------------ + + //printt( "elapsedTime:" + elapsedTime + " cockpit.s.empInfo.duration:" + cockpit.s.empInfo.duration + " fadeOutTime:" + fadeOutTime ) + if ( elapsedTime < cockpit.s.empInfo.duration - fadeOutTime ) + { + return 1.0 + } + + + if ( elapsedTime >= fadeInTime + cockpit.s.empInfo.duration + fadeOutTime ) + { + cockpit.s.empInfo.startTime = 0 + return 0.0 + } + + //------------------------ + // EMP effect is starting + //------------------------ + + if ( elapsedTime < fadeInTime ) + { + return GraphCapped( elapsedTime, 0.0, fadeInTime, 0.0, 1.0 ) + } + + //---------------------- + // EMP effect is ending + //---------------------- + + if ( elapsedTime > fadeInTime + cockpit.s.empInfo.duration ) + { + cockpit.s.empInfo["sub_count"] = 0 + return GraphCapped( elapsedTime, fadeInTime + cockpit.s.empInfo.duration, fadeInTime + cockpit.s.empInfo.duration + fadeOutTime, 1.0, 0.0 ) + } + + //--------------------- + // EMP flicker effect + //--------------------- + + // Time to start a new flicker + if ( cockpit.s.empInfo["sub_start"] == 0 ) + { + cockpit.s.empInfo["sub_start"] <- Time() + if ( cockpit.s.empInfo["sub_count"] == 0 ) + cockpit.s.empInfo["sub_pause"] <- RandomFloatRange( 0.5, 1.5 ) + else + cockpit.s.empInfo["sub_pause"] <- RandomFloat( 0.5 ) + cockpit.s.empInfo["sub_duration"] <- RandomFloatRange( 0.1, 0.4 ) + cockpit.s.empInfo["sub_alpha"] <- RandomFloatRange( 0.4, 0.9 ) + cockpit.s.empInfo["sub_count"]++; + } + local flickerElapsedTime = Time() - cockpit.s.empInfo["sub_start"] + + // Start a new flicker if the current one is finished + if ( flickerElapsedTime > cockpit.s.empInfo["sub_pause"] + cockpit.s.empInfo["sub_duration"] ) + cockpit.s.empInfo["sub_start"] = 0 + + if ( flickerElapsedTime < cockpit.s.empInfo["sub_pause"] ) + { + // Pause before the flicker + return 1.0 + } + else if ( flickerElapsedTime < cockpit.s.empInfo["sub_pause"] + ( cockpit.s.empInfo["sub_duration"] / 2.0 ) ) + { + // First half of the flicker + return GraphCapped( flickerElapsedTime, 0.0, cockpit.s.empInfo["sub_duration"] / 2.0, 1.0, cockpit.s.empInfo["sub_alpha"] ) + } + else + { + // Second half of the flicker + return GraphCapped( flickerElapsedTime, cockpit.s.empInfo["sub_duration"] / 2.0, cockpit.s.empInfo["sub_duration"], cockpit.s.empInfo["sub_alpha"], 1.0 ) + } +} + +function ServerCallback_TitanCockpitEMP( duration ) +{ + thread TitanCockpit_DoEMP( duration / 4 ) +} + +function TitanCockpit_DoEMP( duration ) +{ + entity player = GetLocalViewPlayer() + entity cockpit = player.GetCockpit() + + if ( !IsValid( cockpit ) ) + return + + if ( !player.IsTitan() ) + return + + if ( !player.s.inTitanCockpit ) + return + + Signal( player, "EMP" ) + EndSignal( player, "EMP" ) + player.EndSignal( "OnDestroy" ) + + // this needs tweaking... looks a bit artificial + ClientCockpitShake( 0.25, 3, 1.0, Vector( 0, 0, 1 ) ) // amplitude, frequency, duration, direction + + thread PlayCockpitEMPLights( cockpit, duration ) + + // Start the screens and vdu power outages + cockpit.s.empInfo.xOffset = RandomFloatRange( 0.5, 0.75 ) + cockpit.s.empInfo.yOffset = RandomFloatRange( 0.5, 0.75 ) + if ( CoinFlip() ) + cockpit.s.empInfo.xOffset *= -1 + if ( CoinFlip() ) + cockpit.s.empInfo.yOffset *= -1 + + cockpit.s.empInfo.startTime = Time() + cockpit.s.empInfo.duration = duration + + EmitSoundOnEntity( player, EMP_IMPARED_SOUND ) + wait duration + FadeOutSoundOnEntity( player, EMP_IMPARED_SOUND, 1.5 ) +} + +function PlayCockpitEMPLights( cockpit, duration ) +{ + duration += 1.5 // blend out + local attachID + local origin + local angles + local fxLights = [] + + string tagName = "COCKPIT" // SCR_CL_BL" + attachID = cockpit.LookupAttachment( tagName ) + origin = cockpit.GetAttachmentOrigin( attachID ) + origin.z -= 25 + angles = Vector( 0, 0, 0 ) + local lightTable = {} + lightTable.light <- CreateClientSideDynamicLight( origin, angles, Vector( 0.0, 0.0, 0.0 ), 80.0 ) + lightTable.modulate <- true + fxLights.append( lightTable ) + + wait 0.5 + + foreach ( fxLight in fxLights ) + { + fxLight.light.SetCockpitLight( true ) + } + + local startTime = Time() + local rate = 1.2 + + local endTime = Time() + duration + + while ( IsValid( cockpit ) ) + { + if ( Time() > endTime ) + break + + float subtractColor = GraphCapped( Time(), endTime - 0.25, endTime, 1.0, 0.0 ) + local pulseFrac = GetPulseFrac( rate, startTime ) + pulseFrac *= subtractColor + //pulseFrac -= fadeInColor + + foreach ( index, fxLight in fxLights ) + { + Assert( fxLight.modulate ) + fxLight.light.SetLightColor( Vector( pulseFrac, 0, 0 ) ) + + // the case where fxLight.modulate == false used to be handled by this script, which used undefined variable fadeInColor: + // fxLight.light.SetLightColor( Vector( fadeInColor, fadeInColor, fadeInColor ) ) + } + + WaitFrame() + } + + foreach ( fxLight in fxLights ) + { + fxLight.light.Destroy() + } +} + + +function TitanCockpit_IsBooting( cockpit ) +{ + return cockpit.GetTimeInCockpit() < 1.3 +} + +function TitanCockpitAnimThink( cockpit, body ) +{ + cockpit.SetOpenViewmodelOffset( 20.0, 0.0, 10.0 ) + cockpit.Anim_NonScriptedPlay( "atpov_cockpit_hatch_close_idle" ) + + if ( body ) + body.Anim_NonScriptedPlay( "atpov_cockpit_hatch_close_idle" ) +} + + +bool function IsDisplayingEjectInterface( entity player ) +{ + if ( !player.IsTitan() ) + return false + + if ( player.ContextAction_IsMeleeExecution() ) //Could just check for ContextAction_IsActive() if we need to be more general + return false + + if ( !GetDoomedState( player ) && Time() - player.p.ejectEnableTime > EJECT_FADE_TIME ) + return false + + if ( Riff_TitanExitEnabled() == eTitanExitEnabled.Never || Riff_TitanExitEnabled() == eTitanExitEnabled.DisembarkOnly ) + return false + + //if ( !CanDisembark( player ) ) + // return false + + return true +} + +void function PlayerPressed_Eject( entity player ) +{ + if ( !IsDisplayingEjectInterface( player ) ) + return + + if ( Time() - player.p.ejectPressTime > TITAN_EJECT_MAX_PRESS_DELAY ) + UpdateEjectHud_SetButtonPressCount( player, 0 ) + + if ( !IsAlive( player ) ) + return + + EmitSoundOnEntity( player, "titan_eject_xbutton" ) + EmitSoundOnEntity( player, "hud_boost_card_radar_jammer_redtextbeep_1p" ) + UpdateEjectHud_SetButtonPressTime( player ) + UpdateEjectHud_SetButtonPressCount( player, (player.p.ejectPressCount + 1) ) + + player.ClientCommand( "TitanEject " + player.p.ejectPressCount ) + + entity cockpit = player.GetCockpit() + if ( player.p.ejectPressCount < 3 || cockpit.s.ejectStartTime ) + return + + PlayerEjects( player, cockpit ) +} + +void function AddCommonEjectMessage( string message ) +{ + file.moddedCommonEjectMessages.append( message ) +} + +void function AddRareEjectMessage( string message ) +{ + file.moddedRareEjectMessages.append( message ) +} + +string function RollRandomEjectString() +{ + const int COCKPIT_EJECT_COMMON_COUNT = 6 + const int COCKPIT_EJECT_RARE_COUNT = 36 + const float CHANCE_FOR_RARE = 0.15 + + float randForType = RandomFloat( 1.0 ) + if ( randForType < CHANCE_FOR_RARE ) + { + int index = RandomInt( COCKPIT_EJECT_RARE_COUNT + file.moddedRareEjectMessages.len() ) + if ( index < COCKPIT_EJECT_RARE_COUNT ) + return "#COCKPIT_EJECT_RARE_" + index + else + return file.moddedRareEjectMessages[index - COCKPIT_EJECT_RARE_COUNT] + } + + int index = RandomInt( COCKPIT_EJECT_COMMON_COUNT + file.moddedCommonEjectMessages.len() ) + if ( index < COCKPIT_EJECT_COMMON_COUNT ) + return "#COCKPIT_EJECT_COMMON_" + index + else + return file.moddedCommonEjectMessages[index - COCKPIT_EJECT_COMMON_COUNT] + + unreachable +} + +void function PlayerEjects( entity player, entity cockpit ) //Note that this can be run multiple times in a frame, e.g. get damaged by 4 pellets of a shotgun that brings the Titan into a doomed state with auto eject. Not ideal +{ + // prevent animation from playing if player is in the middle of execution + if ( player.ContextAction_IsActive() && !player.ContextAction_IsBusy() ) + return + + player.Signal( "Ejecting" ) + + SetCockpitUIEjectingState( true ) + + local ejectAlarmSound + cockpit.s.ejectStartTime = Time() + string animationName + if ( GetNuclearPayload( player ) > 0 ) + { + animationName = "atpov_cockpit_eject_nuclear" + cockpit.Anim_NonScriptedPlay( animationName ) + if ( IsValid( cockpit.e.body ) ) + cockpit.e.body.Anim_NonScriptedPlay( "atpov_cockpit_eject_nuclear" ) + ejectAlarmSound = TITAN_NUCLEAR_DEATH_ALARM + } + else + { + animationName = "atpov_cockpit_eject" + cockpit.Anim_NonScriptedPlay( animationName ) + if ( IsValid( cockpit.e.body ) ) + cockpit.e.body.Anim_NonScriptedPlay( "atpov_cockpit_eject" ) + + ejectAlarmSound = TITAN_ALARM_SOUND + } + + thread LightingUpdateAfterOpeningCockpit() + thread EjectAudioThink( player, ejectAlarmSound ) + + float animDuration = cockpit.GetSequenceDuration( animationName ) + + thread MonitorPlayerEjectAnimBeingStuck( player, animDuration ) +} + +void function MonitorPlayerEjectAnimBeingStuck( entity player, float duration ) +{ + player.Signal( "MonitorPlayerEjectAnimBeingStuck" ) + player.EndSignal( "MonitorPlayerEjectAnimBeingStuck" ) + player.EndSignal( "OnDeath" ) + player.EndSignal( "OnDestroy" ) + player.EndSignal( "SettingsChanged" ) + + + wait duration + 2.0 // 1s as a buffer + + if ( player.IsTitan() ) + { + entity cockpit = player.GetCockpit() + cockpit.Anim_NonScriptedPlay( "atpov_cockpit_hatch_close_idle" ) + if ( IsValid( cockpit.e.body ) ) + cockpit.e.body.Anim_NonScriptedPlay( "atpov_cockpit_hatch_close_idle" ) + + SetCockpitUIEjectingState( false ) + } +} + +function ServerCallback_EjectConfirmed() +{ + if ( !IsWatchingReplay() ) + return + + entity player = GetLocalViewPlayer() + entity cockpit = player.GetCockpit() + + if ( !cockpit || !IsTitanCockpitModelName( cockpit.GetModelName() ) ) + return + + PlayerEjects( player, cockpit ) +} + +function EjectAudioThink( entity player, ejectAlarmSound = TITAN_ALARM_SOUND ) +{ + EmitSoundOnEntity( player, ejectAlarmSound ) + TitanCockpit_PlayDialog( player, "manualEjectNotice" ) + + player.EndSignal( "OnDeath" ) + + player.WaitSignal( "SettingsChanged" ) + + if ( player.GetPlayerClass() != "pilot" ) + return + + OnThreadEnd( + function() : ( player ) + { + if ( !IsAlive( player ) ) + { + StopSoundOnEntity( player, TITAN_EJECT_ASCENT ) + StopSoundOnEntity( player, TITAN_EJECT_DESCENT ) + } + else + { + FadeOutSoundOnEntity( player, TITAN_EJECT_ASCENT, 0.25 ) + FadeOutSoundOnEntity( player, TITAN_EJECT_DESCENT, 0.25 ) + } + + StopSoundOnEntity( player, TITAN_EJECT_APEX ) + } + ) + + EmitSoundOnEntity( player, TITAN_EJECT_BOOST ) + + float startTime = Time() + float duration = GetSoundDuration( TITAN_EJECT_ASCENT ) + EmitSoundOnEntity( player, TITAN_EJECT_ASCENT ) + float timeOut = duration - 0.25 + vector velocity + float diff = 0.0 + + const int STAGE_ASCENT = 1 + const int STAGE_APEX = 2 + const int STAGE_DESCENT = 3 + + int ejectStage = STAGE_ASCENT + + string currentSound = TITAN_EJECT_ASCENT + + while ( diff < timeOut ) + { + PerfStart( 127 ) + + diff = (Time() - startTime) + + velocity = player.GetVelocity() + float length = Length( velocity ) + + if ( diff > 0.5 ) + { + if ( player.IsOnGround() ) + { + PerfEnd( 127 ) + break + } + } + + if ( ejectStage != STAGE_DESCENT && velocity.z < 0 ) + { + FadeOutSoundOnEntity( player, TITAN_EJECT_ASCENT, 0.25 ) + timeOut = GetSoundDuration( TITAN_EJECT_DESCENT ) + EmitSoundOnEntity( player, TITAN_EJECT_DESCENT ) + currentSound = TITAN_EJECT_DESCENT + ejectStage = STAGE_DESCENT + } + else if ( ejectStage == STAGE_ASCENT && length < 400 ) + { + EmitSoundOnEntity( player, TITAN_EJECT_APEX ) + ejectStage = STAGE_APEX + } + + PerfEnd( 127 ) + + WaitFrame() + } +} + +function LightingUpdateAfterOpeningCockpit() +{ + while ( true ) + { + if ( !GetLocalViewPlayer().s.inTitanCockpit ) + break + WaitFrame() + } + + SetCockpitLightingEnabled( 0, false ) +} + + +function TonemappingUpdateAfterOpeningCockpit() //Deprecated, no longer used +{ + local duration = 3 + local tonemapMin = 2 + local tonemapMax = 5 + + while ( true ) + { + if ( !GetLocalViewPlayer().s.inTitanCockpit ) + break + WaitFrame() + } + + SetCockpitLightingEnabled( 0, false ) + + AutoExposureSetExposureCompensationBias( tonemapMax ) + AutoExposureSnap() + wait( 0.1 ) + + TitanDisembarkDSP( 0.5 ) + + local startTime = Time() + while ( true ) + { + local time = Time() - startTime + float factor = GraphCapped( time, 0, duration, 1, 0 ) + factor = factor * factor * factor + local toneMapScale = tonemapMin + (tonemapMax - tonemapMin) * factor + AutoExposureSetExposureCompensationBias( toneMapScale ) + AutoExposureSnap() + wait 0 + if ( factor == 0 ) + break + } + + AutoExposureSetExposureCompensationBias( 0 ) +} + +function ServerCallback_TitanEmbark() +{ + TitanCockpit_PlayDialog( GetLocalViewPlayer(), "embark" ) +} + +function ServerCallback_TitanDisembark() +{ + entity player = GetLocalViewPlayer() + + thread LightingUpdateAfterOpeningCockpit() + + //HideFriendlyIndicatorAndCrosshairNames() + + //PlayMusic( "Music_FR_Militia_PilotAction2" ) +} + + +function PlayerPressed_QuickDisembark( player ) +{ + player.ClientCommand( "TitanDisembark" ) +} + +void function PlayerPressed_EjectEnable( entity player ) +{ + if ( !player.IsTitan() ) + return + + if ( !IsAlive( player ) ) + return + + if ( IsValid( player.GetParent() ) ) + return + + if ( TitanEjectIsDisabled() ) + { + EmitSoundOnEntity( player, "CoOp_SentryGun_DeploymentDeniedBeep" ) + SetTimedEventNotification( 1.5, "" ) + SetTimedEventNotification( 1.5, "#NOTIFY_EJECT_DISABLED" ) + return + } + + if ( Riff_TitanExitEnabled() == eTitanExitEnabled.Never || Riff_TitanExitEnabled() == eTitanExitEnabled.DisembarkOnly ) + return + + //if ( !CanDisembark( player ) ) + // return + + if ( player.ContextAction_IsMeleeExecution() ) //Could just check for ContextAction_IsActive() if we need to be more general + return + + if ( player.GetHealth() == 1 ) + { + #if MP + if ( !FD_ReadyUpEnabled() ) + #endif + { + player.ClientCommand( "TitanEject " + 3 ) + return + } + } + + EmitSoundOnEntity( player, "titan_eject_dpad" ) + UpdateEjectHud_SetManualEjectStartTime( player ) + player.Signal( "UpdateRodeoAlert" ) // need this to hide titan stomp hint +} + +float function CalcJoltMagnitude( player, cockpit, joltDir, float damageAmount, damageType, int damageSourceID ) +{ + const float COCKPIT_MAX_JOLT_DAMAGE = 2000.0 + + float resultRaw = damageAmount / COCKPIT_MAX_JOLT_DAMAGE + return clamp( resultRaw, 0.0, 1.0 ) +} + +function JoltCockpit( cockpit, player, joltDir, float damageAmount, damageType, damageSourceId ) +{ + float severity = CalcJoltMagnitude( player, cockpit, joltDir, damageAmount, damageType, expect int( damageSourceId ) ) + player.CockpitJolt( joltDir, severity ) +} + +function RandomizeDir( dir, randPitch = 0, randYaw = 0, basePitch = 0, baseYaw = 0 ) +{ + local pitch = RandomFloatRange( -randPitch, randPitch ) + local yaw = RandomFloatRange( -randYaw, randYaw ) + local angles = VectorToAngles( dir ) + angles = AnglesCompose( angles, Vector( pitch, yaw, 0 ) ) + angles = AnglesCompose( angles, Vector( basePitch, baseYaw, 0 ) ) + return AnglesToForward( angles ) +} + +function TitanCockpitDoomedThink( cockpit, player ) +{ + cockpit.EndSignal( "OnDestroy" ) + + local titanSoul = player.GetTitanSoul() + + if ( titanSoul == null || !titanSoul.IsDoomed() ) + WaitSignal( player, "Doomed", "Ejecting" ) + + local color = Vector( 0.6, 0.06, 0 ) + local radius = 70.0 + + FlashCockpitLight( cockpit, color, radius, -1 ) +} + +void function TitanCockpitHealthChangedThink( cockpit, entity player ) +{ + cockpit.EndSignal( "OnDestroy" ) + + while ( true ) + { + table results = WaitSignal( player, "HealthChanged" ) + + if ( !IsAlive( player ) ) + continue + + float oldHealthFrac = float( results.oldHealth ) / float( player.GetMaxHealth() ) + float newHealthFrac = float( results.newHealth ) / float( player.GetMaxHealth() ) + + if ( oldHealthFrac > newHealthFrac ) + { + var rui = RuiCreate( $"ui/ajax_cockpit_lost_health_segment.rpak", clGlobal.topoTitanCockpitHud, RUI_DRAW_COCKPIT, 10 ) + RuiSetGameTime( rui, "startTime", Time() ) + RuiSetFloat( rui, "oldHealthFrac", oldHealthFrac ) + RuiSetFloat( rui, "newHealthFrac", newHealthFrac ) + + string playerSettings = GetLocalViewPlayer().GetPlayerSettings() + float health = player.GetPlayerModHealth() + float healthPerSegment = GetPlayerSettingsFieldForClassName_HealthPerSegment( playerSettings ) + RuiSetInt( rui, "numHealthSegments", int( health / healthPerSegment ) ) + } + } +} + + +function FlashCockpitLight( cockpit, color, radius, duration, tag = "SCR_CL_BL" ) +{ + cockpit.EndSignal( "TitanUnDoomed" ) + cockpit.EndSignal( "OnDestroy" ) + + local attachID = cockpit.LookupAttachment( tag ) + local origin = cockpit.GetAttachmentOrigin( attachID ) + local angles = Vector( 0, 0, 0 ) + + local fxLight = CreateClientSideDynamicLight( origin, angles, color, radius ) + fxLight.SetCockpitLight( true ) + fxLight.SetParent( cockpit ) + + OnThreadEnd( + function() : ( fxLight ) + { + fxLight.Destroy() + } + ) + + local startTime = Time() + local rate = 3.0 + + while ( IsValid( cockpit ) && (Time() < startTime + duration || duration == -1 ) ) + { + local pulseFrac = GetPulseFrac( rate, startTime ) + pulseFrac += 0.5 + fxLight.SetLightColor( Vector( color.x * pulseFrac, color.y * pulseFrac, color.z * pulseFrac ) ) + + WaitFrame() + } +} + +function PlayCockpitSparkFX_Internal( cockpit, string tagName ) +{ + expect entity( cockpit ) + + // this is called from a delaythread so needs valid check + if ( !IsValid( cockpit ) ) + return + + int attachID = cockpit.LookupAttachment( tagName ) + if ( attachID == 0 ) + { + tagName = CoinFlip() ? "FX_TL_PANEL" : "FX_TR_PANEL" + attachID = cockpit.LookupAttachment( tagName ) + Assert( attachID, "Could not find fallback attachment index " + attachID + " for '" + tagName + "'' in model " + GetLocalViewPlayer().GetCockpit().GetModelName() ) + } + + int fxID = GetParticleSystemIndex( $"xo_cockpit_spark_01" ) + int fxInstID = PlayFXOnTag( cockpit, fxID, attachID ) + + EffectSetIsWithCockpit( fxInstID, true ) +} + +function PlayCockpitSparkFX( cockpit, int sparkCount ) +{ + const int TAG_COUNT = 6 + const string[TAG_COUNT] cockpitFXEmitTags = [ "FX_TL_PANEL", "FX_TR_PANEL", "FX_TC_PANELA", "FX_TC_PANELB", "FX_BL_PANEL", "FX_BR_PANEL" ] + array<int> playlist = [0,1,2,3,4,5] + playlist.randomize() + + for ( int idx = 0; idx < sparkCount; idx++ ) + { + int lookup = (idx % TAG_COUNT) + int tagIndex = playlist[lookup] + string tagName = cockpitFXEmitTags[tagIndex] + PlayCockpitSparkFX_Internal( cockpit, tagName ) + } +} + +const int DAMAGE_PER_SPARK = 1000 +const int SPARK_MULTIPLIER = 3 + +int function CalSparkCountForHit( entity player, float damageAmount, bool becameDoomed ) +{ + if ( becameDoomed ) + return 20 + if ( damageAmount <= 0 ) + return 0 + + int healthNow = player.GetHealth() + int healthPrev = healthNow + int( damageAmount ) + int healthMax = player.GetMaxHealth() + + bool isDoomed = GetDoomedState( player ) + int sparksNow = (healthNow / DAMAGE_PER_SPARK) + int sparksPrev = (healthPrev / DAMAGE_PER_SPARK) + if ( (healthPrev == healthMax) && !isDoomed ) + --sparksPrev // no spark on first damage + + int delta = (sparksPrev - sparksNow) + if ( delta < 0 ) + return 0 + + return (delta * SPARK_MULTIPLIER) +} + +function TitanCockpit_DamageFeedback( entity player, cockpit, float damageAmount, damageType, damageOrigin, damageSourceId, bool doomedNow, int doomedDamage ) +{ + RumbleForTitanDamage( damageAmount ) + + vector joltDir = Normalize( player.CameraPosition() - damageOrigin ) + float joltDamage = doomedNow ? float( doomedDamage ) : damageAmount + JoltCockpit( cockpit, player, joltDir, joltDamage, damageType, damageSourceId ) + + bool isShieldHit = (damageType & DF_SHIELD_DAMAGE) ? true : false + if ( isShieldHit ) + return + + int sparkCount = CalSparkCountForHit( player, damageAmount, doomedNow ); + //printt( "sparks: " + sparkCount + " dmg: " + damageAmount + " - " + player.GetHealth() + " / " + player.GetMaxHealth() ) + PlayCockpitSparkFX( cockpit, sparkCount ) +} + +function ServerCallback_TitanCockpitBoot() +{ + thread ServerCallback_TitanCockpitBoot_Internal() +} + +function ServerCallback_TitanCockpitBoot_Internal() +{ + AutoExposureSetExposureCompensationBias( -6 ) + AutoExposureSnap() + wait 0.1 + AutoExposureSetExposureCompensationBias( 0 ) +} + +function ServerCallback_TitanEMP( maxValue, duration, fadeTime, doFlash = true, doSound = true ) +{ + thread TitanEMP_Internal( maxValue, duration, fadeTime, doFlash, doSound ) +} + +function TitanEMP_Internal( maxValue, duration, fadeTime, doFlash = true, doSound = true ) +{ + entity player = GetLocalViewPlayer() + + player.Signal( "TitanEMP_Internal" ) + player.EndSignal( "TitanEMP_Internal" ) + + player.EndSignal( "OnDeath" ) + player.EndSignal( "SettingsChanged" ) + + local angles = Vector( 0, -90, 90 ) + + local wide = 16 + local tall = 9 + + float fovOffset = Graph( player.GetFOV(), 75, 120, 4, 2.5 ) + + local empVgui = CreateClientsideVGuiScreen( "vgui_titan_emp", VGUI_SCREEN_PASS_VIEWMODEL, Vector(0,0,0), Vector(0,0,0), wide, tall ); + + //empVgui.SetParent( player.GetViewModelEntity(), "CAMERA_BASE" ) + empVgui.SetRefract( true ) // Force refract resolve before drawing vgui. (This can cost GPU!) + empVgui.SetParent( player ) + empVgui.SetAttachOffsetOrigin( < fovOffset, wide / 2, -tall / 2 > ) + empVgui.SetAttachOffsetAngles( angles ) + + empVgui.GetPanel().WarpEnable() + + local EMPScreenFX = HudElement( "EMPScreenFX", empVgui.GetPanel() ) + local EMPScreenFlash = HudElement( "EMPScreenFlash", empVgui.GetPanel() ) + + OnThreadEnd( + function() : ( player, empVgui ) + { + empVgui.Destroy() + } + ) + + EMPScreenFX.Show() + EMPScreenFX.SetAlpha( maxValue * 255 ) + EMPScreenFX.FadeOverTimeDelayed( 0, fadeTime, duration ) + + if ( doFlash ) + { + EMPScreenFlash.Show() + EMPScreenFlash.SetAlpha( 255 ) + EMPScreenFlash.FadeOverTimeDelayed( 0, fadeTime + duration, 0 ) + } + + if ( doSound ) + { + EmitSoundOnEntity( player, EMP_IMPARED_SOUND ) + wait duration + FadeOutSoundOnEntity( player, EMP_IMPARED_SOUND, fadeTime ) + } + + wait fadeTime +} + + +void function LinkCoreHint( entity soul ) +{ + if ( file.coreHintRui == null ) + return + + RuiTrackFloat( file.coreHintRui, "coreFrac", soul, RUI_TRACK_SCRIPT_NETWORK_VAR, GetNetworkedVariableIndex( "coreAvailableFrac" ) ) +} + + +void function FlashCockpitHealth( vector color ) +{ + if ( file.cockpitRui == null ) + return + + RuiSetGameTime( file.cockpitRui, "startFlashTime", Time() ) + RuiSetFloat3( file.cockpitRui, "flashColor", color ) +} + +void function UpdateHealthSegmentCount() +{ + if ( file.cockpitRui == null ) + return + + entity player = GetLocalViewPlayer() + string playerSettings = player.GetPlayerSettings() + float health = player.GetPlayerModHealth() + float healthPerSegment = GetPlayerSettingsFieldForClassName_HealthPerSegment( playerSettings ) + RuiSetInt( file.cockpitRui, "numHealthSegments", int( health / healthPerSegment ) ) +} +#if MP +void function NetworkedVarChangedCallback_UpdateVanguardRUICoreStatus( entity soul, int oldValue, int newValue, bool actuallyChanged ) +{ + if ( file.cockpitRui == null ) + return + + if ( actuallyChanged == false ) + return + + entity player = GetLocalViewPlayer() + if ( !IsValid( player ) || !player.IsTitan() ) + return + + UpdateHealthSegmentCount() + + string titanName = GetTitanCharacterName( player ) + if ( titanName == "vanguard" ) + { + RuiSetString( file.cockpitRui, "titanInfo1", GetVanguardCoreString( player, 1 ) ) + RuiSetString( file.cockpitRui, "titanInfo2", GetVanguardCoreString( player, 2 ) ) + RuiSetString( file.cockpitRui, "titanInfo3", GetVanguardCoreString( player, 3 ) ) + RuiSetString( file.cockpitRui, "titanInfo4", GetVanguardCoreString( player, 4 ) ) + } +} +#endif + +var function Scorch_CreateHotstreakBar() +{ + Assert( file.scorchHotstreakRui == null ) + + file.scorchHotstreakRui = CreateFixedTitanCockpitRui( $"ui/scorch_hotstreak_bar.rpak" ) + + RuiTrackFloat( file.scorchHotstreakRui, "coreMeterMultiplier", GetLocalViewPlayer(), RUI_TRACK_SCRIPT_NETWORK_VAR, GetNetworkedVariableIndex( "coreMeterModifier" ) ) + + return file.scorchHotstreakRui +} + +void function Scorch_DestroyHotstreakBar() +{ + TitanCockpitDestroyRui( file.scorchHotstreakRui ) + file.scorchHotstreakRui = null +} + +bool function Scorch_ShouldCreateHotstreakBar() +{ + entity player = GetLocalViewPlayer() + + if ( !IsAlive( player ) ) + return false + + array<entity> mainWeapons = player.GetMainWeapons() + if ( mainWeapons.len() == 0 ) + return false + + entity primaryWeapon = mainWeapons[0] + return primaryWeapon.HasMod( "fd_hot_streak" ) +} diff --git a/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut b/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut index 755396e3..f17216fb 100644 --- a/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut +++ b/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut @@ -1,60 +1,42 @@ untyped globalize_all_functions -struct { - int highestScore = 0 - int secondHighestScore = 0 -} file - -void function OnPrematchStart() +GameStateStruct function DiscordRPC_GenerateGameState( GameStateStruct gs ) { - if ( GetServerVar( "roundBased" ) ) - NSUpdateTimeInfo( level.nv.roundEndTime - Time() ) - else - NSUpdateTimeInfo( level.nv.gameEndTime - Time() ) -} + int highestScore = 0 + int secondHighest = 0 -void function NSUpdateGameStateClientStart() -{ - #if MP - AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart ) - #endif - - thread NSUpdateGameStateLoopClient() - OnPrematchStart() -} - -void function NSUpdateGameStateLoopClient() -{ - while ( true ) + foreach ( player in GetPlayerArray() ) { - if ( IsSingleplayer() ) - { - NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), 1, 1, 1, GetServerVar( "roundBased" ), 1 ) - wait 1.0 - } - else - { - foreach ( player in GetPlayerArray() ) - { - if ( GameRules_GetTeamScore( player.GetTeam() ) >= file.highestScore ) - { - file.highestScore = GameRules_GetTeamScore( player.GetTeam() ) - } - else if ( GameRules_GetTeamScore( player.GetTeam() ) > file.secondHighestScore ) - { - file.secondHighestScore = GameRules_GetTeamScore( player.GetTeam() ) - } - } - - int ourScore = 0 - if ( IsValid( GetLocalClientPlayer() ) ) - ourScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() ) - - int limit = IsRoundBased() ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 ) - NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), ourScore, file.secondHighestScore, file.highestScore, GetServerVar( "roundBased" ), limit ) - OnPrematchStart() - wait 1.0 - } + if ( GameRules_GetTeamScore( player.GetTeam() ) >= highestScore ) + { + highestScore = GameRules_GetTeamScore( player.GetTeam() ) + } + else if ( GameRules_GetTeamScore( player.GetTeam() ) > secondHighest ) + { + secondHighest = GameRules_GetTeamScore( player.GetTeam() ) + } } + + gs.map = GetMapName() + gs.mapDisplayname = Localize(GetMapDisplayName(GetMapName())) + + gs.playlist = GetCurrentPlaylistName() + gs.playlistDisplayname = Localize(GetCurrentPlaylistVarString("name", GetCurrentPlaylistName())) + + gs.currentPlayers = GetPlayerArray().len() + gs.maxPlayers = GetCurrentPlaylistVarInt( "maxPlayers", -1 ) + + if ( IsValid( GetLocalClientPlayer() ) ) + gs.ownScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() ) + + gs.otherHighestScore = gs.ownScore == highestScore ? secondHighest : highestScore + + gs.maxScore = IsRoundBased() ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 ) + + if ( GetServerVar( "roundBased" ) ) + gs.timeEnd = expect float(level.nv.roundEndTime - Time()) + else + gs.timeEnd = expect float(level.nv.gameEndTime - Time()) + return gs } diff --git a/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut index 1e381989..ce5abe86 100644 --- a/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut +++ b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut @@ -1,38 +1,16 @@ untyped globalize_all_functions -void function NSUpdateGameStateUIStart() +UIPresenceStruct function DiscordRPC_GenerateUIPresence( UIPresenceStruct uis ) { - thread NSUpdateGameStateLoopUI() -} - -void function NSUpdateGameStateLoopUI() -{ - while ( true ) - { - wait 1.0 + if ( uiGlobal.isLoading ) + uis.gameState = eDiscordGameState.LOADING; + else if ( uiGlobal.loadedLevel == "" ) + uis.gameState = eDiscordGameState.MAINMENU; + else if ( IsLobby() || uiGlobal.loadedLevel == "mp_lobby" ) + uis.gameState = eDiscordGameState.LOBBY; + else + uis.gameState = eDiscordGameState.INGAME; - if ( uiGlobal.loadedLevel == "" ) - { - if ( uiGlobal.isLoading ) - NSSetLoading( true ) - else - { - NSSetLoading( false ) - NSUpdateGameStateUI( "", "", "", "", true, false ) - } - - continue - } - - NSSetLoading( false ) - if( GetConVarString( "mp_gamemode" ) == "solo" ) - { - NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() + "_CAMPAIGN_NAME" ) ), "Campaign", "Campaign", IsFullyConnected(), false ) - } - else - { - NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() ) ), GetConVarString( "mp_gamemode" ), Localize( GetPlaylistDisplayName( GetConVarString( "mp_gamemode" ) ) ), IsFullyConnected(), false ) - } - } + return uis } diff --git a/Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut b/Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut index 6d446654..0bcb7864 100644 --- a/Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut +++ b/Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut @@ -207,19 +207,9 @@ #endif // CLIENT && MP #if UI - struct - { - table MouseMovementCaptureFunctionsTable = {} - } file - - const MOUSE_ROTATE_MULTIPLIER = 25.0 - global function UpdateUIMapSupportsMenuModels global function RunMenuClientFunction global function UI_SetPresentationType - - global function AddMouseMovementCaptureHandler - global function UICodeCallback_MouseMovementCapture #endif // UI global const STORE_BG_DEFAULT = 0 @@ -2897,30 +2887,4 @@ RunClientScript( "UpdateMenuToHarvester" ) } } - - void function AddMouseMovementCaptureHandler( var menu, void functionref( int, int ) func ) - { - file.MouseMovementCaptureFunctionsTable.rawset( menu, func ) - } - - void function UpdateMouseMovementCaptureFunctions( int deltaX, int deltaY ) - { - var activeMenu = GetActiveMenu() - if ( file.MouseMovementCaptureFunctionsTable.rawin( activeMenu ) ) - file.MouseMovementCaptureFunctionsTable.rawget( activeMenu )(deltaX, deltaY) - } - - void function UICodeCallback_MouseMovementCapture( var capturePanel, int deltaX, int deltaY ) - { - float screenScaleXModifier = 1920.0 / GetScreenSize()[0] // 1920 is base screen width - float mouseXRotateDelta = deltaX * screenScaleXModifier * MOUSE_ROTATE_MULTIPLIER - //printt( "deltaX:", deltaX, "deltaY:", deltaY ) - - float screenScaleYModifier = 1080.0 / GetScreenSize()[1] // 1920 is base screen width - float mouseYRotationDelta = deltaY * screenScaleYModifier * MOUSE_ROTATE_MULTIPLIER - - UpdateMouseMovementCaptureFunctions( deltaX, deltaY ) - - RunMenuClientFunction( "UpdateMouseRotateDelta", mouseXRotateDelta, mouseYRotationDelta ) - } #endif // UI diff --git a/Northstar.Client/mod/scripts/vscripts/ui/_menus.nut b/Northstar.Client/mod/scripts/vscripts/ui/_menus.nut new file mode 100644 index 00000000..c83381fd --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/_menus.nut @@ -0,0 +1,2004 @@ +untyped + +global const bool EDIT_LOADOUT_SELECTS = true +global const string PURCHASE_SUCCESS_SOUND = "UI_Menu_Store_Purchase_Success" + +global function UICodeCallback_CloseAllMenus +global function UICodeCallback_ActivateMenus +global function UICodeCallback_LevelInit +global function UICodeCallback_LevelLoadingStarted +global function UICodeCallback_LevelLoadingFinished +global function UICodeCallback_LevelShutdown +global function UICodeCallback_OnConnected +global function UICodeCallback_OnFocusChanged +global function UICodeCallback_NavigateBack +global function UICodeCallback_ToggleInGameMenu +global function UICodeCallback_TryCloseDialog +global function UICodeCallback_UpdateLoadingLevelName +global function UICodeCallback_ConsoleKeyboardClosed +global function UICodeCallback_ErrorDialog +global function UICodeCallback_AcceptInvite +global function UICodeCallback_OnDetenteDisplayed +global function UICodeCallback_OnSpLogDisplayed +global function UICodeCallback_EntitlementsChanged +global function UICodeCallback_StoreTransactionCompleted +global function UICodeCallback_GamePurchased +global function UICodeCallback_PartyUpdated +global function UICodeCallback_KeyBindOverwritten + +global function AdvanceMenu +global function OpenSubmenu // REMOVE +global function CloseSubmenu // REMOVE +global function CloseActiveMenu +global function CloseActiveMenuNoParms +global function CloseAllMenus +global function CloseAllInGameMenus +global function CloseAllDialogs +global function CloseAllToTargetMenu +global function PrintMenuStack +global function CleanupInGameMenus +global function GetActiveMenu +global function GetMenu +global function GetPanel +global function GetAllMenuPanels +global function InitGamepadConfigs +global function InitMenus +global function AdvanceMenuEventHandler +global function PCSwitchTeamsButton_Activate +global function PCToggleSpectateButton_Activate +global function AddMenuElementsByClassname +global function FocusDefault +global function SetPanelDefaultFocus +global function PanelFocusDefault +global function OpenMenuWrapper +global function CloseMenuWrapper +global function IsLevelMultiplayer +global function AddMenuEventHandler +global function AddPanelEventHandler +global function AddButtonEventHandler +global function AddEventHandlerToButton +global function AddEventHandlerToButtonClass +global function DisableMusic +global function EnableMusic +global function PlayMusic +global function StopMusic +global function IsMenuInMenuStack +global function GetTopNonDialogMenu +global function IsDialog +global function IsDialogActive +global function IsDialogOnlyActiveMenu +global function SetNavUpDown +global function SetNavLeftRight +global function IsTrialPeriodActive +global function LaunchGamePurchaseOrDLCStore +global function SetMenuThinkFunc + +global function PCBackButton_Activate + +global function RegisterMenuVarInt +global function GetMenuVarInt +global function SetMenuVarInt +global function RegisterMenuVarBool +global function GetMenuVarBool +global function SetMenuVarBool +global function RegisterMenuVarVar +global function GetMenuVarVar +global function SetMenuVarVar +global function AddMenuVarChangeHandler + +global function InviteFriends + +global function HACK_DelayedSetFocus_BecauseWhy + +#if DURANGO_PROG + global function OpenXboxPartyApp + global function OpenXboxHelp +#endif // DURANGO_PROG + +global function OpenReviewTermsDialog +global function ClassicMusic_OnChange +global function IsClassicMusicAvailable + + +void function UICodeCallback_CloseAllMenus() +{ + printt( "UICodeCallback_CloseAllMenus" ) + CloseAllMenus() + // This is usually followed by a call to UICodeCallback_ActivateMenus(). +} + +// Bringing up the console will cause this, and it probably shouldn't +void function UICodeCallback_ActivateMenus() +{ + if ( IsConnected() ) + return + + printt( "UICodeCallback_ActivateMenus:", uiGlobal.activeMenu && Hud_GetHudName( uiGlobal.activeMenu ) ) + + if ( uiGlobal.menuStack.len() == 0 ) + { + AdvanceMenu( GetMenu( "MainMenu" ) ) + } + + if ( uiGlobal.activeMenu == GetMenu( "MainMenu" ) ) + Signal( uiGlobal.signalDummy, "OpenErrorDialog" ) + + PlayMusic() + + #if DURANGO_PROG + Durango_LeaveParty() + #endif // DURANGO_PROG +} + +void function UICodeCallback_ToggleInGameMenu() +{ + if ( !IsFullyConnected() ) + return + + var activeMenu = uiGlobal.activeMenu + bool isMP = IsLevelMultiplayer( GetActiveLevel() ) + bool isLobby = IsLobby() + + var ingameMenu + if ( isMP ) + { + ingameMenu = GetMenu( "InGameMPMenu" ) + } + else + { + // Disable this callback for this special case menu so players can't skip it. + var spTitanTutorialMenu = GetMenu( "SPTitanLoadoutTutorialMenu" ) + if ( activeMenu == spTitanTutorialMenu ) + return + + ingameMenu = GetMenu( "InGameSPMenu" ) + } + + if ( IsDialog( uiGlobal.activeMenu ) ) + { + // Do nothing if a dialog is showing + } + else if ( TeamTitanSelectMenuIsOpen() ) + { + if ( uiGlobal.activeMenu == GetMenu( "TeamTitanSelectMenu" ) ) + { + // Do nothing here either + } + else + { + CloseActiveMenu() + } + } + else if ( ( isMP && !isLobby ) || !isMP ) + { + if ( !activeMenu ) + AdvanceMenu( ingameMenu ) + else + CloseAllInGameMenus() + } +} + +// Return true to show load screen, false to not show load screen. +// levelname can be "" because the level to load isn't always known when the load screen starts +bool function UICodeCallback_LevelLoadingStarted( string levelname ) +{ + printt( "UICodeCallback_LevelLoadingStarted: " + levelname ) + + CloseAllDialogs() + + uiGlobal.loadingLevel = levelname + uiGlobal.isLoading = true + + StopMusic() + + if ( uiGlobal.playingVideo ) + Signal( uiGlobal.signalDummy, "PlayVideoEnded" ) + + if ( uiGlobal.playingCredits ) + Signal( uiGlobal.signalDummy, "PlayingCreditsDone" ) + + // kill lingering postgame summary since persistent data may not be available at this point + Signal( uiGlobal.signalDummy, "PGDisplay" ) + +#if CONSOLE_PROG + if ( !Console_IsSignedIn() ) + return false +#endif + + return true +} + +// Return true to show load screen, false to not show load screen. +bool function UICodeCallback_UpdateLoadingLevelName( string levelname ) +{ + printt( "UICodeCallback_UpdateLoadingLevelName: " + levelname ) + +#if CONSOLE_PROG + if ( !Console_IsSignedIn() ) + return false +#endif + + return true +} + +void function UICodeCallback_LevelLoadingFinished( bool error ) +{ + printt( "UICodeCallback_LevelLoadingFinished: " + uiGlobal.loadingLevel + " (" + error + ")" ) + + if ( !IsLobby() ) + { + HudChat_ClearTextFromAllChatPanels() + ResetActiveChatroomLastModified() + } + else + { + uiGlobal.lobbyFromLoadingScreen = true + } + + uiGlobal.loadingLevel = "" + uiGlobal.isLoading = false + Signal( uiGlobal.signalDummy, "LevelFinishedLoading" ) +} + +void function UICodeCallback_LevelInit( string levelname ) +{ + Assert( IsConnected() ) + + StopVideo() + + uiGlobal.loadedLevel = levelname + + printt( "UICodeCallback_LevelInit: " + uiGlobal.loadedLevel ) + + if ( !uiGlobal.loadoutsInitialized ) + { + string gameModeString = GetConVarString( "mp_gamemode" ) + if ( gameModeString != "solo" ) + { + InitStatsTables() + } + } + + InitItems() + + if ( IsMultiplayer() ) + { + ShWeaponXP_Init() + ShTitanXP_Init() + ShFactionXP_Init() + } + else + { + SPObjectiveStringsInit() + } + + #if DEV + UpdatePrecachedSPWeapons() + #endif + + + if ( !uiGlobal.loadoutsInitialized ) + { + string gameModeString = GetConVarString( "mp_gamemode" ) + if ( gameModeString != "solo" ) + { + DeathHints_Init() + InitDefaultLoadouts() + CreateChallenges() + uiGlobal.loadoutsInitialized = true + } + } + + if ( IsLevelMultiplayer( levelname ) || IsLobbyMapName( levelname ) ) + { + thread UpdateCachedLoadouts() + thread UpdateCachedNewItems() + thread InitUISpawnLoadoutIndexes() + + if ( !uiGlobal.eventHandlersAdded ) + { + uiGlobal.eventHandlersAdded = true + } + + UI_GetAllChallengesProgress() + + bool isLobby = IsLobbyMapName( levelname ) + + string gameModeString = GetConVarString( "mp_gamemode" ) + if ( gameModeString == "" ) + gameModeString = "<null>" + + Assert( gameModeString == GetConVarString( "mp_gamemode" ) ) + Assert( gameModeString != "" ) + + int gameModeId = GameMode_GetGameModeId( gameModeString ) + + int mapId = eMaps.invalid + if ( levelname in getconsttable().eMaps ) + { + mapId = expect int( getconsttable().eMaps[ levelname ] ) + } + else + { + // Don't worry about this until we have to consider R2 Durango TCRs (10/2015) + //if ( !IsTestMap() ) + // CodeWarning( "No map named '" + levelname + "' exists in eMaps, all shipping maps should be in this enum" ) + } + + int difficultyLevelId = 0 + int roundId = 0 + + if ( isLobby ) + Durango_OnLobbySessionStart( gameModeId, difficultyLevelId ) + else + Durango_OnMultiplayerRoundStart( gameModeId, mapId, difficultyLevelId, roundId, 0 ) + } + else + { + // SP loadout stuff + UI_GetAllChallengesProgress() // TODO: Can this be moved so we don't call it twice? It's called above. + + SP_ResetObjectiveStringIndex() // Since this persists thru level load, we need to explicitely clear it. + } + + if ( IsMultiplayer() ) + { + foreach ( callbackFunc in uiGlobal.onLevelInitCallbacks ) + { + thread callbackFunc() + } + + } + thread UpdateMenusOnConnect( levelname ) + + uiGlobal.previousLevel = uiGlobal.loadedLevel + uiGlobal.previousPlaylist = GetCurrentPlaylistName() +} + +void function UICodeCallback_LevelShutdown() +{ + Signal( uiGlobal.signalDummy, "LevelShutdown" ) + + printt( "UICodeCallback_LevelShutdown: " + uiGlobal.loadedLevel ) + + StopVideo() + + if ( uiGlobal.loadedLevel != "" ) + CleanupInGameMenus() + + uiGlobal.loadedLevel = "" + uiGlobal.mapSupportsMenuModelsUpdated = false + uiGlobal.sp_showAlternateMissionLog = false +} + +void function UICodeCallback_NavigateBack() +{ + if ( uiGlobal.activeMenu == null ) + return + + if ( IsDialog( uiGlobal.activeMenu ) ) + { + if ( uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData.noChoice || + uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData.forceChoice || + Time() < uiGlobal.dialogInputEnableTime ) + return + } + + Assert( uiGlobal.activeMenu in uiGlobal.menuData ) + if ( uiGlobal.menuData[ uiGlobal.activeMenu ].navBackFunc != null ) + { + thread uiGlobal.menuData[ uiGlobal.activeMenu ].navBackFunc() + return + } + + if ( uiGlobal.activeMenu.GetType() == "submenu" ) // REMOVE + { + CloseSubmenu() + return + } + + CloseActiveMenu( true ) +} + +// Called when IsConnected() will start returning true. +void function UICodeCallback_OnConnected() +{ + +} + +void function UICodeCallback_OnFocusChanged( var oldFocusedPanel, var newFocusedPanel ) +{ + +} + +// Accepting an origin invite closes dialogs, or aborts if they can't be closed +bool function UICodeCallback_TryCloseDialog() +{ + if ( !IsDialog( uiGlobal.activeMenu ) ) + return true + + if ( uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData.forceChoice ) + return false + + CloseAllDialogs() + Assert( !IsDialog( uiGlobal.activeMenu ) ) + return true +} + +void function UICodeCallback_ConsoleKeyboardClosed() +{ + switch ( uiGlobal.activeMenu ) + { + case GetMenu( "EditPilotLoadoutMenu" ): + string oldName = GetPilotLoadoutName( GetCachedPilotLoadout( uiGlobal.editingLoadoutIndex ) ) + string newName = GetPilotLoadoutRenameText() + + // strip doesn't work on UTF-8 strings + // newName = strip( newName ) // Remove leading/trailing whitespace + if ( newName == "" ) // If all whitespace entered reset to previous name + newName = oldName + + SetPilotLoadoutName( newName ) + SelectPilotLoadoutRenameText() + if ( newName != oldName ) + EmitUISound( "Menu.Accept" ) // No callback when cancelled so for now assume name was changed + break + + default: + break + } +} + +void function UICodeCallback_OnDetenteDisplayed() +{ +// thread PlayDetentSound() +//} +// +//void function PlayDetentSound() +//{ +// WaitFrame() // otherwise gets killed off by code pause +// WaitFrame() // otherwise gets killed off by code pause +// EmitUISound( "Pilot_Killed_Indicator" ) +} + +void function UICodeCallback_OnSpLogDisplayed() +{ +} + +void function UICodeCallback_ErrorDialog( string errorDetails ) +{ + printt( "UICodeCallback_ErrorDialog: " + errorDetails ) + thread OpenErrorDialog( errorDetails ) +} + +void function UICodeCallback_AcceptInviteThread( string accesstoken ) +{ + printt( "UICodeCallback_AcceptInviteThread '" + accesstoken + "'") + + #if PS4_PROG + if ( !Ps4_PSN_Is_Loggedin() ) + { + Ps4_LoginDialog_Schedule(); + while( Ps4_LoginDialog_Running() ) + WaitFrame() + if ( !Ps4_PSN_Is_Loggedin() ) + return; + } + + if( Ps4_CheckPlus_Schedule() ) + { + while( Ps4_CheckPlus_Running() ) + WaitFrame() + if( !Ps4_CheckPlus_Allowed() ) + { + if( Ps4_CheckPlus_GetLastRequestResults() != 0 ) + { + return + } + + if( Ps4_ScreenPlusDialog_Schedule() ) + { + while( Ps4_ScreenPlusDialog_Running() ) + WaitFrame() + if( !Ps4_ScreenPlusDialog_Allowed() ) + return; + } + else + { + return; + } + } + } + + #endif // #if PS4_PROG + + SubscribeToChatroomPartyChannel( accesstoken ); + +} + + +void function UICodeCallback_AcceptInvite( string accesstoken ) +{ + printt( "UICodeCallback_AcceptInvite '" + accesstoken + "'") + thread UICodeCallback_AcceptInviteThread( accesstoken ) +} + +// TODO: replaceCurrent should not be an option. It should be a different function. +void function AdvanceMenu( var menu, bool replaceCurrent = false ) +{ + //foreach ( index, menu in uiGlobal.menuStack ) + //{ + // if ( menu != null ) + // printt( "menu index " + index + " is named " + menu.GetDisplayName() ) + //} + + if ( uiGlobal.activeMenu ) + { + // Don't open the same menu again if it's already open + if ( uiGlobal.activeMenu == menu ) + return + + // Opening a normal menu while a dialog is open + Assert( !IsDialog( uiGlobal.activeMenu ), "Tried opening menu: " + Hud_GetHudName( menu ) + " when uiGlobal.activeMenu was: " + Hud_GetHudName( uiGlobal.activeMenu ) ) + } + + if ( uiGlobal.activeMenu && !IsDialog( menu ) ) // Dialogs show on top so don't close existing menu when opening them + { + SetBlurEnabled( false ) + + if ( replaceCurrent ) + { + CloseMenuWrapper( uiGlobal.activeMenu ) + uiGlobal.menuStack.pop() + } + else + { + CloseMenu( uiGlobal.activeMenu ) + printt( Hud_GetHudName( uiGlobal.activeMenu ), "menu closed" ) + } + } + + if ( IsDialog( menu ) && uiGlobal.activeMenu ) + SetFooterPanelVisibility( uiGlobal.activeMenu, false ) + + uiGlobal.menuStack.push( menu ) + uiGlobal.activeMenu = menu + + uiGlobal.lastMenuNavDirection = MENU_NAV_FORWARD + + if ( uiGlobal.activeMenu ) + { + if ( !IsLobby() && !uiGlobal.mapSupportsMenuModels ) + SetBlurEnabled( true ) + + OpenMenuWrapper( uiGlobal.activeMenu, true ) + } + + Signal( uiGlobal.signalDummy, "ActiveMenuChanged" ) +} + +void function SetFooterPanelVisibility( var menu, bool visible ) +{ + if ( !Hud_HasChild( menu, "FooterButtons" ) ) + return + + var panel = Hud_GetChild( menu, "FooterButtons" ) + Hud_SetVisible( panel, visible ) +} + +void function OpenSubmenu( var menu, bool updateMenuPos = true ) +{ + Assert( menu ) + Assert( menu.GetType() == "submenu" ) + + if ( uiGlobal.activeMenu ) + { + // Don't open the same menu again if it's already open + if ( uiGlobal.activeMenu == menu ) + return + } + + local submenuPos = Hud_GetAbsPos( GetFocus() ) + + uiGlobal.menuStack.push( menu ) + uiGlobal.activeMenu = menu + + OpenMenuWrapper( uiGlobal.activeMenu, true ) + + if ( updateMenuPos ) + { + var vguiButtonFrame = Hud_GetChild( uiGlobal.activeMenu, "ButtonFrame" ) + Hud_SetPos( vguiButtonFrame, submenuPos[0], submenuPos[1] ) + } + + uiGlobal.lastMenuNavDirection = MENU_NAV_FORWARD + + Signal( uiGlobal.signalDummy, "ActiveMenuChanged" ) +} + +void function CloseSubmenu( bool openStackMenu = true ) +{ + if ( !uiGlobal.activeMenu ) + return + + if ( uiGlobal.activeMenu.GetType() != "submenu" ) + return + + CloseMenuWrapper( uiGlobal.activeMenu ) + uiGlobal.menuStack.pop() + + uiGlobal.lastMenuNavDirection = MENU_NAV_FORWARD + + if ( uiGlobal.menuStack.len() ) + { + uiGlobal.activeMenu = uiGlobal.menuStack.top() + + // This runs any OnOpen function for the menu and sets focus, but doesn't actually open the menu because it is already open + if ( openStackMenu ) + OpenMenuWrapper( uiGlobal.activeMenu, false ) + } + else + { + uiGlobal.activeMenu = null + } + + Signal( uiGlobal.signalDummy, "ActiveMenuChanged" ) +} + +void function CloseActiveMenuNoParms() +{ + CloseActiveMenu() +} + +void function CloseActiveMenu( bool cancelled = false, bool openStackMenu = true ) +{ + bool updateBlur = true + bool wasDialog = false + + if ( uiGlobal.activeMenu ) + { + if ( IsDialog( uiGlobal.activeMenu ) ) + { + updateBlur = false + wasDialog = true + uiGlobal.dialogInputEnableTime = 0.0 + + if ( uiGlobal.dialogCloseCallback ) + { + uiGlobal.dialogCloseCallback( cancelled ) + uiGlobal.dialogCloseCallback = null + } + } + + if ( updateBlur ) + SetBlurEnabled( false ) + + CloseMenuWrapper( uiGlobal.activeMenu ) + } + + uiGlobal.menuStack.pop() + if ( uiGlobal.menuStack.len() ) + uiGlobal.activeMenu = uiGlobal.menuStack.top() + else + uiGlobal.activeMenu = null + + uiGlobal.lastMenuNavDirection = MENU_NAV_BACK + + if ( wasDialog ) + { + if ( uiGlobal.activeMenu ) + SetFooterPanelVisibility( uiGlobal.activeMenu, true ) + + if ( IsDialog( uiGlobal.activeMenu ) ) + openStackMenu = true + else + openStackMenu = false + } + + if ( uiGlobal.activeMenu ) + { + if ( uiGlobal.activeMenu.GetType() == "submenu" ) + { + Hud_SetFocused( uiGlobal.menuData[ uiGlobal.activeMenu ].lastFocus ) + } + else if ( openStackMenu ) + { + OpenMenuWrapper( uiGlobal.activeMenu, false ) + + if ( updateBlur && !IsLobby() && !uiGlobal.mapSupportsMenuModels ) + SetBlurEnabled( true ) + } + } + + Signal( uiGlobal.signalDummy, "ActiveMenuChanged" ) +} + +void function CloseAllMenus() +{ + if ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) + + if ( uiGlobal.activeMenu && uiGlobal.activeMenu.GetType() == "submenu" ) + CloseSubmenu( false ) + + if ( uiGlobal.activeMenu ) + { + SetBlurEnabled( false ) + CloseMenuWrapper( uiGlobal.activeMenu ) + } + + uiGlobal.menuStack = [] + uiGlobal.activeMenu = null + + uiGlobal.lastMenuNavDirection = MENU_NAV_BACK + + Signal( uiGlobal.signalDummy, "ActiveMenuChanged" ) +} + +void function CloseAllInGameMenus() +{ + while ( uiGlobal.activeMenu ) + { + if ( uiGlobal.activeMenu.GetType() == "submenu" ) + CloseSubmenu( false ) + + CloseActiveMenu( true, false ) + } +} + +void function CloseAllDialogs() +{ + while ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) +} + +void function CloseAllToTargetMenu( var targetMenu ) +{ + while ( uiGlobal.activeMenu != targetMenu ) + CloseActiveMenu( true, false ) +} + +void function PrintMenuStack() +{ + array<var> stack = clone uiGlobal.menuStack + stack.reverse() + + printt( "MENU STACK:" ) + + foreach ( menu in stack ) + { + if ( menu ) + printt( " ", Hud_GetHudName( menu ) ) + else + printt( " null" ) + } +} + +// Happens on any level load +void function UpdateMenusOnConnect( string levelname ) +{ + EndSignal( uiGlobal.signalDummy, "LevelShutdown" ) // HACK fix because UICodeCallback_LevelInit() incorrectly runs when disconnected by client error. Test with "script_error_client" while a level is loaded. + + CloseAllDialogs() + + var mainMenu = GetMenu( "MainMenu" ) + if ( IsMenuInMenuStack( mainMenu ) && !IsMenuInMenuStack( null ) ) + CloseAllToTargetMenu( mainMenu ) + + Assert( uiGlobal.activeMenu != null || uiGlobal.menuStack.len() == 0 ) + + AdvanceMenu( null ) + + // TODO: The order things are called in should be predictable so this isn't needed + while ( !uiGlobal.mapSupportsMenuModelsUpdated ) + { + //printt( Time(), "beginning waitframe, uiGlobal.mapSupportsMenuModelsUpdated is:", uiGlobal.mapSupportsMenuModelsUpdated ) + WaitFrame() + //printt( Time(), "ended waitframe, uiGlobal.mapSupportsMenuModelsUpdated is:", uiGlobal.mapSupportsMenuModelsUpdated ) + } + + if ( IsLevelMultiplayer( levelname ) ) + { + bool isLobby = IsLobbyMapName( levelname ) + + if ( isLobby ) + { + if ( IsPrivateMatch() ) + { + AdvanceMenu( GetMenu( "PrivateLobbyMenu" ) ) + } + else + { + AdvanceMenu( GetMenu( "LobbyMenu" ) ) + } + + thread UpdateAnnouncementDialog() + } + else + { + UI_SetPresentationType( ePresentationType.INACTIVE ) + } + } +} + +bool function IsMenuInMenuStack( var searchMenu ) +{ + foreach ( menu in uiGlobal.menuStack ) + { + // loading a map pushes a null sentinel onto the menu stack + if ( !menu ) + continue + + if ( menu == searchMenu ) + return true + } + + return false +} + +var function GetTopNonDialogMenu() +{ + array<var> menuArray = clone uiGlobal.menuStack + menuArray.reverse() + + foreach ( menu in menuArray ) + { + if ( menu == null || IsDialog( menu ) ) + continue + + return menu + } + + return null +} + +void function CleanupInGameMenus() +{ + Signal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + CloseAllInGameMenus() + Assert( uiGlobal.activeMenu == null ) + if ( uiGlobal.menuStack.len() ) + { + if ( uiGlobal.loadingLevel == "" ) + CloseActiveMenu() // Disconnected. Remove stack null and open main menu. + else + CloseActiveMenu( true, false ) // Level to level transition. Remove stack null and DON'T open main menu. + } +} + +var function GetActiveMenu() +{ + return uiGlobal.activeMenu +} + +var function GetMenu( string menuName ) +{ + return uiGlobal.menus[ menuName ] +} + +var function GetPanel( string panelName ) +{ + return uiGlobal.panels[ panelName ] +} + +array<var> function GetAllMenuPanels( var menu ) +{ + array<var> menuPanels + + foreach ( panel in uiGlobal.allPanels ) + { + if ( Hud_GetParent( panel ) == menu ) + menuPanels.append( panel ) + } + + return menuPanels +} + +void function InitGamepadConfigs() +{ + uiGlobal.buttonConfigs = [ { orthodox = "gamepad_button_layout_default.cfg", southpaw = "gamepad_button_layout_default_southpaw.cfg" } ] + uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_bumper_jumper.cfg", southpaw = "gamepad_button_layout_bumper_jumper_southpaw.cfg" } ) + uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_bumper_jumper_alt.cfg", southpaw = "gamepad_button_layout_bumper_jumper_alt_southpaw.cfg" } ) + uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_pogo_stick.cfg", southpaw = "gamepad_button_layout_pogo_stick_southpaw.cfg" } ) + uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_button_kicker.cfg", southpaw = "gamepad_button_layout_button_kicker_southpaw.cfg" } ) + uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_circle.cfg", southpaw = "gamepad_button_layout_circle_southpaw.cfg" } ) + uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_ninja.cfg", southpaw = "gamepad_button_layout_ninja_southpaw.cfg" } ) + uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_custom.cfg", southpaw = "gamepad_button_layout_custom.cfg" } ) + + uiGlobal.stickConfigs = [] + uiGlobal.stickConfigs.append( "gamepad_stick_layout_default.cfg" ) + uiGlobal.stickConfigs.append( "gamepad_stick_layout_southpaw.cfg" ) + uiGlobal.stickConfigs.append( "gamepad_stick_layout_legacy.cfg" ) + uiGlobal.stickConfigs.append( "gamepad_stick_layout_legacy_southpaw.cfg" ) + + foreach ( key, val in uiGlobal.buttonConfigs ) + { + VPKNotifyFile( "cfg/" + val.orthodox ) + VPKNotifyFile( "cfg/" + val.southpaw ) + } + + foreach ( key, val in uiGlobal.stickConfigs ) + VPKNotifyFile( "cfg/" + val ) + + ExecCurrentGamepadButtonConfig() + ExecCurrentGamepadStickConfig() + + SetStandardAbilityBindingsForPilot( GetLocalClientPlayer() ) +} + +void function InitMenus() +{ + InitGlobalMenuVars() + SpShWeaponsInit() + + AddMenu( "MainMenu", $"resource/ui/menus/main.menu", InitMainMenu, "#MAIN" ) + AddPanel( GetMenu( "MainMenu" ), "EstablishUserPanel", InitEstablishUserPanel ) + AddPanel( GetMenu( "MainMenu" ), "MainMenuPanel", InitMainMenuPanel ) + + AddMenu( "PlayVideoMenu", $"resource/ui/menus/play_video.menu", InitPlayVideoMenu ) + AddMenu( "LobbyMenu", $"resource/ui/menus/lobby.menu", InitLobbyMenu, "#LOBBY" ) + + AddMenu( "FDMenu", $"resource/ui/menus/playlist_fd.menu", InitFDPlaylistMenu ) + AddMenu( "TeamTitanSelectMenu", $"resource/ui/menus/team_titan_select.menu", InitTeamTitanSelectMenu ) + AddMenu( "PlaylistMenu", $"resource/ui/menus/playlist.menu", InitPlaylistMenu ) + AddMenu( "PlaylistMixtapeMenu", $"resource/ui/menus/playlist_mixtape.menu", InitPlaylistMixtapeMenu ) + AddMenu( "PlaylistMixtapeChecklistMenu", $"resource/ui/menus/playlist_mixtape_checklist.menu", InitPlaylistMixtapeChecklistMenu ) + + AddMenu( "SinglePlayerDevMenu", $"resource/ui/menus/singleplayer_dev.menu", InitSinglePlayerDevMenu, "SINGLE PLAYER DEV" ) + AddMenu( "SinglePlayerMenu", $"resource/ui/menus/singleplayer.menu", InitSinglePlayerMenu, "SINGLE PLAYER" ) + + AddMenu( "SearchMenu", $"resource/ui/menus/search.menu", InitSearchMenu ) + + AddMenu( "GammaMenu", $"resource/ui/menus/gamma.menu", InitGammaMenu, "#BRIGHTNESS" ) + + AddMenu( "CommunitiesMenu", $"resource/ui/menus/community.menu", InitCommunitiesMenu ) + AddMenu( "Notifications", $"resource/ui/menus/notifications.menu", InitNotificationsMenu ) + AddMenu( "MyNetworks", $"resource/ui/menus/communities_mine.menu", InitMyNetworksMenu ) + AddMenu( "InboxFrontMenu", $"resource/ui/menus/inbox_front.menu", InitInboxFrontMenu ) + AddMenu( "Inbox", $"resource/ui/menus/inbox.menu", InitInboxMenu ) + AddMenu( "BrowseCommunities", $"resource/ui/menus/communities_browse.menu" ) + AddMenu( "CommunityEditMenu", $"resource/ui/menus/community_edit.menu" ) + AddMenu( "CommunityAdminSendMessage", $"resource/ui/menus/community_sendMessage.menu" ) + AddMenu( "CommunityAdminInviteRequestMenu", $"resource/ui/menus/community_inviteRequest.menu" ) +#if NETWORK_INVITE + AddMenu( "InviteFriendsToNetworkMenu", $"resource/ui/menus/invite_friends.menu", InitInviteFriendsToNetworkMenu ) +#endif + + AddMenu( "InGameMPMenu", $"resource/ui/menus/ingame_mp.menu", InitInGameMPMenu ) + AddMenu( "InGameSPMenu", $"resource/ui/menus/ingame_sp.menu", InitInGameSPMenu ) + + AddMenu( "Dialog", $"resource/ui/menus/dialog.menu", InitDialogMenu ) + AddMenu( "AnnouncementDialog", $"resource/ui/menus/dialog_announcement.menu", InitAnnouncementDialog ) + AddMenu( "ConnectingDialog", $"resource/ui/menus/dialog_connecting.menu", InitConnectingDialog ) + AddMenu( "DataCenterDialog", $"resource/ui/menus/dialog_datacenter.menu", InitDataCenterDialogMenu ) + AddMenu( "EULADialog", $"resource/ui/menus/dialog_eula.menu", InitEULADialog ) + AddMenu( "ReviewTermsDialog", $"resource/ui/menus/dialog_review_terms.menu", InitReviewTermsDialog ) + AddMenu( "RegistrationDialog", $"resource/ui/menus/dialog_registration.menu", InitRegistrationDialog ) + AddMenu( "AdvocateGiftDialog", $"resource/ui/menus/dialog_advocate_gift.menu", InitAdvocateGiftDialog ) + + AddMenu( "ControlsMenu", $"resource/ui/menus/controls.menu", InitControlsMenu, "#CONTROLS" ) + AddMenu( "ControlsAdvancedLookMenu", $"resource/ui/menus/controls_advanced_look.menu", InitControlsAdvancedLookMenu, "#CONTROLS_ADVANCED_LOOK" ) + AddMenu( "GamepadLayoutMenu", $"resource/ui/menus/gamepadlayout.menu", InitGamepadLayoutMenu ) +#if PC_PROG + AddMenu_WithCreateFunc( "MouseKeyboardBindingsMenu", $"resource/ui/menus/mousekeyboardbindings.menu", InitMouseKeyboardMenu, CreateKeyBindingMenu ) + AddMenu( "AudioMenu", $"resource/ui/menus/audio.menu", InitAudioMenu, "#AUDIO" ) + AddMenu_WithCreateFunc( "VideoMenu", $"resource/ui/menus/video.menu", InitVideoMenu, CreateVideoOptionsMenu ) +#elseif CONSOLE_PROG + AddMenu( "AudioVideoMenu", $"resource/ui/menus/audio_video.menu", InitAudioVideoMenu, "#AUDIO_VIDEO" ) +#endif + + AddMenu( "AdvancedHudMenu", $"resource/ui/menus/advanced_hud.menu", InitAdvancedHudMenu, "#ADVANCED_HUD" ) + + AddMenu( "PilotLoadoutsMenu", $"resource/ui/menus/pilotloadouts.menu", InitPilotLoadoutsMenu ) + AddMenu( "TitanLoadoutsMenu", $"resource/ui/menus/titanloadouts.menu", InitTitanLoadoutsMenu ) + AddMenu( "EditPilotLoadoutsMenu", $"resource/ui/menus/pilotloadouts.menu", InitEditPilotLoadoutsMenu ) + AddMenu( "EditTitanLoadoutsMenu", $"resource/ui/menus/titanloadouts.menu", InitEditTitanLoadoutsMenu ) + AddMenu( "EditPilotLoadoutMenu", $"resource/ui/menus/editpilotloadout.menu", InitEditPilotLoadoutMenu ) + AddMenu( "EditTitanLoadoutMenu", $"resource/ui/menus/edittitanloadout.menu", InitEditTitanLoadoutMenu ) + + AddMenu( "SPTitanLoadoutMenu", $"resource/ui/menus/sptitanloadout.menu", InitSPTitanLoadoutMenu ) + AddMenu( "SPTitanLoadoutTutorialMenu", $"resource/ui/menus/sptitanloadout_tutorial.menu", InitSPTitanLoadoutTutorialMenu ) + + AddMenu( "SuitSelectMenu", $"resource/ui/menus/suitselect.menu", InitSuitSelectMenu ) + AddMenu( "WeaponSelectMenu", $"resource/ui/menus/weaponselect.menu", InitWeaponSelectMenu ) + AddMenu( "CategorySelectMenu", $"resource/ui/menus/categoryselect.menu", InitCategorySelectMenu ) + AddMenu( "AbilitySelectMenu", $"resource/ui/menus/abilityselect.menu", InitAbilitySelectMenu ) + AddMenu( "PassiveSelectMenu", $"resource/ui/menus/passiveselect.menu", InitPassiveSelectMenu ) + AddSubmenu( "ModSelectMenu", $"resource/ui/menus/modselect.menu", InitModSelectMenu ) + AddMenu( "CamoSelectMenu", $"resource/ui/menus/camoselect.menu", InitCamoSelectMenu ) + AddMenu( "NoseArtSelectMenu", $"resource/ui/menus/noseartselect.menu", InitNoseArtSelectMenu ) + AddMenu( "CallsignCardSelectMenu", $"resource/ui/menus/callsigncardselect.menu", InitCallsignCardSelectMenu ) + AddMenu( "CallsignIconSelectMenu", $"resource/ui/menus/callsigniconselect.menu", InitCallsignIconSelectMenu ) + AddMenu( "BoostStoreMenu", $"resource/ui/menus/booststore.menu", InitBoostStoreMenu ) + + AddMenu( "PrivateLobbyMenu", $"resource/ui/menus/private_lobby.menu", InitPrivateMatchMenu, "#PRIVATE_MATCH" ) + AddMenu( "MapsMenu", $"resource/ui/menus/map_select.menu", InitMapsMenu ) + AddMenu( "ModesMenu", $"resource/ui/menus/mode_select.menu", InitModesMenu ) + AddMenu( "MatchSettingsMenu", $"resource/ui/menus/match_settings.menu", InitMatchSettingsMenu ) + + AddMenu( "Advocate_Letter", $"resource/ui/menus/advocate_letter.menu", InitAdvocateLetterMenu ) + AddMenu( "Generation_Respawn", $"resource/ui/menus/generation_respawn.menu", InitGenerationRespawnMenu ) + AddMenu( "ChallengesMenu", $"resource/ui/menus/challenges.menu", InitChallengesMenu ) + + AddMenu( "ViewStatsMenu", $"resource/ui/menus/viewstats.menu", InitViewStatsMenu, "#PERSONAL_STATS" ) + AddMenu( "ViewStats_Overview_Menu", $"resource/ui/menus/viewstats_overview.menu", InitViewStatsOverviewMenu ) + //AddMenu( "ViewStats_Kills_Menu", $"resource/ui/menus/viewstats_kills.menu", InitViewStatsKillsMenu ) + AddMenu( "ViewStats_Time_Menu", $"resource/ui/menus/viewstats_time.menu", InitViewStatsTimeMenu ) + //AddMenu( "ViewStats_Distance_Menu", $"resource/ui/menus/viewstats_distance.menu", InitViewStatsDistanceMenu ) + AddMenu( "ViewStats_Weapons_Menu", $"resource/ui/menus/viewstats_weapons.menu", InitViewStatsWeaponsMenu ) + AddMenu( "ViewStats_Titans_Menu", $"resource/ui/menus/viewstats_titans.menu", InitViewStatsTitansMenu ) + AddMenu( "ViewStats_Misc_Menu", $"resource/ui/menus/viewstats_misc.menu", InitViewStatsMiscMenu ) + AddMenu( "ViewStats_Maps_Menu", $"resource/ui/menus/viewstats_maps.menu", InitViewStatsMapsMenu ) + + AddMenu( "PostGameMenu", $"resource/ui/menus/postgame.menu", InitPostGameMenu ) + AddMenu( "EOG_XP", $"resource/ui/menus/eog_xp.menu", InitEOG_XPMenu ) + AddMenu( "EOG_Coins", $"resource/ui/menus/eog_coins.menu", InitEOG_CoinsMenu ) + AddMenu( "EOG_Challenges", $"resource/ui/menus/eog_challenges.menu", InitEOG_ChallengesMenu ) + AddMenu( "EOG_Unlocks", $"resource/ui/menus/eog_unlocks.menu", InitEOG_UnlocksMenu ) + AddMenu( "EOG_Scoreboard", $"resource/ui/menus/eog_scoreboard.menu", InitEOG_ScoreboardMenu ) + + AddMenu( "CreditsMenu", $"resource/ui/menus/credits.menu", InitCreditsMenu, "#CREDITS" ) + + AddMenu( "BurnCardMenu", $"resource/ui/menus/burn_cards.menu", InitBurnCardMenu, "#MENU_BURNCARD_MENU" ) + AddMenu( "FactionChoiceMenu", $"resource/ui/menus/faction_choice.menu", InitFactionChoiceMenu, "#FACTION_CHOICE_MENU" ) + AddMenu( "ArmoryMenu", $"resource/ui/menus/armory.menu", InitArmoryMenu, "#ARMORY_MENU" ) + + AddMenu( "StoreMenu", $"resource/ui/menus/store.menu", InitStoreMenu, "#STORE_MENU" ) + AddMenu( "StoreMenu_NewReleases", $"resource/ui/menus/store_new_releases.menu", InitStoreMenuNewReleases, "#STORE_NEW_RELEASES" ) + AddMenu( "StoreMenu_Limited", $"resource/ui/menus/store_limited.menu", InitStoreMenuLimited, "#STORE_LIMITED" ) + AddMenu( "StoreMenu_Sales", $"resource/ui/menus/store_bundles.menu", InitStoreMenuSales, "#STORE_BUNDLES" ) + AddMenu( "StoreMenu_Titans", $"resource/ui/menus/store_prime_titans.menu", InitStoreMenuTitans, "#STORE_TITANS" ) // reusing store_prime_titans.menu + AddMenu( "StoreMenu_PrimeTitans", $"resource/ui/menus/store_prime_titans.menu", InitStoreMenuPrimeTitans, "#STORE_PRIME_TITANS" ) + //AddMenu( "StoreMenu_WeaponSelect", $"resource/ui/menus/store_weapon_select.menu", InitStoreMenuWeaponSelect ) + //AddMenu( "StoreMenu_WeaponSkinPreview", $"resource/ui/menus/store_weapon_skin_preview.menu", InitStoreMenuWeaponSkinPreview ) + AddMenu( "StoreMenu_WeaponSkinBundles", $"resource/ui/menus/store_weapon_skin_bundles.menu", InitStoreMenuWeaponSkinBundles ) + AddMenu( "StoreMenu_WeaponSkins", $"resource/ui/menus/store_weapons.menu", InitStoreMenuWeaponSkins ) + AddMenu( "StoreMenu_Customization", $"resource/ui/menus/store_customization.menu", InitStoreMenuCustomization, "#STORE_CUSTOMIZATION_PACKS" ) + AddMenu( "StoreMenu_CustomizationPreview", $"resource/ui/menus/store_customization_preview.menu", InitStoreMenuCustomizationPreview, "#STORE_CUSTOMIZATION_PACKS" ) + AddMenu( "StoreMenu_Camo", $"resource/ui/menus/store_camo.menu", InitStoreMenuCamo, "#STORE_CAMO_PACKS" ) + AddMenu( "StoreMenu_CamoPreview", $"resource/ui/menus/store_camo_preview.menu", InitStoreMenuCamoPreview, "#STORE_CAMO_PACKS" ) + AddMenu( "StoreMenu_Callsign", $"resource/ui/menus/store_callsign.menu", InitStoreMenuCallsign, "#STORE_CALLSIGN_PACKS" ) + AddMenu( "StoreMenu_CallsignPreview", $"resource/ui/menus/store_callsign_preview.menu", InitStoreMenuCallsignPreview, "#STORE_CALLSIGN_PACKS" ) + + AddMenu( "KnowledgeBaseMenu", $"resource/ui/menus/knowledgebase.menu", InitKnowledgeBaseMenu ) + AddMenu( "KnowledgeBaseMenuSubMenu", $"resource/ui/menus/knowledgebase_submenu.menu", InitKnowledgeBaseMenuSubMenu ) + + AddMenu( "DevMenu", $"resource/ui/menus/dev.menu", InitDevMenu, "Dev" ) + InitSharedStartPoints() + + foreach ( menu in uiGlobal.allMenus ) + { + if ( uiGlobal.menuData[ menu ].initFunc != null ) + uiGlobal.menuData[ menu ].initFunc() + + array<var> elems = GetElementsByClassname( menu, "TabsCommonClass" ) + if ( elems.len() ) + uiGlobal.menuData[ menu ].hasTabs = true + + elems = GetElementsByClassname( menu, "EnableKeyBindingIcons" ) + foreach ( elem in elems ) + Hud_EnableKeyBindingIcons( elem ) + } + + InitTabs() + + var tabbedMenu = GetMenu( "PostGameMenu" ) + AddPanel( tabbedMenu, "PVEPanel", InitPVEPanel ) + AddPanel( tabbedMenu, "SummaryPanel", InitSummaryPanel ) + AddPanel( tabbedMenu, "FDAwardsPanel", InitFDAwardsPanel ) + + AddPanel( tabbedMenu, "ScoreboardPanel", InitScoreboardPanel ) + + foreach ( panel in uiGlobal.allPanels ) + { + if ( uiGlobal.panelData[ panel ].initFunc != null ) + uiGlobal.panelData[ panel ].initFunc() + } + + // A little weird, but GetElementsByClassname() uses menu scope rather than parent scope. + foreach ( menu in uiGlobal.allMenus ) + { + array<var> buttons = GetElementsByClassname( menu, "DefaultFocus" ) + foreach ( button in buttons ) + { + var panel = Hud_GetParent( button ) + + //Assert( elems.len() == 1, "More than 1 panel element set as DefaultFocus!" ) + Assert( panel != null, "no parent panel found for button " + Hud_GetHudName( button ) ) + Assert( panel in uiGlobal.panelData, "panel " + Hud_GetHudName( panel ) + " isn't in uiGlobal.panelData, but button " + Hud_GetHudName( button ) + " has defaultFocus set!" ) + uiGlobal.panelData[ panel ].defaultFocus = button + //printt( "Found DefaultFocus, button was:", Hud_GetHudName( button ), "panel was:", Hud_GetHudName( panel ) ) + } + } + + InitFooterOptions() + + #if DEV + if ( Dev_CommandLineHasParm( "-autoprecache_all" ) ) + { + // repreache all levels + ExecuteLoadingClientCommands_SetStartPoint( "sp_training" ) + ClientCommand( "map sp_training" ) + CloseAllMenus() + } + #endif +} + +void functionref( var ) function AdvanceMenuEventHandler( var menu ) +{ + return void function( var item ) : ( menu ) + { + if ( Hud_IsLocked( item ) ) + return + + AdvanceMenu( menu ) + } +} + +void function PCBackButton_Activate( var button ) +{ + UICodeCallback_NavigateBack() +} + +void function PCSwitchTeamsButton_Activate( var button ) +{ + ClientCommand( "PrivateMatchSwitchTeams" ) +} + +void function PCToggleSpectateButton_Activate( var button ) +{ + ClientCommand( "PrivateMatchToggleSpectate" ) +} + +void function ToggleButtonStates( var button ) +{ + for ( ;; ) + { + Hud_SetEnabled( button, true ) + wait 1 + Hud_SetSelected( button, true ) + wait 1 + Hud_SetLocked( button, true ) + wait 1 + Hud_SetNew( button, true ) + wait 1 + Hud_SetNew( button, false ) + wait 1 + Hud_SetLocked( button, false ) + wait 1 + Hud_SetSelected( button, false ) + wait 1 + Hud_SetEnabled( button, false ) + wait 1 + } +} + +void function AddMenuElementsByClassname( var menu, string classname ) +{ + array<var> elements = GetElementsByClassname( menu, classname ) + + if ( !(classname in menu.classElements) ) + menu.classElements[classname] <- [] + + menu.classElements[classname].extend( elements ) +} + +void function FocusDefault( var menu ) +{ + if ( + menu == GetMenu( "MainMenu" ) || + menu == GetMenu( "CategorySelectMenu" ) || + menu == GetMenu( "AbilitySelectMenu" ) || + menu == GetMenu( "PassiveSelectMenu" ) || + menu == GetMenu( "WeaponSelectMenu" ) || + menu == GetMenu( "SuitSelectMenu" ) || + menu == GetMenu( "CamoSelectMenu" ) || + menu == GetMenu( "NoseArtSelectMenu" ) || + menu == GetMenu( "FactionChoiceMenu" ) || + menu == GetMenu( "BurnCardMenu" ) || + menu == GetMenu( "CallsignCardSelectMenu" ) || + menu == GetMenu( "CallsignIconSelectMenu" ) ) + { + } + else + { + //printt( "FocusDefaultMenuItem() called" ) + FocusDefaultMenuItem( menu ) + } +} + +void function SetPanelDefaultFocus( var panel, var button ) +{ + uiGlobal.panelData[ panel ].defaultFocus = button +} + +void function PanelFocusDefault( var panel ) +{ + //printt( "PanelFocusDefault called" ) + if ( uiGlobal.panelData[ panel ].defaultFocus ) + { + Hud_SetFocused( uiGlobal.panelData[ panel ].defaultFocus ) + //printt( "PanelFocusDefault if passed,", Hud_GetHudName( uiGlobal.panelData[ panel ].defaultFocus ), "focused" ) + } +} + +void function SetMenuThinkFunc( var menu, void functionref() func ) +{ + Assert( uiGlobal.menuData[ menu ].thinkFunc == null ) + uiGlobal.menuData[ menu ].thinkFunc = func +} + +void function AddMenuEventHandler( var menu, int event, void functionref() func ) +{ + if ( event == eUIEvent.MENU_OPEN ) + { + Assert( uiGlobal.menuData[ menu ].openFunc == null ) + uiGlobal.menuData[ menu ].openFunc = func + } + else if ( event == eUIEvent.MENU_CLOSE ) + { + Assert( uiGlobal.menuData[ menu ].closeFunc == null ) + uiGlobal.menuData[ menu ].closeFunc = func + } + else if ( event == eUIEvent.MENU_SHOW ) + { + Assert( uiGlobal.menuData[ menu ].showFunc == null ) + uiGlobal.menuData[ menu ].showFunc = func + } + else if ( event == eUIEvent.MENU_HIDE ) + { + Assert( uiGlobal.menuData[ menu ].hideFunc == null ) + uiGlobal.menuData[ menu ].hideFunc = func + } + else if ( event == eUIEvent.MENU_NAVIGATE_BACK ) + { + Assert( uiGlobal.menuData[ menu ].navBackFunc == null ) + uiGlobal.menuData[ menu ].navBackFunc = func + } + else if ( event == eUIEvent.MENU_TAB_CHANGED ) + { + Assert( uiGlobal.menuData[ menu ].tabChangedFunc == null ) + uiGlobal.menuData[ menu ].tabChangedFunc = func + } + else if ( event == eUIEvent.MENU_ENTITLEMENTS_CHANGED ) + { + Assert( uiGlobal.menuData[ menu ].entitlementsChangedFunc == null ) + uiGlobal.menuData[ menu ].entitlementsChangedFunc = func + } + else if ( event == eUIEvent.MENU_INPUT_MODE_CHANGED ) + { + Assert( uiGlobal.menuData[ menu ].inputModeChangedFunc == null ) + uiGlobal.menuData[ menu ].inputModeChangedFunc = func + } +} + +void function AddPanelEventHandler( var panel, int event, void functionref() func ) +{ + if ( event == eUIEvent.PANEL_SHOW ) + uiGlobal.panelData[ panel ].showFunc = func + else if ( event == eUIEvent.PANEL_HIDE ) + uiGlobal.panelData[ panel ].hideFunc = func +} + +// TODO: Get a real on open event from code? +void function OpenMenuWrapper( var menu, bool focusDefault ) +{ + OpenMenu( menu ) + printt( Hud_GetHudName( menu ), "menu opened" ) + + Assert( menu in uiGlobal.menuData ) + if ( uiGlobal.menuData[ menu ].openFunc != null ) + { + thread uiGlobal.menuData[ menu ].openFunc() + //printt( "Called openFunc for:", menu.GetHudName() ) + } + + if ( focusDefault ) + FocusDefault( menu ) + + //UpdateMenuTabs() + UpdateFooterOptions() +} + +void function CloseMenuWrapper( var menu ) +{ + CloseMenu( menu ) + printt( Hud_GetHudName( menu ), "menu closed" ) + + Assert( menu in uiGlobal.menuData ) + if ( uiGlobal.menuData[ menu ].closeFunc != null ) + { + thread uiGlobal.menuData[ menu ].closeFunc() + //printt( "Called closeFunc for:", Hud_GetHudName( menu ) ) + } +} + +bool function IsLevelMultiplayer( string levelname ) +{ + return levelname.find( "mp_" ) == 0 +} + +void function AddButtonEventHandler( var button, int event, void functionref( var ) func ) +{ + Hud_AddEventHandler( button, event, func ) +} + +void function AddEventHandlerToButton( var menu, string buttonName, int event, void functionref( var ) func ) +{ + var button = Hud_GetChild( menu, buttonName ) + Hud_AddEventHandler( button, event, func ) +} + +void function AddEventHandlerToButtonClass( var menu, string classname, int event, void functionref( var ) func ) +{ + array<var> buttons = GetElementsByClassname( menu, classname ) + + foreach ( button in buttons ) + { + //printt( "button name:", Hud_GetHudName( button ) ) + Hud_AddEventHandler( button, event, func ) + } +} + +// Added slight delay to main menu music to work around a hitch caused when the game first starts up +void function PlayMusicAfterDelay() +{ + wait MAINMENU_MUSIC_DELAY + if ( uiGlobal.playingMusic ) + EmitUISound( "MainMenu_Music" ) +} + +void function DisableMusic() +{ + EmitUISound( "Movie_MuteAllGameSound" ) +} + +void function EnableMusic() +{ + StopUISoundByName( "Movie_MuteAllGameSound" ) +} + +void function PlayMusic() +{ + if ( !uiGlobal.playingMusic && !uiGlobal.playingVideo && !uiGlobal.playingCredits ) + { + //printt( "PlayMusic() called. Playing: MainMenu_Music. uiGlobal.playingMusic:", uiGlobal.playingMusic, "uiGlobal.playingVideo:", uiGlobal.playingVideo, "uiGlobal.playingCredits:", uiGlobal.playingCredits ) + uiGlobal.playingMusic = true + thread PlayMusicAfterDelay() + } + else + { + //printt( "PlayMusic() called, but doing nothing. uiGlobal.playingMusic:", uiGlobal.playingMusic, "uiGlobal.playingVideo:", uiGlobal.playingVideo, "uiGlobal.playingCredits:", uiGlobal.playingCredits ) + } +} + +void function StopMusic() +{ + //printt( "StopMusic() called. Stopping: MainMenu_Music" ) + StopUISound( "MainMenu_Music" ) + uiGlobal.playingMusic = false +} + +void function RegisterMenuVarInt( string varName, int value ) +{ + table<string, int> intVars = uiGlobal.intVars + + Assert( !( varName in intVars ) ) + + intVars[varName] <- value +} + +void function RegisterMenuVarBool( string varName, bool value ) +{ + table<string, bool> boolVars = uiGlobal.boolVars + + Assert( !( varName in boolVars ) ) + + boolVars[varName] <- value +} + +void function RegisterMenuVarVar( string varName, var value ) +{ + table<string, var> varVars = uiGlobal.varVars + + Assert( !( varName in varVars ) ) + + varVars[varName] <- value +} + +int function GetMenuVarInt( string varName ) +{ + table<string, int> intVars = uiGlobal.intVars + + Assert( varName in intVars ) + + return intVars[varName] +} + +bool function GetMenuVarBool( string varName ) +{ + table<string, bool> boolVars = uiGlobal.boolVars + + Assert( varName in boolVars ) + + return boolVars[varName] +} + +var function GetMenuVarVar( string varName ) +{ + table<string, var> varVars = uiGlobal.varVars + + Assert( varName in varVars ) + + return varVars[varName] +} + +void function SetMenuVarInt( string varName, int value ) +{ + table<string, int> intVars = uiGlobal.intVars + + Assert( varName in intVars ) + + if ( intVars[varName] == value ) + return + + intVars[varName] = value + + table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs + + if ( varName in varChangeFuncs ) + { + foreach ( func in varChangeFuncs[varName] ) + { + //printt( varName, "changed, calling changeFunc:", string( func ) ) + func() + } + } +} + +void function SetMenuVarBool( string varName, bool value ) +{ + table<string, bool> boolVars = uiGlobal.boolVars + + Assert( varName in boolVars ) + + if ( boolVars[varName] == value ) + return + + boolVars[varName] = value + + table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs + + if ( varName in varChangeFuncs ) + { + foreach ( func in varChangeFuncs[varName] ) + { + //printt( varName, "changed, calling changeFunc:", string( func ) ) + func() + } + } +} + +void function SetMenuVarVar( string varName, var value ) +{ + table<string, var> varVars = uiGlobal.varVars + + Assert( varName in varVars ) + + if ( varVars[varName] == value ) + return + + varVars[varName] = value + + table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs + + if ( varName in varChangeFuncs ) + { + foreach ( func in varChangeFuncs[varName] ) + { + //printt( varName, "changed, calling changeFunc:", string( func ) ) + func() + } + } +} + +void function AddMenuVarChangeHandler( string varName, void functionref() func ) +{ + table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs + + if ( !( varName in varChangeFuncs ) ) + varChangeFuncs[varName] <- [] + + // TODO: Verify we're not duplicating an existing func + varChangeFuncs[varName].append( func ) +} + +// These are common menu statuses that trigger menu logic any time they change +// They should become code callbacks, so script doesn't poll +void function InitGlobalMenuVars() +{ + RegisterMenuVarVar( "focus", null ) + RegisterMenuVarBool( "isConnected", false ) + RegisterMenuVarBool( "isFullyConnected", false ) + RegisterMenuVarBool( "isPartyLeader", false ) + RegisterMenuVarBool( "isPrivateMatch", false ) + RegisterMenuVarBool( "isGamepadActive", IsControllerModeActive() ) + + #if CONSOLE_PROG + RegisterMenuVarBool( "CONSOLE_isOnline", false ) + RegisterMenuVarBool( "CONSOLE_isSignedIn", false ) + #endif // CONSOLE_PROG + + #if DURANGO_PROG + RegisterMenuVarBool( "DURANGO_isGameFullyInstalled", false ) + RegisterMenuVarBool( "DURANGO_canInviteFriends", false ) + RegisterMenuVarBool( "DURANGO_isJoinable", false ) + #elseif PS4_PROG + RegisterMenuVarBool( "PS4_canInviteFriends", false) + #elseif PC_PROG + RegisterMenuVarBool( "ORIGIN_isEnabled", false ) + RegisterMenuVarBool( "ORIGIN_isJoinable", false ) + #endif + + thread UpdateFocus() + thread UpdateIsConnected() + thread UpdateIsFullyConnected() + thread UpdateAmIPartyLeader() + thread UpdateIsPrivateMatch() + thread UpdateActiveMenuThink() + + #if CONSOLE_PROG + thread UpdateConsole_IsOnline() + thread UpdateConsole_IsSignedIn() + #endif // CONSOLE_PROG + + #if DURANGO_PROG + thread UpdateDurango_IsGameFullyInstalled() + thread UpdateDurango_CanInviteFriends() + thread UpdateDurango_IsJoinable() + #elseif PS4_PROG + thread UpdatePS4_CanInviteFriends() + #elseif PC_PROG + thread UpdateOrigin_IsEnabled() + thread UpdateOrigin_IsJoinable() + thread UpdateIsGamepadActive() + #endif +} + +void function UpdateFocus() +{ + while ( true ) + { + SetMenuVarVar( "focus", GetFocus() ) + WaitFrame() + } +} + +void function UpdateActiveMenuThink() +{ + while ( true ) + { + var menu = GetActiveMenu() + if ( menu ) + { + Assert( menu in uiGlobal.menuData ) + if ( uiGlobal.menuData[ menu ].thinkFunc != null ) + uiGlobal.menuData[ menu ].thinkFunc() + } + + WaitFrame() + } +} + +void function UpdateIsConnected() +{ + while ( true ) + { + SetMenuVarBool( "isConnected", IsConnected() ) + WaitFrame() + } +} + +void function UpdateIsFullyConnected() +{ + while ( true ) + { + SetMenuVarBool( "isFullyConnected", IsFullyConnected() ) + WaitFrame() + } +} + +void function UpdateAmIPartyLeader() +{ + while ( true ) + { + SetMenuVarBool( "isPartyLeader", AmIPartyLeader() ) + WaitFrame() + } +} + +void function UpdateIsPrivateMatch() +{ + while ( true ) + { + SetMenuVarBool( "isPrivateMatch", IsPrivateMatch() ) + WaitFrame() + } +} + +#if CONSOLE_PROG + void function UpdateConsole_IsOnline() + { + while ( true ) + { + SetMenuVarBool( "CONSOLE_isOnline", Console_IsOnline() ) + WaitFrame() + } + } + + void function UpdateConsole_IsSignedIn() + { + while ( true ) + { + SetMenuVarBool( "CONSOLE_isSignedIn", Console_IsSignedIn() ) + WaitFrame() + } + } +#endif // CONSOLE_PROG + + +#if PS4_PROG + void function UpdatePS4_CanInviteFriends() + { + while ( true ) + { + SetMenuVarBool( "PS4_canInviteFriends", PS4_canInviteFriends() ) + WaitFrame() + } + } +#endif // PS4_PROG + + + +#if DURANGO_PROG + void function UpdateDurango_IsGameFullyInstalled() + { + while ( true ) + { + SetMenuVarBool( "DURANGO_isGameFullyInstalled", IsGameFullyInstalled() ) + wait 1 // Poll less frequent + } + } + + void function UpdateDurango_CanInviteFriends() + { + while ( true ) + { + SetMenuVarBool( "DURANGO_canInviteFriends", Durango_CanInviteFriends() ) + WaitFrame() + } + } + + void function UpdateDurango_IsJoinable() + { + while ( true ) + { + SetMenuVarBool( "DURANGO_isJoinable", Durango_IsJoinable() ) + WaitFrame() + } + } +#endif // DURANGO_PROG + +#if PC_PROG + void function UpdateOrigin_IsEnabled() + { + while ( true ) + { + SetMenuVarBool( "ORIGIN_isEnabled", Origin_IsEnabled() ) + WaitFrame() + } + } + + void function UpdateOrigin_IsJoinable() + { + while ( true ) + { + SetMenuVarBool( "ORIGIN_isJoinable", Origin_IsJoinable() ) + WaitFrame() + } + } + + void function UpdateIsGamepadActive() + { + while ( true ) + { + SetMenuVarBool( "isGamepadActive", IsControllerModeActive() ) + WaitFrame() + } + } +#endif // PC_PROG + +void function InviteFriends( var button ) +{ + //AdvanceMenu( GetMenu( "InviteFriendsToPartyMenu" ) ) + + #if DURANGO_PROG + Durango_InviteFriends() + #elseif PS4_PROG + ClientCommand("session_debug_invite"); + #elseif PC_PROG + Assert( Origin_IsEnabled() ) + Assert( Origin_IsJoinable() ) + + Origin_ShowInviteFriendsDialog() + #endif +} + +#if DURANGO_PROG +void function OpenXboxPartyApp( var button ) +{ + Durango_OpenPartyApp() +} + +void function OpenXboxHelp( var button ) +{ + Durango_ShowHelpWindow() +} +#endif // DURANGO_PROG + +void function OpenReviewTermsDialog( var button ) +{ + AdvanceMenu( GetMenu( "ReviewTermsDialog" ) ) +} + +void function OpenErrorDialog( string errorDetails ) +{ + DialogData dialogData + dialogData.header = "#ERROR" + dialogData.message = errorDetails + dialogData.image = $"ui/menu/common/dialog_error" + +#if PC_PROG + AddDialogButton( dialogData, "#DISMISS" ) + + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) +#endif // PC_PROG + AddDialogFooter( dialogData, "#B_BUTTON_DISMISS_RUI" ) + + while ( uiGlobal.activeMenu != GetMenu( "MainMenu" ) ) + { + WaitSignal( uiGlobal.signalDummy, "OpenErrorDialog", "ActiveMenuChanged" ) + } + + OpenDialog( dialogData ) +} + +bool function IsDialog( var menu ) +{ + if ( menu == null ) + return false + + return uiGlobal.menuData[ menu ].isDialog +} + +bool function IsDialogActive( DialogData dialogData ) +{ + if ( !IsDialog( uiGlobal.activeMenu ) ) + return false + + return uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData == dialogData +} + +bool function IsDialogOnlyActiveMenu() +{ + if ( !IsDialog( uiGlobal.activeMenu ) ) + return false + + int stackLen = uiGlobal.menuStack.len() + if ( stackLen < 1 ) + return false + + if ( uiGlobal.menuStack[stackLen - 1] != uiGlobal.activeMenu ) + return false + + if ( stackLen == 1 ) + return true + + if ( uiGlobal.menuStack[stackLen - 2] == null ) + return true + + return false +} + +void function SetNavUpDown( array<var> buttons, var wrap = true ) +{ + Assert( buttons.len() > 0 ) + + var first = buttons[0] + var last = buttons[buttons.len() - 1] + var prev + var next + var button + + for ( int i = 0; i < buttons.len(); i++ ) + { + button = buttons[i] + + if ( button == first ) + prev = last + else + prev = buttons[i - 1] + + if ( button == last ) + next = first + else + next = buttons[i + 1] + + button.SetNavUp( prev ) + button.SetNavDown( next ) + + //printt( "SetNavUP for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( prev ) ) + //printt( "SetNavDown for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( next ) ) + } +} + +void function SetNavLeftRight( array<var> buttons, var wrap = true ) +{ + Assert( buttons.len() > 0 ) + + var first = buttons[0] + var last = buttons[buttons.len() - 1] + var prev + var next + var button + + for ( int i = 0; i < buttons.len(); i++ ) + { + button = buttons[i] + + if ( button == first ) + prev = last + else + prev = buttons[i - 1] + + if ( button == last ) + next = first + else + next = buttons[i + 1] + + button.SetNavLeft( prev ) + button.SetNavRight( next ) + + //printt( "SetNavUP for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( prev ) ) + //printt( "SetNavDown for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( next ) ) + } +} + +void function UICodeCallback_EntitlementsChanged() +{ + if ( uiGlobal.activeMenu == null ) + return + + if ( uiGlobal.menuData[ uiGlobal.activeMenu ].entitlementsChangedFunc != null ) + thread uiGlobal.menuData[ uiGlobal.activeMenu ].entitlementsChangedFunc() +} + +#if PC_PROG +void function QuitGame() +{ + ClientCommand( "quit" ) +} +#endif + +void function UICodeCallback_StoreTransactionCompleted() +{ + // this callback is only supported and needed on PS4 currently +#if PS4_PROG + if ( InStoreMenu() ) + OnOpenDLCStore() +#endif +} + +void function UICodeCallback_GamePurchased() +{ + // this callback is only supported and needed on PC currently +#if PC_PROG + DialogData dialogData + dialogData.header = "#PURCHASE_GAME_COMPLETE" + dialogData.message = "#PURCHASE_GAME_RESTART" + AddDialogButton( dialogData, "#QUIT", QuitGame ) + + OpenDialog( dialogData ) +#endif +} + +bool function IsTrialPeriodActive() +{ + return GetConVarBool( "trialPeriodIsActive" ) +} + +void function LaunchGamePurchaseOrDLCStore( array<string> menuNames = [ "StoreMenu" ] ) +{ + if ( Script_IsRunningTrialVersion() ) + { + LaunchGamePurchase() + } + else + { + void functionref() preOpenFunc = null + + foreach ( menuName in menuNames ) + { + // Special case because this menu needs a few properties set before opening + if ( menuName == "StoreMenu_WeaponSkins" ) + { + preOpenFunc = DefaultToDLC11WeaponWarpaintBundle + break + } + } + + OpenStoreMenu( menuNames, preOpenFunc ) + } +} + +void function UICodeCallback_PartyUpdated() +{ + if ( AmIPartyLeader() ) + { + string activeSearchingPlaylist = GetActiveSearchingPlaylist() + if ( activeSearchingPlaylist != "" && !CanPlaylistFitMyParty( activeSearchingPlaylist ) ) + { + CancelMatchSearch() + + DialogData dialogData + dialogData.header = "#MATCHMAKING_CANCELED" + dialogData.message = "#MATCHMAKING_CANCELED_REASON_PARTY_SIZE" + AddDialogButton( dialogData, "#OK" ) + + OpenDialog( dialogData ) + } + } +} + + +void function HACK_DelayedSetFocus_BecauseWhy( var item ) +{ + wait 0.1 + if ( IsValid( item ) ) + Hud_SetFocused( item ) +} + +void function ClassicMusic_OnChange( var button ) +{ + bool isEnabled = GetConVarBool( "sound_classic_music" ) + + if ( IsFullyConnected() && IsMultiplayer() && GetUIPlayer() ) + { + if ( IsItemLocked( GetUIPlayer(), "classic_music" ) ) + SetConVarBool( "sound_classic_music", false ) + + if ( IsLobby() ) + thread RunClientScript( "OnSoundClassicMusicChanged" ) + } +} + +bool function IsClassicMusicAvailable() +{ + bool classicMusicAvailable = false + if ( IsFullyConnected() && IsMultiplayer() && GetUIPlayer() ) + classicMusicAvailable = !IsItemLocked( GetUIPlayer(), "classic_music" ) + + return classicMusicAvailable +} + +void function UICodeCallback_KeyBindOverwritten( string key, string oldbinding, string newbinding ) +{ + DialogData dialogData + dialogData.header = Localize( "#MENU_KEYBIND_WAS_BEING_USED", key ) + dialogData.message = Localize( "#MENU_KEYBIND_WAS_BEING_USED_SUB", key, Localize( oldbinding ) ) + + AddDialogButton( dialogData, "#OK" ) + + OpenDialog( dialogData ) +} 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 00000000..89b7f719 --- /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 ) +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/chatroom.nut b/Northstar.Client/mod/scripts/vscripts/ui/chatroom.nut new file mode 100644 index 00000000..4e98ee8a --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/chatroom.nut @@ -0,0 +1,902 @@ +untyped + +global function Chatroom_GlobalInit +global function InitChatroom +global function UpdateChatroomUI +global function UICodeCallback_ShowUserInfo +global function UICodeCallback_RemoteMatchInfoUpdated +global function UICodeCallback_SetChatroomMode +global function UpdateOpenInvites +global function HideOpenInvite +global function ShowOpenInvite +global function FillInUserInfoPanel +global function UpdateChatroomThread +global function IsVoiceChatPushToTalk + +global function bsupdate + +global const LOBBY_MATERIAL_OWNER = $"rui/menu/common/lobby_icon_owner" +global const LOBBY_MATERIAL_ADMIN = $"rui/menu/common/lobby_icon_admin" + +struct RemoteMatchPlayerInfoRow +{ + var playerPanel + var name + var score + var kills + var deaths +} + +struct RemoteMatchInfoPanel +{ + var panel + var PlaylistName + var MapName + var ModeName + var TimeLeft + var ScoreLimit + var Team1Score + var Team2Score + array<RemoteMatchPlayerInfoRow> team1Players + array<RemoteMatchPlayerInfoRow> team2Players +} + +struct OpenInviteUI +{ + var openInviteJoinButton + var openInvitePanel + var openInviteMessage + var openInviteCountdownText + array openInvitePlayerSlots + array openInvitePlaylistSlots +} + +global struct UserInfoPanel +{ + var Panel + var Name + var Kills + var Wins + var Losses + var Deaths + var XP + var callsignCard + array communityLabels + array communityNames +} + +struct ChatroomWidget +{ + var chatroomPanel + var chatroomWidget + var chatroomTextChat + + var chatroomBackground + var chatroomDivider + var chatroomHappyHour + var chatroomMode + + UserInfoPanel userInfoPanel + + RemoteMatchInfoPanel remoteMatchInfoPanelWidgets + + var communityChatroomModeButton + var chatroomHintText + var happyHourTimeLeft + + OpenInviteUI openInviteUI +} + +struct +{ + string userInfoPanel_hardware = "" + string userInfoPanel_userId = "0" + var communityChatroomMode + bool currentUserIsStreaming = false + array<ChatroomWidget> chatroomUIs + bool hasFocus +} file + +bool function IsVoiceChatPushToTalk() +{ + if ( GetPartySize() > 1 ) + return true + return DoesCurrentCommunitySupportChat() +} + +void function UICodeCallback_SetChatroomMode( string mode ) +{ + file.communityChatroomMode = mode + UpdateChatroomUI() +} + +void function UpdateChatroomUI() +{ + foreach ( chatroomUI in file.chatroomUIs ) + { + if ( file.communityChatroomMode == "chatroom" ) + { + int communityId = GetCurrentCommunityId() + CommunitySettings ornull communitySettings = GetCommunitySettings( communityId ) + + string communityName + if ( communitySettings != null ) + { + expect CommunitySettings( communitySettings ) + communityName = GetCurrentCommunityName() + " [" + communitySettings.clanTag + "]" + } + else + { + communityName = expect string( GetCurrentCommunityName() ) + } + + if ( IsChatroomMuted() ) + SetLabelRuiText( chatroomUI.communityChatroomModeButton, Localize( "#COMMUNITY_CHATROOM_MUTED", communityName ) ) + else + SetLabelRuiText( chatroomUI.communityChatroomModeButton, Localize( "#COMMUNITY_CHATROOM", communityName ) ) + } + else if ( file.communityChatroomMode == "party" ) + { + SetLabelRuiText( chatroomUI.communityChatroomModeButton, Localize( "#COMMUNITY_PARTY", GetPartyLeaderName() ) ) + } + else + { + SetLabelRuiText( chatroomUI.communityChatroomModeButton, Localize( file.communityChatroomMode ) ) + } + + int meritsLeft = GetHappyHourMeritsLeft() + if ( meritsLeft == 0 ) + { + SetLabelRuiText( chatroomUI.happyHourTimeLeft, Localize( "#HAPPYHOUR_NOMERITSLEFT", meritsLeft ) ) + SetNamedRuiText( chatroomUI.happyHourTimeLeft, "happyHourHintString", "" ) + //SetNamedRuiText( chatroomUI.happyHourTimeLeft, "happyHourHintString", Localize( "#HAPPYHOUR_HINT_ACTIVE_01" ) ) + } + else if ( meritsLeft >= 1 ) + { + SetLabelRuiText( chatroomUI.happyHourTimeLeft, Localize( GetHappyHourStatus() ) ) + SetNamedRuiText( chatroomUI.happyHourTimeLeft, "happyHourHintString", Localize( "#HAPPYHOUR_HINT_MERITS", 5 ) ) + } + UICodeCallback_ShowUserInfo( file.userInfoPanel_hardware, file.userInfoPanel_userId ) + } + + UpdateFooterOptions() +} + +bool function FillInCommunityMembership( UserInfoPanel userInfoPanel, CommunityMembership membershipData, int communityIndex ) +{ + if ( userInfoPanel.communityNames.len() <= communityIndex ) + return false; + + string title + title = "[" + membershipData.communityClantag + "] " + Localize( membershipData.communityName ); + + if ( membershipData.membershipLevel == "owner" ) + Hud_SetText( userInfoPanel.communityLabels[communityIndex], "#COMMUNITY_MEMBERSHIP_OWNER" ) + else if ( membershipData.membershipLevel == "admin" ) + Hud_SetText( userInfoPanel.communityLabels[communityIndex], "#COMMUNITY_MEMBERSHIP_ADMIN" ) + else if ( membershipData.membershipLevel == "member" ) + Hud_SetText( userInfoPanel.communityLabels[communityIndex], "#COMMUNITY_MEMBERSHIP_MEMBER" ) + else + Assert( false, "Unknown membership level " + membershipData.membershipLevel + " in FillInCommunityMembership" ) + + Hud_SetText( userInfoPanel.communityNames[communityIndex], title ) + Hud_Show( userInfoPanel.communityLabels[communityIndex] ); + Hud_Show( userInfoPanel.communityNames[communityIndex] ); + + return true +} + +void function FillInUserInfoPanel( UserInfoPanel userInfoPanel, CommunityUserInfo userInfo ) +{ + file.currentUserIsStreaming = userInfo.isLivestreaming + + Hud_SetText( userInfoPanel.Name, userInfo.name ) + string killsText = "" + userInfo.kills + Hud_SetText( userInfoPanel.Kills, killsText ) + string winsText = "" + userInfo.wins + Hud_SetText( userInfoPanel.Wins, winsText ) + string lossesText = "" + userInfo.losses + Hud_SetText( userInfoPanel.Losses, lossesText ) + string deathsText = "" + userInfo.deaths + Hud_SetText( userInfoPanel.Deaths, deathsText ) + string xpText = ShortenNumber( userInfo.xp ) + Hud_EnableKeyBindingIcons( userInfoPanel.XP ) + Hud_SetText( userInfoPanel.XP, Localize( "#CREDITSIGN_N", xpText ) ) + + CallingCard callingCard = CallingCard_GetByIndex( userInfo.callingCardIdx ) + CallsignIcon callsignIcon = CallsignIcon_GetByIndex( userInfo.callSignIdx ) + + var card = userInfoPanel.callsignCard + var rui = Hud_GetRui( userInfoPanel.callsignCard ) + RuiSetImage( rui, "cardImage", callingCard.image ) + RuiSetImage( rui, "iconImage", callsignIcon.image ) + RuiSetInt( rui, "layoutType", callingCard.layoutType ) + RuiSetImage( rui, "cardGenImage", GetGenIcon( userInfo.gen, userInfo.lvl ) ) + RuiSetString( rui, "playerLevel", PlayerXPDisplayGenAndLevel( userInfo.gen, userInfo.lvl ) ) + RuiSetString( rui, "playerName", userInfo.name ) + + array<CommunityMembership> ownerCommunities + array<CommunityMembership> adminCommunities + array<CommunityMembership> memberCommunities + + for ( int i = 0; i < userInfo.numCommunities; i++ ) + { + CommunityMembership ornull communityInfo = GetCommunityUserMembershipInfo( userInfo.hardware, userInfo.uid, i ) + if ( !communityInfo ) + continue; + expect CommunityMembership( communityInfo ) + string membershipLevel = communityInfo.membershipLevel + if ( membershipLevel == "owner" ) + { + ownerCommunities.append( communityInfo ) + } + else if ( membershipLevel == "admin" ) + { + adminCommunities.append( communityInfo ) + } + else if ( membershipLevel == "member" ) + { + memberCommunities.append( communityInfo ) + } + else + { + printt( "Unknown membershipLevel " + membershipLevel ) + Assert( false, "Unknown membershipLevel" ) + } + } + + array<CommunityMembership> allCommunities + for ( int i = 0; i < ownerCommunities.len(); i++ ) + allCommunities.append( ownerCommunities[i] ) + for ( int i = 0; i < adminCommunities.len(); i++ ) + allCommunities.append( adminCommunities[i] ) + for ( int i = 0; i < memberCommunities.len(); i++ ) + allCommunities.append( memberCommunities[i] ) + + int currentCommunityIndex = 0 + for ( ; currentCommunityIndex < allCommunities.len(); currentCommunityIndex++ ) + { + if ( !FillInCommunityMembership( userInfoPanel, allCommunities[currentCommunityIndex], currentCommunityIndex ) ) + break; + } + + for ( ; currentCommunityIndex < userInfoPanel.communityNames.len(); currentCommunityIndex++ ) + { + Hud_Hide( userInfoPanel.communityLabels[currentCommunityIndex] ); + Hud_Hide( userInfoPanel.communityNames[currentCommunityIndex] ); + } + + UpdateFooterOptions() +} + +void function GetUserInfoThread( string hardware, string userId ) +{ + EndSignal( uiGlobal.signalDummy, "StopUserInfoLookups" ) + + printt( "getting userinfo for user " + userId ) + + CommunityUserInfo fakeSettings + fakeSettings.name = Localize( "#COMMUNITY_FETCHING" ) + foreach ( chatroomUI in file.chatroomUIs ) + FillInUserInfoPanel( chatroomUI.userInfoPanel, fakeSettings ) + + while ( true ) + { + printt( "asking for userinfo for " + hardware + "=" + userId ) + + CommunityUserInfo ornull userInfo = GetCommunityUserInfo( hardware, userId ) + if ( !userInfo ) + { + wait 0.05 + } + else + { + printt( "Got user info for user " + userId + " on hardware " + hardware ) + expect CommunityUserInfo( userInfo ) + + printt( "User " + userId + " is in " + userInfo.numCommunities + " communities" ) + + foreach ( chatroomUI in file.chatroomUIs ) + FillInUserInfoPanel( chatroomUI.userInfoPanel, userInfo ) + break + } + } +} + + +void function UICodeCallback_ShowUserInfo( string hardware, string userId ) +{ + Signal( uiGlobal.signalDummy, "StopUserInfoLookups" ) + + // printt( "Showing user info for UID " + userId + " on hardware " + hardware ) + + file.userInfoPanel_userId = userId + file.userInfoPanel_hardware = hardware + + if ( hardware == "" && userId == "0" ) + { + foreach ( chatroomUI in file.chatroomUIs ) + Hud_Hide( chatroomUI.userInfoPanel.Panel ) + + foreach ( chatroomUI in file.chatroomUIs ) + { + // Hud_SetWidth( chatrooUI.chatroomWidget, Hud_GetBaseWidth( chatrooUI.chatroomWidget ) ) + Hud_SetWidth( chatroomUI.chatroomBackground, Hud_GetBaseWidth( chatroomUI.chatroomBackground ) ) + Hud_Show( chatroomUI.chatroomDivider ) + // Hud_SetWidth( chatrooUI.chatroomHeader, Hud_GetBaseWidth( chatrooUI.chatroomHeader ) ) + // Hud_SetWidth( chatrooUI.chatroomMode, Hud_GetBaseWidth( chatrooUI.chatroomBackground ) ) + #if CONSOLE_PROG + Hud_Show( chatroomUI.chatroomHintText ) + #else + Hud_Show( chatroomUI.chatroomTextChat ) + #endif + } + } + else + { + foreach ( chatroomUI in file.chatroomUIs ) + Hud_Show( chatroomUI.userInfoPanel.Panel ) + + foreach ( chatroomUI in file.chatroomUIs ) + { + // Hud_SetWidth( chatroomUI.chatroomWidget, Hud_GetBaseWidth( chatroomUI.chatroomWidget ) - Hud_GetBaseWidth( chatroomUI.userInfoPanel.Panel ) - 24 ) + Hud_SetWidth( chatroomUI.chatroomBackground, Hud_GetBaseWidth( chatroomUI.chatroomBackground ) - Hud_GetBaseWidth( chatroomUI.userInfoPanel.Panel ) - 12 ) + Hud_Hide( chatroomUI.chatroomDivider ) + // Hud_SetWidth( chatroomUI.chatroomHeader, Hud_GetBaseWidth( chatroomUI.chatroomHeader ) - Hud_GetBaseWidth( chatroomUI.userInfoPanel.Panel ) - 12 ) + // Hud_SetWidth( chatroomUI.chatroomMode, Hud_GetBaseWidth( chatroomUI.chatroomBackground ) - Hud_GetBaseWidth( chatroomUI.userInfoPanel.Panel ) - 24 ) + #if CONSOLE_PROG + Hud_Hide( chatroomUI.chatroomHintText ) + #else + Hud_Hide( chatroomUI.chatroomTextChat ) + #endif + } + + thread GetUserInfoThread( hardware, userId ) + } +} + +void function FindRemoteMatchInfoWidgetsInPanel( RemoteMatchInfoPanel infostruct, var panel ) +{ + infostruct.PlaylistName = Hud_GetChild( panel, "PlaylistName" ) + infostruct.MapName = Hud_GetChild( panel, "MapName" ) + infostruct.ModeName = Hud_GetChild( panel, "ModeName" ) + infostruct.TimeLeft = Hud_GetChild( panel, "TimeLeft" ) + infostruct.ScoreLimit = Hud_GetChild( panel, "ScoreLimit" ) + infostruct.Team1Score = Hud_GetChild( panel, "Team1Score" ) + infostruct.Team2Score = Hud_GetChild( panel, "Team2Score" ) + for ( int i = 1; i <= 2; i++ ) + { + array<RemoteMatchPlayerInfoRow> teamPlayers + if ( i == 1 ) + teamPlayers = infostruct.team1Players + else + teamPlayers = infostruct.team2Players + + for ( int j = 1; j <= 8; j++ ) + { + RemoteMatchPlayerInfoRow teamPlayer + string key = "Team" + i + "Player" + j + teamPlayer.playerPanel = Hud_GetChild( panel, key ) + teamPlayer.name = Hud_GetChild( teamPlayer.playerPanel, "Name" ) + teamPlayer.score = Hud_GetChild( teamPlayer.playerPanel, "Score" ) + teamPlayer.kills = Hud_GetChild( teamPlayer.playerPanel, "Kills" ) + teamPlayer.deaths = Hud_GetChild( teamPlayer.playerPanel, "Deaths" ) + teamPlayers.append( teamPlayer ) + } + } +} + +int function RemoteMatchInfoPlayerSort( RemoteClientInfoFromMatchInfo a, RemoteClientInfoFromMatchInfo b ) +{ + return ( b.score - a.score ) +} + +void function FillInRemoteMatchInfoPanel( RemoteMatchInfo info, RemoteMatchInfoPanel panel ) +{ + Hud_Show( panel.panel ) + + Hud_SetText( panel.PlaylistName, GetPlaylistDisplayName( info.playlist ) ) + Hud_SetText( panel.MapName, Localize( "#" + info.map ) ) + + string modeName + + if ( IsFDMode( info.gamemode ) ) + { + modeName = "#GAMEMODE_COOP" + // HACK because fd has multiple gamemodes in playlists + } + else + { + modeName = GAMETYPE_TEXT[ info.gamemode ] + } + + if ( IsFullyConnected() ) + modeName = GetGameModeDisplayName( info.gamemode ) + + Hud_SetText( panel.ModeName, modeName ) + int minsLeft = info.timeLeftSecs / 60 + int secsLeft = info.timeLeftSecs % 60 + string timeLeft = "" + minsLeft + if ( secsLeft < 10 ) + timeLeft = timeLeft + ":0" + secsLeft + else + timeLeft = timeLeft + ":" + secsLeft + Hud_SetText( panel.TimeLeft, timeLeft ) + string scoreLimit = "" + info.maxScore + Hud_SetText( panel.ScoreLimit, scoreLimit ) + string imcScore = "" + info.teamScores[TEAM_IMC] + string milScore = "" + info.teamScores[TEAM_MILITIA] + Hud_SetText( panel.Team1Score, imcScore ) + Hud_SetText( panel.Team2Score, milScore ) + + int team1PlayerCount = 0 + int team2PlayerCount = 0 + + info.clients.sort( RemoteMatchInfoPlayerSort ) + + for ( int i = 0; i < info.clients.len(); i++ ) + { + RemoteMatchPlayerInfoRow teamPlayer + if ( info.clients[i].teamNum == TEAM_IMC ) + { + if ( team1PlayerCount >= panel.team1Players.len() ) + { + printt( "too many team players" ) + continue + } + + teamPlayer = panel.team1Players[team1PlayerCount] + team1PlayerCount++ + } + else if ( info.clients[i].teamNum == TEAM_MILITIA ) + { + if ( team2PlayerCount >= panel.team2Players.len() ) + { + printt( "too many team players" ) + continue + } + + teamPlayer = panel.team2Players[team2PlayerCount] + team2PlayerCount++ + } + else + { + printt( "Unhandled player team " + info.clients[i].teamNum ) + continue + } + string score = "" + info.clients[i].score + string kills = "" + info.clients[i].kills + string deaths = "" + info.clients[i].deaths + + Hud_Hide( teamPlayer.playerPanel ) // not enough room for these + Hud_SetText( teamPlayer.name, info.clients[i].name ) + Hud_SetText( teamPlayer.score, score ) + Hud_SetText( teamPlayer.kills, kills ) + Hud_SetText( teamPlayer.deaths, deaths ) + } + for ( int i = team1PlayerCount; i < panel.team1Players.len(); i++ ) + Hud_Hide( panel.team1Players[i].playerPanel ) + for ( int i = team2PlayerCount; i < panel.team2Players.len(); i++ ) + Hud_Hide( panel.team2Players[i].playerPanel ) + +} + +void function RemoteMatchInfoVisibilityThread() +{ + EndSignal( uiGlobal.signalDummy, "StopRemoteMatchInfoThread" ) + wait 2 + foreach ( chatroomUI in file.chatroomUIs ) + Hud_Hide( chatroomUI.remoteMatchInfoPanelWidgets.panel ) +} + +void function UICodeCallback_RemoteMatchInfoUpdated() +{ + printt( "Remote Match Info Updated!" ) + + RemoteMatchInfo info = GetRemoteMatchInfo() + foreach ( chatroomUI in file.chatroomUIs ) + FillInRemoteMatchInfoPanel( info, chatroomUI.remoteMatchInfoPanelWidgets ) + + Signal( uiGlobal.signalDummy, "StopRemoteMatchInfoThread" ) + thread RemoteMatchInfoVisibilityThread() +} + +void function Chatroom_GlobalInit() +{ + RegisterSignal( "StopRemoteMatchInfoThread" ) +} + +bool function IsSelectedUserStreaming() +{ + if ( !ChatroomHasFocus() ) + return false + return file.currentUserIsStreaming +} + +void function InitChatroom( var parentMenu ) +{ + RegisterSignal( "StopUserInfoLookups" ) + + file.communityChatroomMode = "chatroom" + + var menu = Hud_GetChild( parentMenu, "ChatroomPanel" ) + + ChatroomWidget chatroomUI + file.chatroomUIs.append( chatroomUI ) + + chatroomUI.chatroomPanel = menu + chatroomUI.chatroomWidget = Hud_GetChild( menu, "ChatRoom" ) + chatroomUI.chatroomTextChat = Hud_GetChild( menu, "ChatRoomTextChat" ) + chatroomUI.chatroomBackground = Hud_GetChild( menu, "ChatbarBackground" ) + chatroomUI.chatroomDivider = Hud_GetChild( menu, "ChatroomHeaderBackground" ) + chatroomUI.chatroomHappyHour = Hud_GetChild( menu, "HappyHourTimeLeft" ) + chatroomUI.chatroomMode = Hud_GetChild( menu, "CommunityChatRoomMode" ) + + var remoteMatchInfoPanel = Hud_GetChild( parentMenu, "MatchDetails" ) + chatroomUI.remoteMatchInfoPanelWidgets.panel = remoteMatchInfoPanel + FindRemoteMatchInfoWidgetsInPanel( chatroomUI.remoteMatchInfoPanelWidgets, remoteMatchInfoPanel ) + + chatroomUI.userInfoPanel.Panel = Hud_GetChild( parentMenu, "UserInfo" ) + chatroomUI.userInfoPanel.Name = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "Name" ) + chatroomUI.userInfoPanel.Kills = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "Kills" ) + chatroomUI.userInfoPanel.Wins = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "Wins" ) + chatroomUI.userInfoPanel.Losses = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "Losses" ) + chatroomUI.userInfoPanel.Deaths = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "Deaths" ) + chatroomUI.userInfoPanel.XP = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "XP" ) + chatroomUI.userInfoPanel.callsignCard = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "CallsignCard" ) + + // chatroomUI.userInfoPanel.ViewUserCardButton = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "ViewUserCard" ) + + for ( int i = 0; i < 6; i++ ) + { + if ( !Hud_HasChild( chatroomUI.userInfoPanel.Panel, "Community" + i + "Label" ) ) + break; + var communityLabel = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "Community" + i + "Label" ) + var communityName = Hud_GetChild( chatroomUI.userInfoPanel.Panel, "Community" + i ) + Assert( communityName, "found Community" + i + "Label, but no Community" + i + " in userInfo panel" ); + chatroomUI.userInfoPanel.communityLabels.append( communityLabel ) + chatroomUI.userInfoPanel.communityNames.append( communityName ) + } + + chatroomUI.communityChatroomModeButton = Hud_GetChild( menu, "CommunityChatRoomMode" ) +#if CONSOLE_PROG + chatroomUI.chatroomHintText = Hud_GetChild( menu, "TextChatHintForConsole" ) +#endif + chatroomUI.happyHourTimeLeft = Hud_GetChild( menu, "HappyHourTimeLeft" ) + // Hud_EnableKeyBindingIcons( chatroomUI.communityChatroomModeButton ) + + OpenInviteUI openInviteUI = chatroomUI.openInviteUI + openInviteUI.openInvitePanel = Hud_GetChild( parentMenu, "OpenInvitePanel" ) + openInviteUI.openInviteMessage = Hud_GetChild( openInviteUI.openInvitePanel, "OpenInviteMessage" ) + openInviteUI.openInviteCountdownText = Hud_GetChild( openInviteUI.openInvitePanel, "OpenInviteCountdownText" ) + + var openInviteBackground = Hud_GetChild( openInviteUI.openInvitePanel, "OpenInviteBox" ) + RuiSetColorAlpha( Hud_GetRui( openInviteBackground ), "backgroundColor", <0, 0, 0>, 0.9 ) + + int i = 0; + while ( i < 8 ) + { + int count = i + 1 + var widget = Hud_GetChild( openInviteUI.openInvitePanel, "OpenInvitePlayer" + count ) + if ( !widget ) + break + openInviteUI.openInvitePlayerSlots.append( widget ) + i++ + } + for ( int idx = 0; idx < 9; ++idx ) + { + string widgetName = ("OpenInvitePlaylist" + format( "%02d", idx )) + var widget = Hud_GetChild( openInviteUI.openInvitePanel, widgetName ) + openInviteUI.openInvitePlaylistSlots.append( widget ) + i++ + } + + openInviteUI.openInviteJoinButton = Hud_GetChild( openInviteUI.openInvitePanel, "JoinOpenInviteButton" ) + Hud_EnableKeyBindingIcons( openInviteUI.openInviteJoinButton ) + + AddEventHandlerToButton( openInviteUI.openInvitePanel, "JoinOpenInviteButton", UIE_CLICK, JoinOpenInvite_OnClick ) + AddEventHandlerToButton( openInviteUI.openInvitePanel, "OpenInviteCountdownText", UIE_CLICK, JoinOpenInvite_OnClick ) + AddEventHandlerToButton( openInviteUI.openInvitePanel, "OpenInviteMessageButtonOverlay", UIE_CLICK, JoinOpenInvite_OnClick ) + + AddMenuFooterOption( parentMenu, BUTTON_SHOULDER_LEFT, "#LB_MUTEROOM", "#MUTEROOM", MuteRoom, ChatroomIsNotMuted ) + AddMenuFooterOption( parentMenu, BUTTON_SHOULDER_LEFT, "#LB_UNMUTEROOM", "#UNMUTEROOM", UnmuteRoom, ChatroomIsMuted ) + AddMenuFooterOption( parentMenu, BUTTON_Y, "#Y_BUTTON_OPENINVITE_DESTROY_FOOTER", "#OPENINVITE_DESTROY", LeaveOpenInviteButton, CanDestroyOpenInvite ) + AddMenuFooterOption( parentMenu, BUTTON_Y, "#Y_BUTTON_OPENINVITE_JOIN_FOOTER", "#OPENINVITE_JOIN", JoinOpenInvite, CanJoinOpenInvite ) + AddMenuFooterOption( parentMenu, BUTTON_Y, "#Y_BUTTON_OPENINVITE_LEAVE_FOOTER", "#OPENINVITE_LEAVE", LeaveOpenInviteButton, CanLeaveOpenInvite ) + AddMenuFooterOption( parentMenu, BUTTON_A, "#BUTTON_VIEW_PLAYER_PROFILE", "#MOUSE1_VIEW_PROFILE", null, IsChatroomViewProfileValid ) + AddMenuFooterOption( parentMenu, BUTTON_SHOULDER_RIGHT, "#COMMUNITY_RB_CHATROOM_VIEWSTREAM", "#COMMUNITY_CHATROOM_VIEWSTREAM", null, IsSelectedUserStreaming ) + AddMenuFooterOption( parentMenu, BUTTON_X, "#BUTTON_MUTE", "#MOUSE2_MUTE", null, ChatroomHasFocus ) + + UpdateChatroomUI() + + Hud_AddEventHandler( chatroomUI.chatroomWidget, UIE_LOSE_FOCUS, LostFocus ) + Hud_AddEventHandler( chatroomUI.chatroomWidget, UIE_GET_FOCUS, GotFocus ) +} + +void function bsupdate() +{ + ShowOpenInvite() + + OpenInvite openInvite + openInvite.amILeader = false + openInvite.amIInThis = false + openInvite.numSlots = 5 + openInvite.numClaimedSlots = 1 + + string inviteString = openInvite.amILeader ? "#OPENINVITE_SENDER_PLAYLIST" : "#OPENINVITE_PLAYLIST" + + float endTime = Time() + 10.0 + while ( Time() < endTime ) + { + openInvite.timeLeft = endTime - Time() + + int remainingTime = int( ceil( endTime - Time() ) ) + UpdateOpenInvites( openInvite, inviteString, "scriptacus", "Bounty Hunt", remainingTime ) + + if ( remainingTime == 8 ) + openInvite.numClaimedSlots = 2 + + if ( remainingTime == 6 ) + openInvite.numClaimedSlots = 4 + + //if ( remainingTime == 5 ) + // openInvite.numClaimedSlots = 5 + // + //if ( remainingTime == 4 ) + // openInvite.numClaimedSlots = 6 + + WaitFrame() + } +} + +void function UpdateOpenInvites( OpenInvite openInvite, string message, string param1, string ornull param2, int countdown ) +{ + foreach ( chatroomUI in file.chatroomUIs ) + { + if ( param2 ) + Hud_SetText( chatroomUI.openInviteUI.openInviteMessage, message, param1, param2 ); + else + Hud_SetText( chatroomUI.openInviteUI.openInviteMessage, message, param1 ); + + string countdownText = "" + countdown +// Hud_SetText( chatroomUI.openInviteUI.openInviteCountdownText, "#OPENINVITE_COUNTDOWN", countdownText ) + var countdownRui = Hud_GetRui( chatroomUI.openInviteUI.openInviteCountdownText ) + RuiSetFloat( countdownRui, "timeLeft", openInvite.timeLeft ) + RuiSetFloat( countdownRui, "maxTime", GetConVarFloat( "openinvite_duration_default" ) ) + + bool started = openInvite.timeLeft <= 0 || openInvite.numFreeSlots == 0 + + if ( started ) + { + Hud_Hide( chatroomUI.openInviteUI.openInviteJoinButton ) + } + else if ( CanDestroyOpenInvite() ) + { + Hud_Show( chatroomUI.openInviteUI.openInviteJoinButton ) + if ( IsControllerModeActive() ) + SetNamedRuiText( chatroomUI.openInviteUI.openInviteJoinButton, "buttonText", "#Y_BUTTON_OPENINVITE_DESTROY" ) + else + SetNamedRuiText( chatroomUI.openInviteUI.openInviteJoinButton, "buttonText", "#OPENINVITE_DESTROY" ) + } + else if ( CanLeaveOpenInvite() ) + { + Hud_Show( chatroomUI.openInviteUI.openInviteJoinButton ) + if ( IsControllerModeActive() ) + SetNamedRuiText( chatroomUI.openInviteUI.openInviteJoinButton, "buttonText", "#Y_BUTTON_OPENINVITE_LEAVE" ) + else + SetNamedRuiText( chatroomUI.openInviteUI.openInviteJoinButton, "buttonText", "#OPENINVITE_LEAVE" ) + } + else if ( CanJoinOpenInvite() ) + { + Hud_Show( chatroomUI.openInviteUI.openInviteJoinButton ) + if ( IsControllerModeActive() ) + SetNamedRuiText( chatroomUI.openInviteUI.openInviteJoinButton, "buttonText", "#Y_BUTTON_OPENINVITE_JOIN" ) + else + SetNamedRuiText( chatroomUI.openInviteUI.openInviteJoinButton, "buttonText", "#OPENINVITE_JOIN" ) + } + + string myUID = GetPlayerUID() + int i = 0 + foreach ( player in chatroomUI.openInviteUI.openInvitePlayerSlots ) + { + var rui = Hud_GetRui( player ) + Hud_Show( player ) + + if ( i >= openInvite.numSlots ) + { + //Hud_Hide( player ) + RuiSetBool( rui, "isEnabled", false ) + RuiSetBool( rui, "hasPlayer", false ) + } + else + { + CallsignIcon callsignIcon + bool isMe = false + // asset playerImage + + if ( i < openInvite.numClaimedSlots ) + { + PartyMember member = openInvite.members[i] + isMe = ( member.uid == myUID ) + if ( isMe ) + { + if ( GetUIPlayer() != null ) // this can happen sometimes after a resolution/windowed mode change + callsignIcon = PlayerCallsignIcon_GetActive( GetUIPlayer() ) + else + callsignIcon = CallsignIcon_GetByRef( "gc_icon_happyface" ) + } + else + { + callsignIcon = CallsignIcon_GetByIndex( member.callsignIdx ) + } + } + else + { + callsignIcon = CallsignIcon_GetByRef( "gc_icon_happyface" ) + } + + Hud_Show( player ) + RuiSetBool( rui, "isEnabled", true ) + + RuiSetBool( rui, "hasPlayer", i < openInvite.numClaimedSlots ) + RuiSetBool( rui, "isViewPlayer", isMe ) + RuiSetImage( rui, "playerImage", callsignIcon.image ) + + //if ( i < openInvite.numClaimedSlots ) + // Hud_SetImage( player, $"ui/menu/main_menu/openinvite_occupiedslot" ) + //else + // Hud_SetImage( player, $"ui/menu/main_menu/openinvite_emptyslot" ) + } + i++ + } + + array<string> checklistPlaylists = GetChecklistPlaylistsArray() + + if ( Lobby_IsFDMode() ) + checklistPlaylists = GetFDDifficultyArray() + + array<string> invitePlaylists = split( openInvite.playlistName, "," ) + bool shouldShowCheckboxPlaylists = true + if ( !MixtapeMatchmakingIsEnabled() ) + shouldShowCheckboxPlaylists = false + else if ( invitePlaylists.len() == 0 ) + shouldShowCheckboxPlaylists = false + else if ( (invitePlaylists.len() == 1) && (!checklistPlaylists.contains( invitePlaylists[0] )) ) + shouldShowCheckboxPlaylists = false + + int playlistSlotCount = chatroomUI.openInviteUI.openInvitePlaylistSlots.len() + for( int idx = 0; idx < playlistSlotCount; ++idx ) + { + var slot = chatroomUI.openInviteUI.openInvitePlaylistSlots[idx] + + string thisPlaylistName = idx < checklistPlaylists.len() ? checklistPlaylists[idx] : "" + if ( (thisPlaylistName == "") || !shouldShowCheckboxPlaylists ) + { + Hud_Hide( slot ) + continue + } + + Hud_Show( slot ) + var slotRui = Hud_GetRui( slot ) + asset playlistThumbnail = GetPlaylistThumbnailImage( thisPlaylistName ) + RuiSetImage( slotRui, "checkImage", playlistThumbnail ) + + bool isChecked = invitePlaylists.contains( thisPlaylistName ) + RuiSetBool( slotRui, "isChecked", isChecked ) + + string abbr = GetPlaylistVarOrUseValue( thisPlaylistName, "abbreviation", "" ) + RuiSetString( slotRui, "abbreviation", Localize( abbr ) ) + } + } +} + + +void function HideOpenInvite() +{ + foreach ( chatroomUI in file.chatroomUIs ) + { + Hud_Hide( chatroomUI.openInviteUI.openInvitePanel ) + } +} + +void function ShowOpenInvite() +{ + foreach ( chatroomUI in file.chatroomUIs ) + { + Hud_Show( chatroomUI.openInviteUI.openInvitePanel ) + } +} + + +void function LostFocus( panel ) +{ + Signal( uiGlobal.signalDummy, "StopUserInfoLookups" ) + printt( "Chatroom lost focus" ) + foreach ( chatroomUI in file.chatroomUIs ) + Hud_Hide( chatroomUI.userInfoPanel.Panel ) + file.hasFocus = false + + foreach ( chatroomUI in file.chatroomUIs ) + { + // Hud_SetWidth( chatrooUI.chatroomWidget, Hud_GetBaseWidth( chatrooUI.chatroomWidget ) ) + Hud_SetWidth( chatroomUI.chatroomBackground, Hud_GetBaseWidth( chatroomUI.chatroomBackground ) ) + Hud_Show( chatroomUI.chatroomDivider ) + // Hud_SetWidth( chatrooUI.chatroomMode, Hud_GetBaseWidth( chatrooUI.chatroomBackground ) ) + Hud_Show( chatroomUI.chatroomTextChat ) + } +} + + +void function OnChatroomWidgetGetFocus( var widget ) +{ +} + +void function OnChatroomWidgetLoseFocus( var widget ) +{ +} + +void function GotFocus( panel ) +{ + printt( "Chatroom got focus" ) + file.hasFocus = true + + foreach ( chatroomUI in file.chatroomUIs ) + { + // Hud_SetWidth( chatroomUI.chatroomWidget, Hud_GetBaseWidth( chatroomUI.chatroomWidget ) - Hud_GetBaseWidth( chatroomUI.userInfoPanel.Panel ) - 24 ) + Hud_SetWidth( chatroomUI.chatroomBackground, Hud_GetBaseWidth( chatroomUI.chatroomBackground ) - Hud_GetBaseWidth( chatroomUI.userInfoPanel.Panel ) - 12 ) + Hud_Hide( chatroomUI.chatroomDivider ) + // Hud_SetWidth( chatroomUI.chatroomMode, Hud_GetBaseWidth( chatroomUI.chatroomBackground ) - Hud_GetBaseWidth( chatroomUI.userInfoPanel.Panel ) - 24 ) + Hud_Hide( chatroomUI.chatroomTextChat ) + } +} + +bool function IsChatroomViewProfileValid() +{ + #if PC_PROG + if ( !Origin_IsOverlayAvailable() ) + return false + #endif // PC_PROG + + return ChatroomHasFocus() +} + +bool function ChatroomHasFocus() +{ + return file.hasFocus +} + +bool function ChatroomIsMuted() +{ + if ( IsControllerModeActive() ) + return ChatroomHasFocus() && IsChatroomMuted() + return IsChatroomMuted() +} + +bool function ChatroomIsNotMuted() +{ + if ( IsControllerModeActive() ) + return ChatroomHasFocus() && !IsChatroomMuted() + return !IsChatroomMuted() +} + +void function MuteRoom( var button ) +{ + printt( "muting the room" ) + ClientCommand( "muteroom" ) +} + +void function UnmuteRoom( var button ) +{ + printt( "unmuting the room" ) + ClientCommand( "unmuteroom" ) +} + +void function UpdateChatroomThread() +{ + EndSignal( uiGlobal.signalDummy, "OnCloseLobbyMenu" ) + while ( true ) + { + UpdateChatroomUI() + wait 30 + } +} 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 00000000..89479a76 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_edit_pilot_loadouts.nut @@ -0,0 +1,170 @@ +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 ) + + // 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 ) + 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<var> 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 ) +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ingame.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ingame.nut new file mode 100644 index 00000000..35c9e9ba --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ingame.nut @@ -0,0 +1,702 @@ +//global function InitLobbyStartMenu +global function InitInGameMPMenu +global function InitInGameSPMenu +global function ServerCallback_UI_ObjectiveUpdated +global function ServerCallback_UI_UpdateMissionLog +global function SP_ResetObjectiveStringIndex +global function SCB_SetDoubleXPStatus + +global function SCB_SetCompleteMeritState +global function SCB_SetEvacMeritState +global function SCB_SetMeritCount +global function SCB_SetScoreMeritState +global function SCB_SetWinMeritState +global function SCB_SetWeaponMeritCount +global function SCB_SetTitanMeritCount + +const DATA_TABLE = $"datatable/sp_difficulty.rpak" + +struct +{ + var menuMP + var menuSP + var BtnTrackedChallengeBackground + var BtnTrackedChallengeTitle + array trackedChallengeButtons + var BtnLastCheckpoint + int objectiveStringIndex + bool SP_displayObjectiveOnClose + var settingsHeader + var faqButton + int titanHeaderIndex + var titanHeader + var titanSelectButton + var titanEditButton + + ComboStruct &comboStruct + + array<var> loadoutButtons + array<var> loadoutHeaders +} file + +void function InitInGameMPMenu() +{ + var menu = GetMenu( "InGameMPMenu" ) + file.menuMP = menu + + SP_ResetObjectiveStringIndex() + file.SP_displayObjectiveOnClose = true + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnInGameMPMenu_Open ) + AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnInGameMPMenu_Close ) + + AddUICallback_OnLevelInit( OnInGameLevelInit ) + + ComboStruct comboStruct = ComboButtons_Create( menu ) + + int headerIndex = 0 + int buttonIndex = 0 + var pilotHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_PILOT" ) + file.loadoutHeaders.append( pilotHeader ) + var pilotSelectButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#SELECT" ) + Hud_AddEventHandler( pilotSelectButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "PilotLoadoutsMenu" ) ) ) + file.loadoutButtons.append( pilotSelectButton ) + var pilotEditButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#EDIT" ) + Hud_AddEventHandler( pilotEditButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditPilotLoadoutsMenu" ) ) ) + file.loadoutButtons.append( pilotEditButton ) + + headerIndex++ + buttonIndex = 0 + var titanHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_TITAN" ) + file.titanHeader = titanHeader + file.titanHeaderIndex = headerIndex + file.loadoutHeaders.append( titanHeader ) + var titanSelectButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#SELECT" ) + file.titanSelectButton = titanSelectButton + file.loadoutButtons.append( titanSelectButton ) + Hud_AddEventHandler( titanSelectButton, UIE_CLICK, TitanSelectButtonHandler ) + var titanEditButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#EDIT" ) + Hud_AddEventHandler( titanEditButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditTitanLoadoutsMenu" ) ) ) + file.titanEditButton = titanEditButton + file.loadoutButtons.append( titanEditButton ) + + headerIndex++ + buttonIndex = 0 + var gameHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_GAME" ) + var leaveButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#LEAVE_MATCH" ) + Hud_AddEventHandler( leaveButton, UIE_CLICK, OnLeaveButton_Activate ) + #if DEV + var devButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "Dev" ) + Hud_AddEventHandler( devButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "DevMenu" ) ) ) + #endif + + headerIndex++ + buttonIndex = 0 + var dummyHeader = AddComboButtonHeader( comboStruct, headerIndex, "" ) + var dummyButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "" ) + Hud_SetVisible( dummyHeader, false ) + Hud_SetVisible( dummyButton, false ) + + headerIndex++ + buttonIndex = 0 + file.settingsHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_SETTINGS" ) + var controlsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#CONTROLS" ) + Hud_AddEventHandler( controlsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ControlsMenu" ) ) ) + #if CONSOLE_PROG + var avButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO_VIDEO" ) + Hud_AddEventHandler( avButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioVideoMenu" ) ) ) + #elseif PC_PROG + var videoButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO" ) + Hud_AddEventHandler( videoButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioMenu" ) ) ) + var soundButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#VIDEO" ) + Hud_AddEventHandler( soundButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "VideoMenu" ) ) ) + #endif + + // MOD SETTINGS + var modSettingsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "Mod Settings" ) + Hud_AddEventHandler( modSettingsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ModSettings" ) ) ) + + // Nobody reads the FAQ so we replace it with ModSettings because of the limited combobutton space available + //file.faqButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#KNB_MENU_HEADER" ) + //Hud_AddEventHandler( file.faqButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "KnowledgeBaseMenu" ) ) ) + + //var dataCenterButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#DATA_CENTER" ) + //Hud_AddEventHandler( dataCenterButton, UIE_CLICK, OpenDataCenterDialog ) + + ComboButtons_Finalize( comboStruct ) + + file.comboStruct = comboStruct + + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_CLOSE", "#CLOSE" ) +} + +void function OnInGameMPMenu_Open() +{ + Lobby_SetFDMode( GetCurrentPlaylistVarInt( "ingame_menu_fd_mode", 0 ) == 1 ) + UI_SetPresentationType( ePresentationType.DEFAULT ) + + bool faqIsNew = !GetConVarBool( "menu_faq_viewed" ) || HaveNewPatchNotes() || HaveNewCommunityNotes() + RuiSetBool( Hud_GetRui( file.settingsHeader ), "isNew", faqIsNew ) + //ComboButton_SetNew( file.faqButton, faqIsNew ) + + UpdateLoadoutButtons() + RefreshCreditsAvailable() + thread UpdateCachedNewItems() +} + +void function OnInGameMPMenu_Close() +{ + UI_SetPresentationType( ePresentationType.INACTIVE ) + + if ( IsConnected() && !IsLobby() && IsLevelMultiplayer( GetActiveLevel() ) ) + { + //printt( "OnInGameMPMenu_Close() uiGlobal.updatePilotSpawnLoadout is:", uiGlobal.updatePilotSpawnLoadout ) + //printt( "OnInGameMPMenu_Close() uiGlobal.updateTitanSpawnLoadout is:", uiGlobal.updateTitanSpawnLoadout ) + + string updatePilotSpawnLoadout = uiGlobal.updatePilotSpawnLoadout ? "1" : "0" + string updateTitanSpawnLoadout = uiGlobal.updateTitanSpawnLoadout ? "1" : "0" + + ClientCommand( "InGameMPMenuClosed " + updatePilotSpawnLoadout + " " + updateTitanSpawnLoadout ) + + uiGlobal.updatePilotSpawnLoadout = false + uiGlobal.updateTitanSpawnLoadout = false + + RunClientScript( "RefreshIntroLoadoutDisplay", GetLocalClientPlayer(), uiGlobal.pilotSpawnLoadoutIndex, uiGlobal.titanSpawnLoadoutIndex ) + } +} + +void function UpdateLoadoutButtons() +{ + bool loadoutSelectionEnabled = (GetCurrentPlaylistVarInt( "loadout_selection_enabled", 1 ) == 1) + + SetTitanSelectButtonVisibleState( true ) + + foreach ( button in file.loadoutButtons ) + { + Hud_SetEnabled( button, loadoutSelectionEnabled ) + } + + foreach ( header in file.loadoutHeaders ) + { + if ( loadoutSelectionEnabled ) + Hud_Show( header ) + else + Hud_Hide( header ) + } + + entity player = GetUIPlayer() + + if ( GetAvailableTitanRefs( player ).len() > 1 ) + { + SetComboButtonHeaderTitle( file.menuMP, file.titanHeaderIndex, "#MENU_HEADER_TITAN" ) + ComboButton_SetText( file.titanSelectButton, "#SELECT" ) + Hud_Show( file.titanEditButton ) + } + else if ( GetAvailableTitanRefs( player ).len() == 1 ) + { + TitanLoadoutDef loadout = GetCachedTitanLoadout( uiGlobal.titanSpawnLoadoutIndex ) + + SetComboButtonHeaderTitle( file.menuMP, file.titanHeaderIndex, GetTitanLoadoutName( loadout ) ) + ComboButton_SetText( file.titanSelectButton, "#EDIT" ) + + Hud_Hide( file.titanEditButton ) + ComboButtons_ResetColumnFocus( file.comboStruct ) + } + else + { + SetTitanSelectButtonVisibleState( true ) + } +} + +////////// + +////////// + +void function InitInGameSPMenu() +{ + var menu = GetMenu( "InGameSPMenu" ) + file.menuSP = menu + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenInGameSPMenu ) + AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnCloseInGameSPMenu ) + + ComboStruct comboStruct = ComboButtons_Create( menu ) + + int headerIndex = 0 + int buttonIndex = 0 + + // MISSION Menu + var missionHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_MISSION" ) + var resumeButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#RESUME_GAME_SHORT" ) + Hud_AddEventHandler( resumeButton, UIE_CLICK, OnResumeGame_Activate ) + var lastCheckpointButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#LAST_CHECKPOINT" ) + Hud_AddEventHandler( lastCheckpointButton, UIE_CLICK, OnReloadCheckpoint_Activate ) + file.BtnLastCheckpoint = lastCheckpointButton + var restartButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#RESTART_LEVEL_SHORT" ) + Hud_AddEventHandler( restartButton, UIE_CLICK, OnRestartLevel_Activate ) + + // GAME Menu + // headerIndex++ + // buttonIndex = 0 + // var gameHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_GAME" ) + // var difficultyButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#CHANGE_DIFFICULTY" ) + // Hud_AddEventHandler( difficultyButton, UIE_CLICK, OnChangeDifficulty_Activate ) + // var leaveButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#QUIT" ) + // Hud_AddEventHandler( leaveButton, UIE_CLICK, OnLeaveButton_Activate ) + + // SETTINGS Menu + headerIndex++ + buttonIndex = 0 + var settingsHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_SETTINGS" ) + var controlsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#CONTROLS" ) + Hud_AddEventHandler( controlsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ControlsMenu" ) ) ) + #if CONSOLE_PROG + var avButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO_VIDEO" ) + Hud_AddEventHandler( avButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioVideoMenu" ) ) ) + #elseif PC_PROG + var audioButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO" ) + Hud_AddEventHandler( audioButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioMenu" ) ) ) + var videoButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#VIDEO" ) + Hud_AddEventHandler( videoButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "VideoMenu" ) ) ) + #endif + + // MOD SETTINGS + var modSettingsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "Mod Settings" ) + Hud_AddEventHandler( modSettingsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ModSettings" ) ) ) + + array<var> orderedButtons + + var changeDifficultyBtn = Hud_GetChild( menu, "BtnChangeDifficulty" ) + + AddButtonEventHandler( changeDifficultyBtn, UIE_CLICK, OnChangeDifficulty_Activate ) + Hud_Show( changeDifficultyBtn ) + orderedButtons.append( changeDifficultyBtn ) + + var quitBtn = Hud_GetChild( menu, "BtnQuit" ) + SetButtonRuiText( quitBtn, "#QUIT" ) + AddButtonEventHandler( quitBtn, UIE_CLICK, OnLeaveButton_Activate ) + Hud_Show( quitBtn ) + orderedButtons.append( quitBtn ) + + // DEV button + var devButton = Hud_GetChild( menu, "BtnDev" ) + #if DEV + SetButtonRuiText( devButton, "--- Dev" ) + AddButtonEventHandler( devButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "DevMenu" ) ) ) + Hud_Show( devButton ) + orderedButtons.append( devButton ) + comboStruct.navUpButton = devButton + #else + Hud_Hide( devButton ) + comboStruct.navUpButton = quitBtn + #endif // DEV + + SetNavUpDown( orderedButtons ) + comboStruct.navDownButton = changeDifficultyBtn + + ComboButtons_Finalize( comboStruct ) + + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_CLOSE", "#CLOSE" ) +} + + +void function OnOpenInGameSPMenu() +{ + var collectiblesFoundDesc = Hud_GetChild( file.menuSP, "CollectiblesFoundDesc" ) + var missionLogDesc = Hud_GetChild( file.menuSP, "MissionLogDesc" ) + var changeDifficultyBtn = Hud_GetChild( file.menuSP, "BtnChangeDifficulty" ) + + Hud_SetEnabled( file.BtnLastCheckpoint, HasValidSaveGame() ) + + int currentDifficulty = GetConVarInt( "sp_difficulty" ) + string newDifficultyString + + switch ( currentDifficulty ) + { + case 0: + newDifficultyString = "#CHANGE_DIFFICULTY_EASY" + break + + case 1: + newDifficultyString = "#CHANGE_DIFFICULTY_REGULAR" + break + + case 2: + newDifficultyString = "#CHANGE_DIFFICULTY_HARD" + break + + case 3: + newDifficultyString = "#CHANGE_DIFFICULTY_MASTER" + break + + default: + Assert( 0, "Unknown difficulty " + currentDifficulty ) + break + } + SetButtonRuiText( changeDifficultyBtn, newDifficultyString ) + + string activeLevelName = GetActiveLevel() + if ( activeLevelName != "" ) + { + var dataTable = GetDataTable( $"datatable/sp_levels_data.rpak" ) + + // Make sure this level actually has data to display. + bool levelHasData = false + int numRows = GetDatatableRowCount( dataTable ) + for ( int i = 0; i < numRows; i++ ) + { + string levelName = GetDataTableString( dataTable, i, GetDataTableColumnByName( dataTable, "level" ) ) + if ( activeLevelName == levelName ) + { + levelHasData = true + break + } + } + + if ( levelHasData ) + { + // Mission Log + int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "level" ), activeLevelName ) + string missionLog = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "missionLog" ) ) + + if ( uiGlobal.sp_showAlternateMissionLog ) + { + string alternateMissionLog = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "alternateMissionLog" ) ) + missionLog = alternateMissionLog + } + + Hud_SetText( missionLogDesc, missionLog ) + + // Collectibles + int foundLions = GetCollectiblesFoundForLevel( activeLevelName ) + int maxLions = GetMaxLionsInLevel( activeLevelName ) + Hud_SetText( collectiblesFoundDesc, "#MENU_SP_COLLECTIBLE_DESC", foundLions, maxLions ) + } + else + { + Hud_SetText( missionLogDesc, "#MENU_SP_OBJECTIVES_NO_ENTRY" ) + Hud_SetText( collectiblesFoundDesc, "#MENU_SP_COLLECTIBLE_DESC", 0, 0 ) + } + + // Make sure trial mode doesn't reveal any spoilers! + if ( Script_IsRunningTrialVersion() ) + Hud_SetText( missionLogDesc, "#MENU_SP_OBJECTIVES_NO_ENTRY" ) + } + + SPMenu_UpdateReloadCheckpointButton() +} + + +void function OnCloseInGameSPMenu() +{ + if ( file.SP_displayObjectiveOnClose ) + ClientCommand( "ShowObjective closedSPMenu" ) +} + +void function SPMenu_UpdateReloadCheckpointButton() +{ + if ( level.ui.playerRunningGauntlet ) + ComboButton_SetText( file.BtnLastCheckpoint, "#GAUNTLET_RESTART" ) + else + ComboButton_SetText( file.BtnLastCheckpoint, "#LAST_CHECKPOINT" ) +} + +void function MobilityDifficultyButton_Activate( var button ) +{ + OpenMobilityDifficultyMenu() +} + +void function OnLeaveButton_Activate( var button ) +{ + file.SP_displayObjectiveOnClose = false + LeaveDialog() +} + +void function OnRestartLevel_Activate( var button ) +{ + ShowAreYouSureDialog( "#MENU_RESTART_MISSION_CONFIRM", RestartMission, "#WARNING_LOSE_PROGRESS" ) +} + +void function OnChangeDifficulty_Activate( var button ) +{ + SPDifficultyButton_Click( button ) +} + +void function OnResumeGame_Activate( var button ) +{ + CloseActiveMenu() +} + +void function OnReloadCheckpoint_Activate( var button ) +{ + if ( level.ui.playerRunningGauntlet ) + { + CloseActiveMenu() + ClientCommand( "Gauntlet_PlayerRestartedFromMenu" ) + } + else + { + ShowAreYouSureDialog( "#MENU_RESTART_CHECKPOINT_CONFIRM", ReloadLastCheckpoint, "#EMPTY_STRING" ) + } +} + +void function ShowAreYouSureDialog( string header, void functionref() func, string details ) +{ + DialogData dialogData + dialogData.header = header + dialogData.message = details + + AddDialogButton( dialogData, "#NO" ) + AddDialogButton( dialogData, "#YES", func ) + + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_BACK" ) + + OpenDialog( dialogData ) +} + +void function RestartMission() +{ + file.SP_displayObjectiveOnClose = false + ClientCommand( "RestartMission" ) +} + +void function ReloadLastCheckpoint() +{ + file.SP_displayObjectiveOnClose = false + + printt( "SAVEGAME: Trying to load saveName" ) + if ( HasValidSaveGame() ) + { + printt( "SAVEGAME: Trying to load checkpoint from menu_ingame" ) + SaveGame_LoadWithStartPointFallback() + return + } + + ClientCommand( "RestartFromLevelTransition" ) +} + +void function SP_ResetObjectiveStringIndex() +{ + file.objectiveStringIndex = -1 +} + +void function ServerCallback_UI_ObjectiveUpdated( int stringIndex ) +{ + file.objectiveStringIndex = stringIndex +} + +void function ServerCallback_UI_UpdateMissionLog( bool showAltLog ) +{ + uiGlobal.sp_showAlternateMissionLog = showAltLog +} + +void function SPDifficultyButton_Click( var button ) +{ + DialogData dialogData + dialogData.header = "#SP_DIFFICULTY_MISSION_SELECT_TITLE" + + int currentDifficulty = GetConVarInt( "sp_difficulty" ) + dialogData.coloredButton[ currentDifficulty ] <- true + + if ( currentDifficulty == DIFFICULTY_EASY ) + AddDialogButton( dialogData, "#SP_DIFFICULTY_EASY_TITLE", SPPickEasy, "#SP_DIFFICULTY_EASY_DESCRIPTION", true ) + else + AddDialogButton( dialogData, "#SP_DIFFICULTY_EASY_TITLE", SPPickEasy, "#SP_DIFFICULTY_EASY_DESCRIPTION", false ) + + + if ( currentDifficulty == DIFFICULTY_NORMAL ) + AddDialogButton( dialogData, "#SP_DIFFICULTY_NORMAL_TITLE", SPPickNormal, "#SP_DIFFICULTY_NORMAL_DESCRIPTION", true ) + else + AddDialogButton( dialogData, "#SP_DIFFICULTY_NORMAL_TITLE", SPPickNormal, "#SP_DIFFICULTY_NORMAL_DESCRIPTION", false ) + + + if ( currentDifficulty == DIFFICULTY_HARD ) + AddDialogButton( dialogData, "#SP_DIFFICULTY_HARD_TITLE", SPPickHard, "#SP_DIFFICULTY_HARD_DESCRIPTION", true ) + else + AddDialogButton( dialogData, "#SP_DIFFICULTY_HARD_TITLE", SPPickHard, "#SP_DIFFICULTY_HARD_DESCRIPTION", false ) + + + if ( currentDifficulty == DIFFICULTY_MASTER ) + AddDialogButton( dialogData, "#SP_DIFFICULTY_MASTER_TITLE", SPPickMaster, "#SP_DIFFICULTY_MASTER_DESCRIPTION", true ) + else + AddDialogButton( dialogData, "#SP_DIFFICULTY_MASTER_TITLE", SPPickMaster, "#SP_DIFFICULTY_MASTER_DESCRIPTION", false ) + + + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_BACK" ) + AddDialogPCBackButton( dialogData ) + + OpenDialog( dialogData ) +} + +void function SPPickEasy() +{ + RequestSPDifficultyChange( DIFFICULTY_EASY ) + CloseAllMenus() +} + +void function SPPickNormal() +{ + RequestSPDifficultyChange( DIFFICULTY_NORMAL ) + CloseAllMenus() +} + +void function SPPickHard() +{ + RequestSPDifficultyChange( DIFFICULTY_HARD ) + CloseAllMenus() +} + +void function SPPickMaster() +{ + RequestSPDifficultyChange( DIFFICULTY_MASTER ) + CloseAllMenus() +} + +void function RequestSPDifficultyChange( int selectedDifficulty ) +{ + var dataTable = GetDataTable( DATA_TABLE ) + int difficulty = GetDataTableInt( dataTable, selectedDifficulty, GetDataTableColumnByName( dataTable, "index" ) ) + + ClientCommand( "ClientCommand_RequestSPDifficultyChange " + difficulty ) +} + +void function SCB_SetDoubleXPStatus( int status ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + RuiSetInt( Hud_GetRui( doubleXPWidget ), "doubleXPStatus", status ) + + // update this menu too + TTSUpdateDoubleXPStatus( status ) +} + +void function OnInGameLevelInit() +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + RuiSetInt( rui, "doubleXPStatus", 0 ) + RuiSetBool( rui, "isVisible", false ) + + string gameModeScoreHint = expect string( GetCurrentPlaylistVar( "gamemode_score_hint" ) ) + if ( gameModeScoreHint != "" ) + { + RuiSetString( rui, "scoreMeritText", Localize( gameModeScoreHint ) ) + RuiSetInt( rui, "matchScoreMerit", MERIT_STATE_AVAILABLE ) + } + else + { + RuiSetString( rui, "scoreMeritText", "" ) + RuiSetInt( rui, "matchScoreMerit", MERIT_STATE_HIDDEN ) + } + + Hud_SetVisible( doubleXPWidget, !IsPrivateMatch() ) +} +/* +int matchScoreMerit = MERIT_STATE_AVAILABLE +int matchCompleteMerit = MERIT_STATE_AVAILABLE +int matchWinMerit = MERIT_STATE_AVAILABLE +int matchEvacMerit = MERIT_STATE_HIDDEN +int happyHourMerits = MERIT_STATE_HIDDEN + +int meritCount = 0 +*/ + +void function SCB_SetScoreMeritState( int meritState ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + + RuiSetInt( rui, "matchScoreMerit", meritState ) +} + +void function SCB_SetCompleteMeritState( int meritState ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + + RuiSetInt( rui, "matchCompleteMerit", meritState ) +} + +void function SCB_SetWinMeritState( int meritState ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + + RuiSetInt( rui, "matchWinMerit", meritState ) +} + +void function SCB_SetEvacMeritState( int meritState ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + + RuiSetInt( rui, "matchEvacMerit", meritState ) +} + +void function SCB_SetMeritCount( int meritCount ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + + RuiSetInt( rui, "meritCount", meritCount ) +} + +void function SCB_SetWeaponMeritCount( int meritCount ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + + RuiSetInt( rui, "weaponMeritCount", meritCount ) +} + +void function SCB_SetTitanMeritCount( int meritCount ) +{ + var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" ) + var rui = Hud_GetRui( doubleXPWidget ) + + RuiSetInt( rui, "titanMeritCount", meritCount ) +} + +void function TitanSelectButtonHandler( var button ) +{ + if ( !IsFullyConnected() ) + return + + entity player = GetUIPlayer() + if ( GetAvailableTitanRefs( player ).len() > 1 ) + { + AdvanceMenu( GetMenu( "TitanLoadoutsMenu" ) ) + } + else if ( GetAvailableTitanRefs( player ).len() == 1 ) + { + uiGlobal.updateTitanSpawnLoadout = false + SetEditLoadout( "titan", uiGlobal.titanSpawnLoadoutIndex ) + + RunMenuClientFunction( "SetEditingTitanLoadoutIndex", uiGlobal.titanSpawnLoadoutIndex ) + AdvanceMenu( GetMenu( "EditTitanLoadoutMenu" ) ) + } + else + { + // HIDE + } +} + +void function SetTitanSelectButtonVisibleState( bool state ) +{ + if ( state ) + { + Hud_Show( file.titanHeader ) + Hud_Show( file.titanEditButton ) + Hud_Show( file.titanSelectButton ) + } + else + { + ComboButtons_ResetColumnFocus( file.comboStruct ) + Hud_Hide( file.titanHeader ) + Hud_Hide( file.titanEditButton ) + Hud_Hide( file.titanSelectButton ) + } +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut index 938e0d3f..23dae99d 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut @@ -178,6 +178,8 @@ void function InitLobbyMenu() AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) AddMenuFooterOption( menu, BUTTON_BACK, "#BACK_BUTTON_POSTGAME_REPORT", "#POSTGAME_REPORT", OpenPostGameMenu, IsPostGameMenuValid ) AddMenuFooterOption( menu, BUTTON_TRIGGER_RIGHT, "#R_TRIGGER_CHAT", "", null, IsVoiceChatPushToTalk ) + // Client side progression toggle + AddMenuFooterOption( menu, BUTTON_Y, "#Y_BUTTON_TOGGLE_PROGRESSION", "#TOGGLE_PROGRESSION", ShowToggleProgressionDialog ) InitChatroom( menu ) @@ -226,6 +228,57 @@ void function InitLobbyMenu() RegisterSignal( "LeaveParty" ) } +void function ShowToggleProgressionDialog( var button ) +{ + bool enabled = Progression_GetPreference() + + DialogData dialogData + dialogData.menu = GetMenu( "AnnouncementDialog" ) + dialogData.header = enabled ? "#PROGRESSION_TOGGLE_ENABLED_HEADER" : "#PROGRESSION_TOGGLE_DISABLED_HEADER" + dialogData.message = enabled ? "#PROGRESSION_TOGGLE_ENABLED_BODY" : "#PROGRESSION_TOGGLE_DISABLED_BODY" + dialogData.image = $"ui/menu/common/dialog_announcement_1" + + AddDialogButton( dialogData, "#NO" ) + AddDialogButton( dialogData, "#YES", enabled ? DisableProgression : EnableProgression ) + + OpenDialog( dialogData ) +} + +void function EnableProgression() +{ + Progression_SetPreference( true ) + + // update the cache just in case something changed + UpdateCachedLoadouts_Delayed() + + DialogData dialogData + dialogData.menu = GetMenu( "AnnouncementDialog" ) + dialogData.header = "#PROGRESSION_ENABLED_HEADER" + dialogData.message = "#PROGRESSION_ENABLED_BODY" + dialogData.image = $"ui/menu/common/dialog_announcement_1" + + AddDialogButton( dialogData, "#OK" ) + + EmitUISound( "UI_Menu_Item_Purchased_Stinger" ) + + OpenDialog( dialogData ) +} + +void function DisableProgression() +{ + Progression_SetPreference( false ) + + DialogData dialogData + dialogData.menu = GetMenu( "AnnouncementDialog" ) + dialogData.header = "#PROGRESSION_DISABLED_HEADER" + dialogData.message = "#PROGRESSION_DISABLED_BODY" + dialogData.image = $"ui/menu/common/dialog_announcement_1" + + AddDialogButton( dialogData, "#OK" ) + + OpenDialog( dialogData ) +} + void function SetupComboButtonTest( var menu ) { ComboStruct comboStruct = ComboButtons_Create( menu ) @@ -235,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 ) @@ -352,8 +382,9 @@ void function SetupComboButtonTest( var menu ) var soundButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#VIDEO" ) Hud_AddEventHandler( soundButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "VideoMenu" ) ) ) #endif - file.faqButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#KNB_MENU_HEADER" ) - Hud_AddEventHandler( file.faqButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "KnowledgeBaseMenu" ) ) ) + // MOD SETTINGS + var modSettingsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MOD_SETTINGS" ) + Hud_AddEventHandler( modSettingsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ModSettings" ) ) ) comboStruct.navUpButtonDisabled = true comboStruct.navDownButton = file.genUpButton @@ -372,8 +403,6 @@ void function StartPrivateMatch( var button ) return ClientCommand( "StartPrivateMatchSearch" ) - NSSetLoading(true) - NSUpdateListenServer() } void function DoRoomInviteIfAllowed( var button ) @@ -637,9 +666,9 @@ void function OnLobbyMenu_Open() ComboButton_SetNew( file.factionButton, anyNewFactions ) } - bool faqIsNew = !GetConVarBool( "menu_faq_viewed" ) || HaveNewPatchNotes() || HaveNewCommunityNotes() + /*bool faqIsNew = !GetConVarBool( "menu_faq_viewed" ) || HaveNewPatchNotes() || HaveNewCommunityNotes() RuiSetBool( Hud_GetRui( file.settingsHeader ), "isNew", faqIsNew ) - ComboButton_SetNew( file.faqButton, faqIsNew ) + ComboButton_SetNew( file.faqButton, faqIsNew )*/ TryUnlockSRSCallsign() diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut index 930e472b..8e8071f5 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut @@ -43,7 +43,7 @@ void function InitMapsMenu() { file.menu = GetMenu( "MapsMenu" ) - AddMouseMovementCaptureHandler( file.menu, UpdateMouseDeltaBuffer ) + AddMouseMovementCaptureHandler( Hud_GetChild(file.menu, "MouseMovementCapture"), UpdateMouseDeltaBuffer ) AddMenuEventHandler( file.menu, eUIEvent.MENU_CLOSE, OnCloseMapsMenu ) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_mod_settings.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_mod_settings.nut new file mode 100644 index 00000000..8c13955c --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_mod_settings.nut @@ -0,0 +1,1106 @@ +untyped +global function AddModSettingsMenu +global function ModSettings_AddSetting +global function ModSettings_AddEnumSetting +global function ModSettings_AddSliderSetting +global function ModSettings_AddButton +global function ModSettings_AddModTitle +global function ModSettings_AddModCategory +global function PureModulo + +// Legacy functions for backwards compatability. These will be removed eventually +global function AddConVarSetting +global function AddConVarSettingEnum +global function AddConVarSettingSlider +global function AddModSettingsButton +global function AddModTitle +global function AddModCategory + +const int BUTTONS_PER_PAGE = 15 +const string SETTING_ITEM_TEXT = " " // this is long enough to be the same size as the textentry field + +enum eEmptySpaceType +{ + None, + TopBar, + BottomBar +} + +struct ConVarData { + string displayName + bool isEnumSetting = false + string conVar + string type + + string modName + string catName + bool isCategoryName = false + bool isModName = false + + bool isEmptySpace = false + int spaceType = 0 + + // SLIDER BULLSHIT + bool sliderEnabled = false + float min = 0.0 + float max = 1.0 + float stepSize = 0.05 + bool forceClamp = false + + bool isCustomButton = false + void functionref() onPress + + array<string> values + var customMenu + bool hasCustomMenu = false +} + +struct { + var menu + int scrollOffset = 0 + bool updatingList = false + bool isOpen + + array<ConVarData> conVarList + // if people use searches - i hate them but it'll do : ) + array<ConVarData> filteredList + string filterText = "" + table<int, int> enumRealValues + table<string, bool> setFuncs + array<var> modPanels + array<var> resetModButtons + array<MS_Slider> sliders + string currentMod = "" + string currentCat = "" +} file + +struct { + int deltaX = 0 + int deltaY = 0 +} mouseDeltaBuffer + +void function AddModSettingsMenu() +{ + AddMenu( "ModSettings", $"resource/ui/menus/mod_settings.menu", InitModMenu ) +} + +void function InitModMenu() +{ + file.menu = GetMenu( "ModSettings" ) + // DumpStack(2) + AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + + ///////////////////////////// + // BASE NORTHSTAR SETTINGS // + ///////////////////////////// + + /* + ModSettings_AddModTitle( "^FF000000EXAMPLE" ) + ModSettings_AddModCategory( "I wasted way too much time on this..." ) + ModSettings_AddButton( "This is a custom button you can click on!", void function() : () + { + print( "HELLOOOOOO" ) + } ) + ModSettings_AddEnumSetting( "filter_mods", "Very Huge Enum Example", split( "Never gonna give you up Never gonna let you down Never gonna run around and desert you Never gonna make you cry Never gonna say goodbye Never gonna tell a lie and hurt you", " " ) ) + */ + // Nuke weird rui on filter switch :D + // RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnShowFilter" ) ), "buttonText", "" ) + + file.modPanels = GetElementsByClassname( file.menu, "ModButton" ) + + AddMenuEventHandler( file.menu, eUIEvent.MENU_OPEN, OnModMenuOpened ) + AddMenuEventHandler( file.menu, eUIEvent.MENU_CLOSE, OnModMenuClosed ) + + int len = file.modPanels.len() + for ( int i = 0; i < len; i++ ) + { + + // AddButtonEventHandler( button, UIE_CHANGE, OnSettingButtonPressed ) + // get panel + var panel = file.modPanels[i] + + // reset to default nav + var child = Hud_GetChild( panel, "BtnMod" ) + + + child.SetNavUp( Hud_GetChild( file.modPanels[ int( PureModulo( i - 1, len ) ) ], "BtnMod" ) ) + child.SetNavDown( Hud_GetChild( file.modPanels[ int( PureModulo( i + 1, len ) ) ], "BtnMod" ) ) + + // Enum button nav + child = Hud_GetChild( panel, "EnumSelectButton" ) + Hud_DialogList_AddListItem( child, SETTING_ITEM_TEXT, "main" ) + Hud_DialogList_AddListItem( child, SETTING_ITEM_TEXT, "next" ) + Hud_DialogList_AddListItem( child, SETTING_ITEM_TEXT, "prev" ) + + child.SetNavUp( Hud_GetChild( file.modPanels[ int( PureModulo( i - 1, len ) ) ], "EnumSelectButton" ) ) + child.SetNavDown( Hud_GetChild( file.modPanels[ int( PureModulo( i + 1, len ) ) ], "EnumSelectButton" ) ) + Hud_AddEventHandler( child, UIE_CLICK, UpdateEnumSetting ) + + // reset button nav + + child = Hud_GetChild( panel, "ResetModToDefault" ) + Hud_AddEventHandler( child, UIE_GET_FOCUS, void function( var child ) : (panel) + { + Hud_SetColor( Hud_GetChild( panel, "ResetModImage" ), 0, 0, 0, 255 ) + }) + Hud_AddEventHandler( child, UIE_LOSE_FOCUS, void function( var child ) : (panel) + { + Hud_SetColor( Hud_GetChild( panel, "ResetModImage" ), 180, 180, 180, 180 ) + }) + + child.SetNavUp( Hud_GetChild( file.modPanels[ int( PureModulo( i - 1, len ) ) ], "ResetModToDefault" ) ) + child.SetNavDown( Hud_GetChild( file.modPanels[ int( PureModulo( i + 1, len ) ) ], "ResetModToDefault" ) ) + + Hud_AddEventHandler( child, UIE_CLICK, ResetConVar ) + file.resetModButtons.append(child) + + // text field nav + child = Hud_GetChild( panel, "TextEntrySetting" ) + + Hud_AddEventHandler( child, UIE_LOSE_FOCUS, SendTextPanelChanges ) + + child.SetNavUp( Hud_GetChild( file.modPanels[ int( PureModulo( i - 1, len ) ) ], "TextEntrySetting" ) ) + child.SetNavDown( Hud_GetChild( file.modPanels[ int( PureModulo( i + 1, len ) ) ], "TextEntrySetting" ) ) + + child = Hud_GetChild( panel, "Slider" ) + + child.SetNavUp( Hud_GetChild( file.modPanels[ int( PureModulo( i - 1, len ) ) ], "Slider" ) ) + child.SetNavDown( Hud_GetChild( file.modPanels[ int( PureModulo( i + 1, len ) ) ], "Slider" ) ) + + file.sliders.append( MS_Slider_Setup( child ) ) + + Hud_AddEventHandler( child, UIE_CHANGE, OnSliderChange ) + + child = Hud_GetChild( panel, "OpenCustomMenu" ) + + Hud_AddEventHandler( child, UIE_CLICK, CustomButtonPressed ) + } + + // Hud_AddEventHandler( Hud_GetChild( file.menu, "BtnModsSearch" ), UIE_LOSE_FOCUS, OnFilterTextPanelChanged ) + Hud_AddEventHandler( Hud_GetChild( file.menu, "BtnFiltersClear" ), UIE_CLICK, OnClearButtonPressed ) + // mouse delta + AddMouseMovementCaptureHandler( file.menu, UpdateMouseDeltaBuffer ) + + Hud_AddEventHandler( Hud_GetChild( file.menu, "BtnModsSearch" ), UIE_CHANGE, void function ( var inputField ) : () + { + file.filterText = Hud_GetUTF8Text( inputField ) + OnFiltersChange() + } ) +} + +// "PureModulo" +// Used instead of modulo in some places. +// Why? beacuse PureModulo loops back onto positive numbers instead of going into the negatives. +// DO NOT TOUCH. +// a / b != floor( float( a ) / b ) +// int( float( a ) / b ) != floor( float( a ) / b ) +// Examples: +// -1 % 5 = -1 +// PureModulo( -1, 5 ) = 4 +float function PureModulo( int a, int b ) +{ + return b * ( ( float( a ) / b ) - floor( float( a ) / b ) ) +} + +void function ResetConVar( var button ) +{ + ConVarData conVar = file.filteredList[ int ( Hud_GetScriptID( Hud_GetParent( button ) ) ) + file.scrollOffset ] + + if ( conVar.isCategoryName ) + ShowAreYouSureDialog( "#ARE_YOU_SURE", ResetAllConVarsForModEventHandler( conVar.catName ), "#WILL_RESET_ALL_SETTINGS" ) + else + ShowAreYouSureDialog( "#ARE_YOU_SURE", ResetConVarEventHandler( int ( Hud_GetScriptID( Hud_GetParent( button ) ) ) + file.scrollOffset ), Localize( "#WILL_RESET_SETTING", Localize( conVar.displayName ) ) ) +} + +void function ShowAreYouSureDialog( string header, void functionref() func, string details ) +{ + DialogData dialogData + dialogData.header = header + dialogData.message = details + + AddDialogButton( dialogData, "#NO" ) + AddDialogButton( dialogData, "#YES", func ) + + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_BACK" ) + + OpenDialog( dialogData ) +} + +void functionref() function ResetAllConVarsForModEventHandler( string catName ) +{ + return void function() : ( catName ) + { + for ( int i = 0; i < file.conVarList.len(); i++ ) + { + ConVarData c = file.conVarList[ i ] + if ( c.catName != catName || c.isCategoryName || c.isEmptySpace || c.isCustomButton ) + continue + SetConVarToDefault( c.conVar ) + + int index = file.filteredList.find( c ) + if ( file.filteredList.find( c ) < 0 ) + continue + + if ( min( BUTTONS_PER_PAGE - 1, max( 0, index - file.scrollOffset ) ) == index - file.scrollOffset ) + { + Hud_SetText( Hud_GetChild( file.modPanels[ index - file.scrollOffset ], "TextEntrySetting" ), c.isEnumSetting ? c.values[ GetConVarInt( c.conVar ) ] : GetConVarString( c.conVar ) ) + if( c.sliderEnabled ) + MS_Slider_SetValue( file.sliders[ index - file.scrollOffset ], GetConVarFloat( c.conVar ) ) + } + } + } +} + +void functionref() function ResetConVarEventHandler( int modIndex ) +{ + return void function() : ( modIndex ) + { + ConVarData c = file.filteredList[ modIndex ] + SetConVarToDefault( c.conVar ) + if ( min( BUTTONS_PER_PAGE - 1, max( 0, modIndex - file.scrollOffset ) ) == modIndex - file.scrollOffset ) + { + Hud_SetText( Hud_GetChild( file.modPanels[ modIndex - file.scrollOffset ], "TextEntrySetting" ), c.isEnumSetting ? c.values[ GetConVarInt( c.conVar ) ] : GetConVarString( c.conVar ) ) + if( c.sliderEnabled ) + MS_Slider_SetValue( file.sliders[ modIndex - file.scrollOffset ], GetConVarFloat( c.conVar ) ) + } + } +} + +//////////// +// slider // +//////////// +void function UpdateMouseDeltaBuffer( int x, int y ) +{ + mouseDeltaBuffer.deltaX += x + mouseDeltaBuffer.deltaY += y + + SliderBarUpdate() +} + +void function FlushMouseDeltaBuffer() +{ + mouseDeltaBuffer.deltaX = 0 + mouseDeltaBuffer.deltaY = 0 +} + +void function SliderBarUpdate() +{ + if ( file.filteredList.len() <= 15 ) + { + FlushMouseDeltaBuffer() + return + } + + var sliderButton = Hud_GetChild( file.menu, "BtnModListSlider" ) + var sliderPanel = Hud_GetChild( file.menu, "BtnModListSliderPanel" ) + var movementCapture = Hud_GetChild( file.menu, "MouseMovementCapture" ) + + Hud_SetFocused( sliderButton ) + + float minYPos = -40.0 * ( GetScreenSize()[1] / 1080.0 ) // why the hardcoded positions?!?!?!?!?! + float maxHeight = 615.0 * ( GetScreenSize()[1] / 1080.0 ) + float maxYPos = minYPos - ( maxHeight - Hud_GetHeight( sliderPanel ) ) + float useableSpace = ( maxHeight - Hud_GetHeight( sliderPanel ) ) + + float jump = minYPos - ( useableSpace / ( float( file.filteredList.len() ) ) ) + + int pos = expect int( expect array( Hud_GetPos( sliderButton ) )[1] ) + float newPos = float( pos - mouseDeltaBuffer.deltaY ) + FlushMouseDeltaBuffer() + + if ( newPos < maxYPos ) newPos = maxYPos + if ( newPos > minYPos ) newPos = minYPos + + Hud_SetPos( sliderButton, 2, newPos ) + Hud_SetPos( sliderPanel, 2, newPos ) + Hud_SetPos( movementCapture, 2, newPos ) + + file.scrollOffset = -int( ( ( newPos - minYPos ) / useableSpace ) * ( file.filteredList.len() - BUTTONS_PER_PAGE ) ) + UpdateList() +} + +void function UpdateListSliderHeight() +{ + var sliderButton = Hud_GetChild( file.menu, "BtnModListSlider" ) + var sliderPanel = Hud_GetChild( file.menu, "BtnModListSliderPanel" ) + var movementCapture = Hud_GetChild( file.menu, "MouseMovementCapture" ) + + float mods = float ( file.filteredList.len() ) + + float maxHeight = 615.0 * ( GetScreenSize()[1] / 1080.0 ) // why the hardcoded 320/80??? + float minHeight = 80.0 * ( GetScreenSize()[1] / 1080.0 ) + + float height = maxHeight * ( float( BUTTONS_PER_PAGE ) / mods ) + + if ( height > maxHeight ) height = maxHeight + if ( height < minHeight ) height = minHeight + + Hud_SetHeight( sliderButton, height ) + Hud_SetHeight( sliderPanel, height ) + Hud_SetHeight( movementCapture, height ) +} + +void function UpdateList() +{ + Hud_SetFocused( Hud_GetChild( file.menu, "BtnModsSearch" ) ) + file.updatingList = true + + array<ConVarData> filteredList = [] + + array<string> filters = split( file.filterText, "," ) + array<ConVarData> list = file.conVarList + if ( filters.len() <= 0 ) + filters.append( "" ) + foreach( string f in filters ) + { + string filter = strip( f ) + string lastCatNameInFilter = "" + string lastModNameInFilter = "" + int curCatIndex = 0 + int curModTitleIndex = -1 + for ( int i = 0; i < list.len(); i++ ) + { + ConVarData prev = list[ maxint( 0, i - 1 ) ] + ConVarData c = list[i] + ConVarData next = list[ minint( list.len() - 1, i + 1 ) ] + if ( c.isEmptySpace ) + continue + + string displayName = c.displayName + if ( c.isModName ) + { + displayName = c.modName + curModTitleIndex = i + } + if ( c.isCategoryName ) + { + displayName = c.catName + curCatIndex = i + } + if ( filter == "" || SanitizeDisplayName( Localize( displayName ) ).tolower().find( filter.tolower() ) != null ) + { + if ( c.isModName ) + { + lastModNameInFilter = c.modName + array<ConVarData> modVars = GetAllVarsInMod( list, c.modName ) + if ( filteredList.len() <= 0 && modVars[0].spaceType == eEmptySpaceType.None ) + filteredList.extend( modVars.slice( 1, modVars.len() ) ) + else filteredList.extend( modVars ) + + i += modVars.len() - 1 + } + else if ( c.isCategoryName ) + { + if ( lastModNameInFilter != c.modName ) + { + array<ConVarData> modVars = GetModConVarDatas( list, curModTitleIndex ) + if ( filteredList.len() <= 0 && modVars[0].spaceType == eEmptySpaceType.None ) + filteredList.extend( modVars.slice( 1, modVars.len() ) ) + else filteredList.extend( modVars ) + + lastModNameInFilter = c.modName + } + filteredList.extend( GetAllVarsInCategory( list, c.catName ) ) + i += GetAllVarsInCategory( list, c.catName ).len() - 1 + lastCatNameInFilter = c.catName + } + else + { + if ( lastModNameInFilter != c.modName ) + { + array<ConVarData> modVars = GetModConVarDatas( list, curModTitleIndex ) + if ( filteredList.len() <= 0 && modVars[0].spaceType == eEmptySpaceType.None ) + filteredList.extend( modVars.slice( 1, modVars.len() ) ) + else filteredList.extend( modVars ) + + lastModNameInFilter = c.modName + } + if ( lastCatNameInFilter != c.catName ) + { + filteredList.extend( GetCatConVarDatas( curCatIndex ) ) + lastCatNameInFilter = c.catName + } + filteredList.append( c ) + } + } + } + list = filteredList + filteredList = [] + } + filteredList = list + + + file.filteredList = filteredList + + int j = int( min( file.filteredList.len() + file.scrollOffset, BUTTONS_PER_PAGE ) ) + + for ( int i = 0; i < BUTTONS_PER_PAGE; i++ ) + { + Hud_SetEnabled( file.modPanels[i], i < j ) + Hud_SetVisible( file.modPanels[i], i < j ) + + if ( i < j ) + SetModMenuNameText( file.modPanels[i] ) + } + file.updatingList = false + + if ( file.conVarList.len() <= 0 ) + { + Hud_SetVisible( Hud_GetChild( file.menu, "NoResultLabel" ), true ) + Hud_SetText( Hud_GetChild( file.menu, "NoResultLabel" ), "#NO_MODS" ) + } + else if ( file.filteredList.len() <= 0 ) + { + Hud_SetVisible( Hud_GetChild( file.menu, "NoResultLabel" ), true ) + Hud_SetText( Hud_GetChild( file.menu, "NoResultLabel" ), "#NO_RESULTS" ) + } + else + { + Hud_Hide( Hud_GetChild( file.menu, "NoResultLabel" ) ) + } +} + +array<ConVarData> function GetModConVarDatas( array<ConVarData> arr, int index ) +{ + if ( index <= 1 ) + return [ arr[ index - 1 ], arr[ index ], arr[ index + 1 ] ] + return [ arr[ index - 2 ], arr[ index - 1 ], arr[ index ], arr[ index + 1 ] ] +} + +array<ConVarData> function GetCatConVarDatas( int index ) +{ + if ( file.conVarList[ index - 1 ].spaceType != eEmptySpaceType.None ) + return [ file.conVarList[ index ] ] + return [ file.conVarList[ index - 1 ], file.conVarList[ index ] ] +} + +array<ConVarData> function GetAllVarsInCategory( array<ConVarData> arr, string catName ) +{ + array<ConVarData> vars = [] + for ( int i = 0; i < arr.len(); i++ ) + { + ConVarData c = arr[i] + if ( c.catName == catName ) + { + vars.append( arr[i] ) + } + } + return vars +} + +array<ConVarData> function GetAllVarsInMod( array<ConVarData> arr, string modName ) +{ + array<ConVarData> vars = [] + for ( int i = 0; i < arr.len(); i++ ) + { + ConVarData c = arr[i] + if ( c.modName == modName ) + { + vars.append( arr[i] ) + } + } + return vars +} + +void function SetModMenuNameText( var button ) +{ + int index = int ( Hud_GetScriptID( button ) ) + file.scrollOffset + ConVarData conVar = file.filteredList[ int ( Hud_GetScriptID( button ) ) + file.scrollOffset ] + + var panel = file.modPanels[ int ( Hud_GetScriptID( button ) ) ] + + var label = Hud_GetChild( panel, "BtnMod" ) + var textField = Hud_GetChild( panel, "TextEntrySetting" ) + var enumButton = Hud_GetChild( panel, "EnumSelectButton" ) + var resetButton = Hud_GetChild( panel, "ResetModToDefault" ) + var resetVGUI = Hud_GetChild( panel, "ResetModImage" ) + var bottomLine = Hud_GetChild( panel, "BottomLine" ) + var topLine = Hud_GetChild( panel, "TopLine" ) + var modTitle = Hud_GetChild( panel, "ModTitle" ) + var customMenuButton = Hud_GetChild( panel, "OpenCustomMenu") + var slider = Hud_GetChild( panel, "Slider" ) + Hud_SetVisible( slider, false ) + Hud_SetEnabled( slider, true ) + + + if ( conVar.isEmptySpace ) + { + string s = "" + Hud_SetPos( label, 0, 0 ) + Hud_SetVisible( label, false ) + Hud_SetVisible( textField, false ) + Hud_SetVisible( enumButton, false ) + Hud_SetVisible( resetButton, false ) + Hud_SetVisible( resetVGUI, false ) + Hud_SetVisible( modTitle, false ) + Hud_SetVisible( customMenuButton, false ) + Hud_SetVisible( bottomLine, false ) + Hud_SetVisible( topLine, false ) + switch ( conVar.spaceType ) + { + case eEmptySpaceType.TopBar: + Hud_SetVisible( topLine, true ) + return + + case eEmptySpaceType.BottomBar: + Hud_SetVisible( bottomLine, true ) + return + + case eEmptySpaceType.None: + return + } + } + + Hud_SetVisible( textField, !conVar.isCategoryName ) + Hud_SetVisible( bottomLine, conVar.isCategoryName || conVar.spaceType == eEmptySpaceType.BottomBar ) + Hud_SetVisible( topLine, false ) + Hud_SetVisible( enumButton, !conVar.isCategoryName && conVar.isEnumSetting ) + Hud_SetVisible( modTitle, conVar.isModName ) + Hud_SetVisible( customMenuButton, false ) + float scaleX = GetScreenSize()[1] / 1080.0 + float scaleY = GetScreenSize()[1] / 1080.0 + if ( conVar.sliderEnabled ) + { + Hud_SetSize( slider, int( 320 * scaleX ), int( 45 * scaleY ) ) + MS_Slider s = file.sliders[ int ( Hud_GetScriptID( button ) ) ] + MS_Slider_SetMin( s, conVar.min ) + MS_Slider_SetMax( s, conVar.max ) + MS_Slider_SetStepSize( s, conVar.stepSize ) + MS_Slider_SetValue( s, GetConVarFloat( conVar.conVar ) ) + } + else Hud_SetSize( slider, 0, int( 45 * scaleY ) ) + if ( conVar.isCustomButton ) + { + Hud_SetVisible( label, false ) + Hud_SetVisible( textField, false ) + Hud_SetVisible( enumButton, false ) + Hud_SetVisible( resetButton, false ) + Hud_SetVisible( modTitle, false ) + Hud_SetVisible( resetVGUI, false ) + Hud_SetVisible( customMenuButton, true ) + Hud_SetText( customMenuButton, conVar.displayName ) + } + else if ( conVar.isModName ) + { + Hud_SetText( modTitle, conVar.modName ) + Hud_SetPos( label, 0, 0 ) + Hud_SetVisible( label, false ) + Hud_SetVisible( textField, false ) + Hud_SetVisible( enumButton, false ) + Hud_SetVisible( resetButton, false ) + Hud_SetVisible( resetVGUI, false ) + Hud_SetVisible( bottomLine, false ) + Hud_SetVisible( topLine, false ) + } + else if ( conVar.isCategoryName ) + { + Hud_SetText( label, conVar.catName ) + Hud_SetPos( label, 0, 0 ) + Hud_SetSize( label, int( scaleX * ( 1180 - 420 - 85 ) ), int( scaleY * 40 ) ) + Hud_SetVisible( label, true ) + Hud_SetVisible( textField, false ) + Hud_SetVisible( enumButton, false ) + Hud_SetVisible( resetButton, true ) + Hud_SetVisible( resetVGUI, true ) + + Hud_SetSize( resetButton, int( scaleX * 90 ), int( scaleY * 40 ) ) + } + else { + Hud_SetVisible( slider, conVar.sliderEnabled ) + + Hud_SetText( label, conVar.displayName ) + if (conVar.type == "float") + Hud_SetText( textField, string( GetConVarFloat(conVar.conVar) ) ) + else Hud_SetText( textField, conVar.isEnumSetting ? conVar.values[ GetConVarInt( conVar.conVar ) ] : GetConVarString( conVar.conVar ) ) + Hud_SetPos( label, int(scaleX * 25), 0 ) + Hud_SetText( resetButton, "" ) + if (conVar.sliderEnabled) + Hud_SetSize( label, int(scaleX * (375 + 85)), int(scaleY * 40) ) + else Hud_SetSize( label, int(scaleX * (375 + 405)), int(scaleY * 40) ) + if ( conVar.type == "float" ) + Hud_SetText( textField, string( GetConVarFloat( conVar.conVar ) ) ) + else Hud_SetText( textField, conVar.isEnumSetting ? conVar.values[ GetConVarInt( conVar.conVar ) ] : GetConVarString( conVar.conVar ) ) + Hud_SetPos( label, int( scaleX * 25 ), 0 ) + Hud_SetText( resetButton, "" ) + Hud_SetSize( resetButton, int( scaleX * 90 ), int( scaleY * 40 ) ) + if ( conVar.sliderEnabled ) + Hud_SetSize( label, int( scaleX * ( 375 + 85 ) ), int( scaleY * 40 ) ) + else Hud_SetSize( label, int( scaleX * ( 375 + 405 ) ), int( scaleY * 40 ) ) + Hud_SetVisible( label, true ) + Hud_SetVisible( textField, true ) + Hud_SetVisible( resetButton, true ) + Hud_SetVisible( resetVGUI, true ) + } +} + +void function CustomButtonPressed( var button ) +{ + var panel = Hud_GetParent( button ) + ConVarData c = file.filteredList[ int( Hud_GetScriptID( panel ) ) + file.scrollOffset ] + c.onPress() +} + +void function OnScrollDown( var button ) +{ + if ( file.filteredList.len() <= BUTTONS_PER_PAGE ) return + file.scrollOffset += 5 + if ( file.scrollOffset + BUTTONS_PER_PAGE > file.filteredList.len() ) + { + file.scrollOffset = file.filteredList.len() - BUTTONS_PER_PAGE + } + UpdateList() + UpdateListSliderPosition() +} + +void function OnScrollUp( var button ) +{ + file.scrollOffset -= 5 + if ( file.scrollOffset < 0 ) + { + file.scrollOffset = 0 + } + UpdateList() + UpdateListSliderPosition() +} + +void function UpdateListSliderPosition() +{ + var sliderButton = Hud_GetChild( file.menu , "BtnModListSlider" ) + var sliderPanel = Hud_GetChild( file.menu , "BtnModListSliderPanel" ) + var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) + + float mods = float ( file.filteredList.len() ) + + float minYPos = -40.0 * ( GetScreenSize()[1] / 1080.0 ) + float useableSpace = ( 615.0 * ( GetScreenSize()[1] / 1080.0 ) - Hud_GetHeight( sliderPanel ) ) + + float jump = minYPos - ( useableSpace / ( mods - float( BUTTONS_PER_PAGE ) ) * file.scrollOffset ) + + + if ( jump > minYPos ) jump = minYPos + + Hud_SetPos( sliderButton , 2, jump ) + Hud_SetPos( sliderPanel , 2, jump ) + Hud_SetPos( movementCapture , 2, jump ) +} + +void function OnModMenuOpened() +{ + if( !file.isOpen ) + { + file.scrollOffset = 0 + file.filterText = "" + + RegisterButtonPressedCallback( MOUSE_WHEEL_UP , OnScrollUp ) + RegisterButtonPressedCallback( MOUSE_WHEEL_DOWN , OnScrollDown ) + RegisterButtonPressedCallback( MOUSE_LEFT , OnClick ) + + OnFiltersChange() + file.isOpen = true + } +} + +void function OnClick( var button ) +{ + if (file.resetModButtons.contains(GetFocus())) + thread CheckFocus(GetFocus()) + if (GetFocus() == Hud_GetChild(file.menu, "NoResultLabel")) + thread CheckFocus(GetFocus()) +} + +void function CheckFocus( var button ) +{ + wait 0.05 + if (file.resetModButtons.contains(GetFocus())) + { + thread ResetConVar(GetFocus()) + } + if (GetFocus() == Hud_GetChild(file.menu, "NoResultLabel")) + LaunchExternalWebBrowser( "https://northstar.thunderstore.io/", WEBBROWSER_FLAG_FORCEEXTERNAL ) +} + +void function OnFiltersChange() +{ + file.scrollOffset = 0 + + UpdateList() + + UpdateListSliderHeight() +} + +void function OnModMenuClosed() +{ + DeregisterButtonPressedCallback( MOUSE_WHEEL_UP , OnScrollUp ) + DeregisterButtonPressedCallback( MOUSE_WHEEL_DOWN , OnScrollDown ) + DeregisterButtonPressedCallback( MOUSE_LEFT , OnClick ) + + file.scrollOffset = 0 + UpdateListSliderPosition() + file.isOpen = false +} + +void function ModSettings_AddModTitle( string modName, int stackPos = 2 ) +{ + file.currentMod = modName + if ( file.conVarList.len() > 0 ) + { + ConVarData catData + + catData.isEmptySpace = true + catData.modName = file.currentMod + + file.conVarList.append( catData ) + } + ConVarData topBar + topBar.isEmptySpace = true + topBar.modName = modName + topBar.spaceType = eEmptySpaceType.TopBar + + + ConVarData modData + + modData.modName = modName + modData.displayName = modName + modData.isModName = true + + + ConVarData botBar + botBar.isEmptySpace = true + botBar.modName = modName + botBar.spaceType = eEmptySpaceType.BottomBar + file.conVarList.extend( [ topBar, modData, botBar ] ) + file.setFuncs[ expect string( getstackinfos( stackPos )[ "func" ] ) ] <- false +} + +void function AddModTitle( string modName, int stackPos = 2 ) +{ + ModSettings_AddModTitle( modName, stackPos + 1 ) +} + +void function ModSettings_AddModCategory( string catName, int stackPos = 2 ) +{ + if ( !( getstackinfos( stackPos )[ "func" ] in file.setFuncs ) ) + throw getstackinfos( stackPos )[ "src" ] + " #" + getstackinfos( stackPos )[ "line" ] + "\nCannot add a category before a mod title!" + + ConVarData space + space.isEmptySpace = true + space.modName = file.currentMod + space.catName = catName + file.conVarList.append( space ) + + ConVarData catData + + catData.catName = catName + catData.displayName = catName + catData.modName = file.currentMod + catData.isCategoryName = true + + file.conVarList.append( catData ) + + file.currentCat = catName + file.setFuncs[ expect string( getstackinfos( stackPos )[ "func" ] ) ] = true +} + +void function AddModCategory( string catName, int stackPos = 2 ) +{ + ModSettings_AddModCategory( catName, stackPos + 1 ) +} + +void function ModSettings_AddButton( string buttonLabel, void functionref() onPress, int stackPos = 2 ) +{ + if ( !( getstackinfos( stackPos )[ "func" ] in file.setFuncs ) || !file.setFuncs[ expect string( getstackinfos( stackPos )[ "func" ] ) ] ) + throw getstackinfos( stackPos )[ "src" ] + " #" + getstackinfos( stackPos )[ "line" ] + "\nCannot add a button before a category and mod title!" + + ConVarData data + + data.isCustomButton = true + data.displayName = buttonLabel + data.modName = file.currentMod + data.catName = file.currentCat + data.onPress = onPress + + file.conVarList.append( data ) +} + +void function AddModSettingsButton( string buttonLabel, void functionref() onPress, int stackPos = 2 ) +{ + ModSettings_AddButton( buttonLabel, onPress, stackPos + 1 ) +} + +void function ModSettings_AddSetting( string conVar, string displayName, string type = "", int stackPos = 2 ) +{ + if ( !( getstackinfos( stackPos )[ "func" ] in file.setFuncs ) || !file.setFuncs[ expect string( getstackinfos( stackPos )[ "func" ] ) ] ) + throw getstackinfos( stackPos )[ "src" ] + " #" + getstackinfos( stackPos )[ "line" ] + "\nCannot add a setting before a category and mod title!" + ConVarData data + + data.catName = file.currentCat + data.conVar = conVar + data.modName = file.currentMod + data.displayName = displayName + data.type = type + + file.conVarList.append( data ) +} + +void function AddConVarSetting( string conVar, string displayName, string type = "", int stackPos = 2 ) +{ + ModSettings_AddSetting( conVar, displayName, type, stackPos + 1 ) +} + +void function ModSettings_AddSliderSetting( string conVar, string displayName, float min = 0.0, float max = 1.0, float stepSize = 0.1, bool forceClamp = false, int stackPos = 2 ) +{ + if ( !( getstackinfos( stackPos )[ "func" ] in file.setFuncs ) || !file.setFuncs[ expect string( getstackinfos( stackPos )[ "func" ] ) ] ) + throw getstackinfos( stackPos )[ "src" ] + " #" + getstackinfos( stackPos )[ "line" ] + "\nCannot add a setting before a category and mod title!" + ConVarData data + + data.catName = file.currentCat + data.conVar = conVar + data.modName = file.currentMod + data.displayName = displayName + data.type = "float" + data.sliderEnabled = true + data.forceClamp = false + data.min = min + data.max = max + data.stepSize = stepSize + + file.conVarList.append( data ) +} + +void function AddConVarSettingSlider( string conVar, string displayName, float min = 0.0, float max = 1.0, float stepSize = 0.1, bool forceClamp = false, int stackPos = 2 ) +{ + ModSettings_AddSliderSetting( conVar, displayName, min, max, stepSize, forceClamp, stackPos + 1 ) +} + +void function ModSettings_AddEnumSetting( string conVar, string displayName, array<string> values, int stackPos = 2 ) +{ + if ( !( getstackinfos( stackPos )[ "func" ] in file.setFuncs ) || !file.setFuncs[ expect string( getstackinfos( stackPos )[ "func" ] ) ] ) + throw getstackinfos( stackPos )[ "src" ] + " #" + getstackinfos( stackPos )[ "line" ] + "\nCannot add a setting before a category and mod title!" + ConVarData data + + data.catName = file.currentCat + data.modName = file.currentMod + data.conVar = conVar + data.displayName = displayName + data.values = values + data.isEnumSetting = true + data.min = 0 + data.max = values.len() - 1.0 + data.sliderEnabled = values.len() > 2 + data.forceClamp = true + data.stepSize = 1 + + file.conVarList.append( data ) +} + +void function AddConVarSettingEnum( string conVar, string displayName, array<string> values, int stackPos = 2 ) +{ + ModSettings_AddEnumSetting( conVar, displayName, values, stackPos + 1 ) +} + +void function OnSliderChange( var button ) +{ + if ( file.updatingList ) + return + var panel = Hud_GetParent( button ) + ConVarData c = file.filteredList[ int( Hud_GetScriptID( panel ) ) + file.scrollOffset ] + var textPanel = Hud_GetChild( panel, "TextEntrySetting" ) + + if ( c.isEnumSetting ) + { + int val = int( RoundToNearestInt( Hud_SliderControl_GetCurrentValue( button ) ) ) + SetConVarInt( c.conVar, val ) + Hud_SetText( textPanel, ( c.values[ GetConVarInt( c.conVar ) ] ) ) + MS_Slider_SetValue( file.sliders[ int( Hud_GetScriptID( Hud_GetParent( textPanel ) ) ) ], float( val ) ) + + return + } + float val = Hud_SliderControl_GetCurrentValue( button ) + if ( c.forceClamp ) + { + int mod = int( RoundToNearestInt( val % c.stepSize / c.stepSize ) ) + val = ( int( val / c.stepSize ) + mod ) * c.stepSize + } + SetConVarFloat( c.conVar, val ) + MS_Slider_SetValue( file.sliders[ int( Hud_GetScriptID( Hud_GetParent( textPanel ) ) ) ], val ) + + Hud_SetText( textPanel, string( GetConVarFloat( c.conVar ) ) ) +} + +void function SendTextPanelChanges( var textPanel ) +{ + ConVarData c = file.filteredList[ int( Hud_GetScriptID( Hud_GetParent( textPanel ) ) ) + file.scrollOffset ] + if ( c.conVar == "" ) return + // enums don't need to do this + if ( !c.isEnumSetting ) + { + string newSetting = Hud_GetUTF8Text( textPanel ) + + switch ( c.type ) + { + case "int": + try + { + SetConVarInt( c.conVar, newSetting.tointeger() ) + } + catch ( ex ) + { + ThrowInvalidValue( "This setting is an integer, and only accepts whole numbers." ) + Hud_SetText( textPanel, GetConVarString( c.conVar ) ) + } + break + case "bool": + if ( newSetting != "0" && newSetting != "1" ) + { + ThrowInvalidValue( "This setting is a boolean, and only accepts values of 0 or 1." ) + + // set back to previous value : ) + Hud_SetText( textPanel, string( GetConVarBool( c.conVar ) ) ) + + break + } + SetConVarBool( c.conVar, newSetting == "1" ) + break + case "float": + try + { + SetConVarFloat( c.conVar, newSetting.tofloat() ) + } + catch ( ex ) + { + printt( ex ) + ThrowInvalidValue( "This setting is a float, and only accepts a number - we could not parse this!\n\n( Use \".\" for the floating point, not \",\". )" ) + } + if ( c.sliderEnabled ) + { + var panel = Hud_GetParent( textPanel ) + MS_Slider s = file.sliders[ int ( Hud_GetScriptID( panel ) ) ] + + MS_Slider_SetValue( s, GetConVarFloat( c.conVar ) ) + } + break + case "float2": + try + { + array<string> split = split( newSetting, " " ) + if ( split.len() != 2 ) + { + ThrowInvalidValue( "This setting is a float2, and only accepts a pair of numbers - you put in " + split.len() + "!" ) + Hud_SetText( textPanel, GetConVarString( c.conVar ) ) + break + } + vector settingTest = < split[0].tofloat(), split[1].tofloat(), 0 > + + SetConVarString( c.conVar, newSetting ) + } + catch ( ex ) + { + ThrowInvalidValue( "This setting is a float2, and only accepts a pair of numbers - you put something we could not parse!\n\n( Use \".\" for the floating point, not \",\". )" ) + Hud_SetText( textPanel, GetConVarString( c.conVar ) ) + } + break + // idk sometimes it's called Float3 most of the time it's called vector, I am not complaining. + case "vector": + case "float3": + try + { + array<string> split = split( newSetting, " " ) + if ( split.len() != 3 ) + { + ThrowInvalidValue( "This setting is a float3, and only accepts a trio of numbers - you put in " + split.len() + "!" ) + Hud_SetText( textPanel, GetConVarString( c.conVar ) ) + break + } + vector settingTest = < split[0].tofloat(), split[1].tofloat(), 0 > + + SetConVarString( c.conVar, newSetting ) + } + catch ( ex ) + { + ThrowInvalidValue( "This setting is a float3, and only accepts a trio of numbers - you put something we could not parse!\n\n( Use \".\" for the floating point, not \",\". )" ) + Hud_SetText( textPanel, GetConVarString( c.conVar ) ) + } + break + default: + SetConVarString( c.conVar, newSetting ) + break; + } + } + else Hud_SetText( textPanel, Localize( c.values[ GetConVarInt( c.conVar ) ] ) ) +} + +void function ThrowInvalidValue( string desc ) +{ + DialogData dialogData + dialogData.header = "Invalid Value" + dialogData.image = $"ui/menu/common/dialog_error" + dialogData.message = desc + AddDialogButton( dialogData, "#OK" ) + OpenDialog( dialogData ) +} + +void function UpdateEnumSetting( var button ) +{ + int scriptId = int( Hud_GetScriptID( Hud_GetParent( button ) ) ) + ConVarData c = file.filteredList[ scriptId + file.scrollOffset ] + + var panel = file.modPanels[ scriptId ] + + var textPanel = Hud_GetChild( panel, "TextEntrySetting" ) + + string selectionVal = Hud_GetDialogListSelectionValue( button ) + + if ( selectionVal == "main" ) + return + + int enumVal = GetConVarInt( c.conVar ) + if ( selectionVal == "next" ) // enum val += 1 + enumVal = ( enumVal + 1 ) % c.values.len() + else // enum val -= 1 + { + enumVal-- + if ( enumVal == -1 ) + enumVal = c.values.len() - 1 + } + + SetConVarInt( c.conVar, enumVal ) + Hud_SetText( textPanel, c.values[ enumVal ] ) + + Hud_SetDialogListSelectionValue( button, "main" ) +} + +void function OnClearButtonPressed( var button ) +{ + file.filterText = "" + Hud_SetText( Hud_GetChild( file.menu, "BtnModsSearch" ), "" ) + + OnFiltersChange() +} + +string function SanitizeDisplayName( string displayName ) +{ + array<string> parts = split( displayName, "^" ) + string result = "" + if ( parts.len() == 1 ) + return parts[0] + foreach ( string p in parts ) + { + if ( p == "" ) + { + result += "^" + continue + } + int i = 0 + for ( i = 0; i < 8 && i < p.len(); i++ ) + { + var c = p[i] + if ( ( c < 'a' || c > 'f' ) && ( c < 'A' || c > 'F' ) && ( c < '0' || c > '9' ) ) + break + } + if ( i == 0 ) + result += p + else result += p.slice( i, p.len() ) + } + return result +} 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 32a3c8f5..605af383 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() @@ -52,16 +52,11 @@ void function UpdateVisibleModes() Hud_SetEnabled( buttons[ i ], true ) Hud_SetVisible( buttons[ i ], true ) - if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) || modesArray[ modeIndex ] == "aitdm" ) + // This check is refactored in the new mode menu so we can just ignore this atrocity + 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 ) } } @@ -89,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 ) ) @@ -113,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_ns_connect_password.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut index b5a2e9b6..b89e665b 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut @@ -54,5 +54,8 @@ void function OnConnectWithPasswordMenuOpened() void function ConnectWithPassword( var button ) { if ( GetTopNonDialogMenu() == file.menu ) - thread ThreadedAuthAndConnectToServer( Hud_GetUTF8Text( Hud_GetChild( file.menu, "EnterPasswordBox" ) ) ) + { + TriggerConnectToServerCallbacks() + thread ThreadedAuthAndConnectToServer( Hud_GetUTF8Text( Hud_GetChild( file.menu, "EnterPasswordBox" ) ), true ) + } }
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_moddownload.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_moddownload.nut new file mode 100644 index 00000000..4968714c --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_moddownload.nut @@ -0,0 +1,152 @@ +global function DownloadMod +global function DisplayModDownloadErrorDialog +global function FetchVerifiedModsManifesto + +global enum eModInstallStatus +{ + MANIFESTO_FETCHING, + DOWNLOADING, + CHECKSUMING, + EXTRACTING, + DONE, + FAILED, + FAILED_READING_ARCHIVE, + FAILED_WRITING_TO_DISK, + MOD_FETCHING_FAILED, + MOD_CORRUPTED, + NO_DISK_SPACE_AVAILABLE, + NOT_FOUND +} + +const int MB = 1024*1000; + + +void function FetchVerifiedModsManifesto() +{ + print("Start fetching verified mods manifesto from the Internet") + + // Fetching UI + DialogData dialogData + dialogData.header = Localize( "#MANIFESTO_FETCHING_TITLE" ) + dialogData.message = Localize( "#MANIFESTO_FETCHING_TEXT" ) + dialogData.showSpinner = true; + + // Prevent user from closing dialog + dialogData.forceChoice = true; + OpenDialog( dialogData ) + + // Do the actual fetching + NSFetchVerifiedModsManifesto() + + ModInstallState state = NSGetModInstallState() + while ( state.status == eModInstallStatus.MANIFESTO_FETCHING ) + { + state = NSGetModInstallState() + WaitFrame() + } + + // Close dialog when manifesto has been received + CloseActiveMenu() +} + +bool function DownloadMod( RequiredModInfo mod ) +{ + // Downloading mod UI + DialogData dialogData + dialogData.header = Localize( "#DOWNLOADING_MOD_TITLE" ) + dialogData.message = Localize( "#DOWNLOADING_MOD_TEXT", mod.name, mod.version ) + dialogData.showSpinner = true; + + // Prevent user from closing dialog + dialogData.forceChoice = true; + OpenDialog( dialogData ) + + // Save reference to UI elements, to update their content + var menu = GetMenu( "Dialog" ) + var header = Hud_GetChild( menu, "DialogHeader" ) + var body = GetSingleElementByClassname( menu, "DialogMessageClass" ) + + // Start actual mod downloading + NSDownloadMod( mod.name, mod.version ) + + ModInstallState state = NSGetModInstallState() + while ( state.status < eModInstallStatus.DONE ) + { + state = NSGetModInstallState() + UpdateModDownloadDialog( mod, state, menu, header, body ) + WaitFrame() + } + + printt( "Mod status:", state.status ) + + // Close loading dialog + CloseActiveMenu() + + return state.status == eModInstallStatus.DONE +} + +void function UpdateModDownloadDialog( RequiredModInfo mod, ModInstallState state, var menu, var header, var body ) +{ + switch ( state.status ) + { + case eModInstallStatus.MANIFESTO_FETCHING: + Hud_SetText( header, Localize( "#MANIFESTO_FETCHING_TITLE" ) ) + Hud_SetText( body, Localize( "#MANIFESTO_FETCHING_TEXT" ) ) + break + case eModInstallStatus.DOWNLOADING: + Hud_SetText( header, Localize( "#DOWNLOADING_MOD_TITLE_W_PROGRESS", string( state.ratio ) ) ) + Hud_SetText( body, Localize( "#DOWNLOADING_MOD_TEXT_W_PROGRESS", mod.name, mod.version, floor( state.progress / MB ), floor( state.total / MB ) ) ) + break + case eModInstallStatus.CHECKSUMING: + Hud_SetText( header, Localize( "#CHECKSUMING_TITLE" ) ) + Hud_SetText( body, Localize( "#CHECKSUMING_TEXT", mod.name, mod.version ) ) + break + case eModInstallStatus.EXTRACTING: + Hud_SetText( header, Localize( "#EXTRACTING_MOD_TITLE", string( state.ratio ) ) ) + Hud_SetText( body, Localize( "#EXTRACTING_MOD_TEXT", mod.name, mod.version, floor( state.progress / MB ), floor( state.total / MB ) ) ) + break + default: + break + } +} + +void function DisplayModDownloadErrorDialog( string modName ) +{ + ModInstallState state = NSGetModInstallState() + + DialogData dialogData + dialogData.header = Localize( "#FAILED_DOWNLOADING", modName ) + dialogData.image = $"ui/menu/common/dialog_error" + + switch ( state.status ) + { + case eModInstallStatus.FAILED_READING_ARCHIVE: + dialogData.message = Localize( "#FAILED_READING_ARCHIVE" ) + break + case eModInstallStatus.FAILED_WRITING_TO_DISK: + dialogData.message = Localize( "#FAILED_WRITING_TO_DISK" ) + break + case eModInstallStatus.MOD_FETCHING_FAILED: + dialogData.message = Localize( "#MOD_FETCHING_FAILED" ) + break + case eModInstallStatus.MOD_CORRUPTED: + dialogData.message = Localize( "#MOD_CORRUPTED" ) + break + case eModInstallStatus.NO_DISK_SPACE_AVAILABLE: + dialogData.message = Localize( "#NO_DISK_SPACE_AVAILABLE" ) + break + case eModInstallStatus.NOT_FOUND: + dialogData.message = Localize( "#NOT_FOUND" ) + break + case eModInstallStatus.FAILED: + default: + dialogData.message = Localize( "#MOD_FETCHING_FAILED_GENERAL" ) + break + } + + AddDialogButton( dialogData, "#DISMISS" ) + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_DISMISS_RUI" ) + + OpenDialog( dialogData ) +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut index 15d78025..3f643aa3 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut @@ -5,18 +5,26 @@ global function AddNorthstarModMenu_MainMenuFooter global function ReloadMods -const int BUTTONS_PER_PAGE = 17 - +struct modData { + string name = "" + string version = "" + string link = "" + int loadPriority = 0 + bool enabled = false + array<string> conVars = [] +} -struct modStruct { - int modIndex - string modName +struct panelContent { + modData& mod + bool isHeader = false } enum filterShow { ALL = 0, ONLY_ENABLED = 1, ONLY_DISABLED = 2 + ONLY_NOT_REQUIRED = 3, + ONLY_REQUIRED = 4 } struct { @@ -25,16 +33,19 @@ struct { } mouseDeltaBuffer struct { - bool shouldReloadModsOnEnd - string currentMod - var currentButton - int scrollOffset = 0 - - array<modStruct> modsArrayFiltered - + array<panelContent> mods var menu + array<var> panels + int scrollOffset = 0 + array<string> enabledMods + var currentButton + string searchTerm + modData& lastMod } file +const int PANELS_LEN = 15 +const string[3] CORE_MODS = ["Northstar.Client", "Northstar.Coop", "Northstar.CustomServers"] // Shows a warning if you try to disable these + void function AddNorthstarModMenu() { AddMenu( "ModListMenu", $"resource/ui/menus/modlist.menu", InitModMenu ) @@ -54,11 +65,46 @@ void function AdvanceToModListMenu( var button ) void function InitModMenu() { file.menu = GetMenu( "ModListMenu" ) - - AddMouseMovementCaptureHandler( file.menu, UpdateMouseDeltaBuffer ) + file.panels = GetElementsByClassname( file.menu, "ModSelectorPanel" ) + + var rui = Hud_GetRui( Hud_GetChild( file.menu, "WarningLegendImage" ) ) + RuiSetImage( rui, "basicImage", $"ui/menu/common/dialog_error" ) + RuiSetFloat( Hud_GetRui( Hud_GetChild( file.menu, "ModEnabledBar" ) ), "basicImageAlpha", 0.8 ) + + // Mod buttons + foreach ( var panel in file.panels ) + { + var button = Hud_GetChild( panel, "BtnMod" ) + AddButtonEventHandler( button, UIE_GET_FOCUS, OnModButtonFocused ) + AddButtonEventHandler( button, UIE_CLICK, OnModButtonPressed ) + + var rui = Hud_GetRui( Hud_GetChild( panel, "WarningImage" ) ) + RuiSetImage( rui, "basicImage", $"ui/menu/common/dialog_error" ) + } + + AddMouseMovementCaptureHandler( Hud_GetChild(file.menu, "MouseMovementCapture"), UpdateMouseDeltaBuffer ) + + // UI Events AddMenuEventHandler( file.menu, eUIEvent.MENU_OPEN, OnModMenuOpened ) AddMenuEventHandler( file.menu, eUIEvent.MENU_CLOSE, OnModMenuClosed ) + + // up / down buttons + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModListUpArrow" ), UIE_CLICK, OnUpArrowSelected ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModListDownArrow" ), UIE_CLICK, OnDownArrowSelected ) + + // Mod info buttons + AddButtonEventHandler( Hud_GetChild( file.menu, "ModPageButton" ), UIE_CLICK, OnModLinkButtonPressed ) + + // Filter buttons + AddButtonEventHandler( Hud_GetChild( file.menu, "SwtBtnShowFilter"), UIE_CHANGE, OnFiltersChange ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModsSearch"), UIE_CHANGE, OnFiltersChange ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnListReverse"), UIE_CHANGE, OnFiltersChange ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnFiltersClear"), UIE_CLICK, OnBtnFiltersClear_Activate ) + + AddButtonEventHandler( Hud_GetChild( file.menu, "HideCVButton"), UIE_CHANGE, OnHideConVarsChange ) + + // Footers AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) AddMenuFooterOption( file.menu, @@ -74,37 +120,25 @@ void function InitModMenu() "#AUTHENTICATION_AGREEMENT", OnAuthenticationAgreementButtonPressed ) - - foreach ( var button in GetElementsByClassname( file.menu, "ModButton" ) ) - { - AddButtonEventHandler( button, UIE_GET_FOCUS, OnModMenuButtonFocused ) - AddButtonEventHandler( button, UIE_CLICK, OnModMenuButtonPressed ) - } - - AddButtonEventHandler( Hud_GetChild( file.menu, "SwtBtnShowFilter"), UIE_CHANGE, OnFiltersChange ) - AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModsSearch"), UIE_CHANGE, OnFiltersChange ) - - AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModListUpArrow"), UIE_CLICK, OnUpArrowSelected ) - AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModListDownArrow"), UIE_CLICK, OnDownArrowSelected ) - - AddButtonEventHandler( Hud_GetChild( file.menu, "BtnFiltersClear"), UIE_CLICK, OnBtnFiltersClear_Activate ) - + // Nuke weird rui on filter switch RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnShowFilter")), "buttonText", "") + RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "HideCVButton")), "buttonText", "") + RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "BtnListReverse")), "buttonText", "") } +// EVENTS + void function OnModMenuOpened() { - file.shouldReloadModsOnEnd = false - file.scrollOffset = 0 - - RegisterButtonPressedCallback(MOUSE_WHEEL_UP , OnScrollUp) - RegisterButtonPressedCallback(MOUSE_WHEEL_DOWN , OnScrollDown) + file.enabledMods = GetEnabledModsArray() // used to check if mods should be reloaded - Hud_SetText( Hud_GetChild( file.menu, "Title" ), "#MENU_TITLE_MODS" ) + UpdateList() + UpdateListSliderHeight() + UpdateListSliderPosition() - - OnFiltersChange(0) + RegisterButtonPressedCallback(MOUSE_WHEEL_UP , OnScrollUp) + RegisterButtonPressedCallback(MOUSE_WHEEL_DOWN , OnScrollDown) } void function OnModMenuClosed() @@ -115,120 +149,123 @@ void function OnModMenuClosed() DeregisterButtonPressedCallback(MOUSE_WHEEL_DOWN , OnScrollDown) } catch ( ex ) {} - - if ( file.shouldReloadModsOnEnd ) - ReloadMods() -} - -void function OnFiltersChange( var n ) -{ - file.scrollOffset = 0 - - HideAllButtons() - - RefreshModsArray() - - UpdateList() - - UpdateListSliderHeight() -} -void function RefreshModsArray() -{ - string searchTerm = Hud_GetUTF8Text( Hud_GetChild( file.menu, "BtnModsSearch" ) ).tolower() - - file.modsArrayFiltered.clear() - - - bool useSearch = searchTerm != "" - - - array<string> modNames = NSGetModNames() - int modCount = modNames.len() - - foreach ( int index_, mod in modNames ) { - modStruct tempMod - tempMod.modIndex = index_ - tempMod.modName = mod - - int filter = GetConVarInt( "filter_mods" ) - bool enabled = NSIsModEnabled( tempMod.modName ) - - bool containsTerm = tempMod.modName.tolower().find(searchTerm) != null - - if ( filter == filterShow.ALL && (useSearch == true ? containsTerm : true ) ) - { - file.modsArrayFiltered.append( tempMod ) - } - else if ( filter == filterShow.ONLY_ENABLED && enabled && (useSearch == true ? containsTerm : true )) - { - file.modsArrayFiltered.append( tempMod ) - } - else if ( filter == filterShow.ONLY_DISABLED && !enabled && (useSearch == true ? containsTerm : true )) + array<string> current = GetEnabledModsArray() + bool reload + foreach ( string mod in current ) + { + if ( file.enabledMods.find(mod) == -1 ) { - file.modsArrayFiltered.append( tempMod ) + reload = true + break } } + if ( current.len() != file.enabledMods.len() || reload ) // Only reload if we have to + ReloadMods() } -void function HideAllButtons() +void function OnModButtonFocused( var button ) { - array<var> buttons = GetElementsByClassname( file.menu, "ModButton" ) - - // disable all buttons, we'll enable the ones we need later - foreach ( var button in buttons ) + if( int ( Hud_GetScriptID( Hud_GetParent( button ) ) ) > file.mods.len() ) + return + + file.currentButton = button + file.lastMod = file.mods[ int ( Hud_GetScriptID( Hud_GetParent( button ) ) ) + file.scrollOffset - 1 ].mod + string modName = file.lastMod.name + var rui = Hud_GetRui( Hud_GetChild( file.menu, "LabelDetails" ) ) + + RuiSetGameTime( rui, "startTime", -99999.99 ) // make sure it skips the whole animation for showing this + RuiSetString( rui, "headerText", modName ) + RuiSetString( rui, "messageText", FormatModDescription( modName ) ) + + // Add a button to open the link with if required + string link = NSGetModDownloadLinkByModName( modName ) + var linkButton = Hud_GetChild( file.menu, "ModPageButton" ) + if ( link.len() ) { - Hud_SetEnabled( button, false ) - Hud_SetVisible( button, false ) + Hud_SetEnabled( linkButton, true ) + Hud_SetVisible( linkButton, true ) + Hud_SetText( linkButton, link ) } + else + { + Hud_SetEnabled( linkButton, false ) + Hud_SetVisible( linkButton, false ) + } + + SetControlBarColor( modName ) + + bool required = NSIsModRequiredOnClient( modName ) + Hud_SetVisible( Hud_GetChild( file.menu, "WarningLegendLabel" ), required ) + Hud_SetVisible( Hud_GetChild( file.menu, "WarningLegendImage" ), required ) } -void function UpdateList() +void function OnModButtonPressed( var button ) { - array<var> buttons = GetElementsByClassname( file.menu, "ModButton" ) - - - int j = file.modsArrayFiltered.len() > 17 ? 17 : file.modsArrayFiltered.len() - - for ( int i = 0; i < j; i++ ) + string modName = file.mods[ int ( Hud_GetScriptID( Hud_GetParent( button ) ) ) + file.scrollOffset - 1 ].mod.name + if ( StaticFind( modName ) && NSIsModEnabled( modName ) ) + CoreModToggleDialog( modName ) + else { - Hud_SetEnabled( buttons[ i ], true ) - Hud_SetVisible( buttons[ i ], true ) - - SetModMenuNameText( buttons[ i ] ) + NSSetModEnabled( modName, !NSIsModEnabled( modName ) ) + var panel = file.panels[ int ( Hud_GetScriptID( Hud_GetParent( button ) ) ) - 1 ] + SetControlBoxColor( Hud_GetChild( panel, "ControlBox" ), modName ) + SetControlBarColor( modName ) + SetModEnabledHelperImageAsset( Hud_GetChild( panel, "EnabledImage" ), modName ) + // RefreshMods() + UpdateListSliderPosition() + UpdateListSliderHeight() } } -void function SetModMenuNameText( var button ) +void function OnReloadModsButtonPressed( var button ) { - modStruct mod = file.modsArrayFiltered[ int ( Hud_GetScriptID( button ) ) + file.scrollOffset ] + ReloadMods() +} - // should be localisation at some point - if ( NSIsModEnabled( mod.modName ) ) - SetButtonRuiText( button, mod.modName + " v" + NSGetModVersionByModName( mod.modName ) ) - else - SetButtonRuiText( button, mod.modName + " (DISABLED)" ) +void function OnAuthenticationAgreementButtonPressed( var button ) +{ + NorthstarMasterServerAuthDialog() } -void function OnModMenuButtonPressed( var button ) +void function OnModLinkButtonPressed( var button ) { - string modName = file.modsArrayFiltered[ int ( Hud_GetScriptID( button ) ) + file.scrollOffset ].modName - if ( ( modName == "Northstar.Client" || modName == "Northstar.Coop" || modName == "Northstar.CustomServers") && NSIsModEnabled( modName ) ) - { - file.currentMod = modName - file.currentButton = button - CoreModToggleDialog( modName ) - } - else - { - NSSetModEnabled( modName, !NSIsModEnabled( modName ) ) + string modName = file.mods[ int ( Hud_GetScriptID( Hud_GetParent( file.currentButton ) ) ) + file.scrollOffset - 1 ].mod.name + string link = NSGetModDownloadLinkByModName( modName ) + if ( link.find("http://") != 0 && link.find("https://") != 0 ) + link = "http://" + link // links without the http or https protocol get opened in the internal browser + LaunchExternalWebBrowser( link, WEBBROWSER_FLAG_FORCEEXTERNAL ) +} - SetModMenuNameText( button ) +void function OnFiltersChange( var n ) +{ + file.scrollOffset = 0 - file.shouldReloadModsOnEnd = true - } + UpdateList() + UpdateListSliderHeight() + UpdateListSliderPosition() } +void function OnBtnFiltersClear_Activate( var button ) +{ + Hud_SetText( Hud_GetChild( file.menu, "BtnModsSearch" ), "" ) + + SetConVarInt( "filter_mods", 0 ) + + OnFiltersChange( null ) +} + +void function OnHideConVarsChange( var n ) +{ + string modName = file.lastMod.name + if ( modName == "" ) + return + var rui = Hud_GetRui( Hud_GetChild( file.menu, "LabelDetails" ) ) + RuiSetString( rui, "messageText", FormatModDescription( modName ) ) +} + +// LIST LOGIC + void function CoreModToggleDialog( string mod ) { DialogData dialogData @@ -247,46 +284,235 @@ void function CoreModToggleDialog( string mod ) void function DisableMod() { - NSSetModEnabled( file.currentMod, false ) + string modName = file.mods[ int ( Hud_GetScriptID( Hud_GetParent( file.currentButton ) ) ) + file.scrollOffset - 1 ].mod.name + NSSetModEnabled( modName, false ) - SetModMenuNameText( file.currentButton ) + var panel = file.panels[ int ( Hud_GetScriptID( Hud_GetParent( file.currentButton ) ) ) - 1] + SetControlBoxColor( Hud_GetChild( panel, "ControlBox" ), modName ) + SetControlBarColor( modName ) + SetModEnabledHelperImageAsset( Hud_GetChild( panel, "EnabledImage" ), modName ) - file.shouldReloadModsOnEnd = true + RefreshMods() } -void function OnModMenuButtonFocused( var button ) +array<string> function GetEnabledModsArray() { - string modName = file.modsArrayFiltered[ int ( Hud_GetScriptID( button ) ) + file.scrollOffset ].modName + array<string> enabledMods + foreach ( string mod in NSGetModNames() ) + { + if ( NSIsModEnabled( mod ) ) + enabledMods.append( mod ) + } + return enabledMods +} - var rui = Hud_GetRui( Hud_GetChild( file.menu, "LabelDetails" ) ) - - RuiSetGameTime( rui, "startTime", -99999.99 ) // make sure it skips the whole animation for showing this - RuiSetString( rui, "headerText", modName ) - RuiSetString( rui, "messageText", FormatModDescription( modName ) ) +void function HideAllPanels() +{ + foreach ( var panel in file.panels ) + { + Hud_SetEnabled( panel, false ) + Hud_SetVisible( panel, false ) + } +} + +void function UpdateList() +{ + HideAllPanels() + RefreshMods() + DisplayModPanels() +} + +void function RefreshMods() +{ + array<string> modNames = NSGetModNames() + file.mods.clear() + + bool reverse = GetConVarBool( "modlist_reverse" ) + + int lastLoadPriority = reverse ? NSGetModLoadPriority( modNames[ modNames.len() - 1 ] ) + 1 : -1 + string searchTerm = Hud_GetUTF8Text( Hud_GetChild( file.menu, "BtnModsSearch" ) ).tolower() + + for ( int i = reverse ? modNames.len() - 1 : 0; + reverse ? ( i >= 0 ) : ( i < modNames.len() ); + i += ( reverse ? -1 : 1) ) + { + string mod = modNames[i] + + if ( searchTerm.len() && mod.tolower().find( searchTerm ) == null ) + continue + + bool enabled = NSIsModEnabled( mod ) + bool required = NSIsModRequiredOnClient( mod ) + switch ( GetConVarInt( "filter_mods" ) ) + { + case filterShow.ONLY_ENABLED: + if ( !enabled ) + continue + break + case filterShow.ONLY_DISABLED: + if ( enabled ) + continue + break + case filterShow.ONLY_REQUIRED: + if ( !required ) + continue + break + case filterShow.ONLY_NOT_REQUIRED: + if( required ) + continue + break + } + + int pr = NSGetModLoadPriority( mod ) + + if ( reverse ? pr < lastLoadPriority : pr > lastLoadPriority ) + { + modData m + m.name = pr.tostring() + + panelContent c + c.mod = m + c.isHeader = true + file.mods.append( c ) + lastLoadPriority = pr + } + + modData m + m.name = mod + m.version = NSGetModVersionByModName( mod ) + m.link = NSGetModDownloadLinkByModName( mod ) + m.loadPriority = NSGetModLoadPriority( mod ) + m.enabled = enabled + m.conVars = NSGetModConvarsByModName( mod ) + + panelContent c + c.mod = m + + file.mods.append( c ) + } +} + +void function DisplayModPanels() +{ + foreach ( int i, var panel in file.panels) + { + if ( i >= file.mods.len() || file.scrollOffset + i >= file.mods.len() ) // don't try to show more panels than needed + break + + panelContent c = file.mods[ file.scrollOffset + i ] + modData mod = c.mod + var btn = Hud_GetChild( panel, "BtnMod" ) + var headerLabel = Hud_GetChild( panel, "Header" ) + var box = Hud_GetChild( panel, "ControlBox" ) + var line = Hud_GetChild( panel, "BottomLine" ) + var warning = Hud_GetChild( panel, "WarningImage" ) + var enabledImage = Hud_GetChild( panel, "EnabledImage" ) + + if ( c.isHeader ) + { + Hud_SetEnabled( btn, false ) + Hud_SetVisible( btn, false ) + + Hud_SetText( headerLabel, "Load Priority: " + mod.name ) + Hud_SetVisible( headerLabel, true ) + + Hud_SetVisible( box, false ) + Hud_SetVisible( line, true ) + + Hud_SetVisible( warning, false ) + Hud_SetVisible( enabledImage, false ) + } + else + { + Hud_SetEnabled( btn, true ) + Hud_SetVisible( btn, true ) + Hud_SetText( btn, mod.name ) + + Hud_SetVisible( headerLabel, false ) + + SetControlBoxColor( box, mod.name ) + Hud_SetVisible( box, true ) + Hud_SetVisible( line, false ) + + Hud_SetVisible( warning, NSIsModRequiredOnClient( c.mod.name ) ) + + SetModEnabledHelperImageAsset( enabledImage, c.mod.name ) + } + Hud_SetVisible( panel, true ) + } +} + +void function SetModEnabledHelperImageAsset( var panel, string modName ) +{ + if( NSIsModEnabled( modName ) ) + RuiSetImage( Hud_GetRui( panel ), "basicImage", $"rui/menu/common/merit_state_success" ) + else + RuiSetImage( Hud_GetRui( panel ), "basicImage", $"rui/menu/common/merit_state_failure" ) + RuiSetFloat3(Hud_GetRui( panel ), "basicImageColor", GetControlColorForMod( modName ) ) + Hud_SetVisible( panel, true ) +} + +void function SetControlBoxColor( var box, string modName ) +{ + var rui = Hud_GetRui( box ) + // if ( NSIsModEnabled( modName ) ) + // RuiSetFloat3(rui, "basicImageColor", <0,1,0>) + // else + // RuiSetFloat3(rui, "basicImageColor", <1,0,0>) + RuiSetFloat3(rui, "basicImageColor", GetControlColorForMod( modName ) ) +} + +void function SetControlBarColor( string modName ) +{ + var bar_element = Hud_GetChild( file.menu, "ModEnabledBar" ) + var bar = Hud_GetRui( bar_element ) + // if ( NSIsModEnabled( modName ) ) + // RuiSetFloat3(bar, "basicImageColor", <0,1,0>) + // else + // RuiSetFloat3(bar, "basicImageColor", <1,0,0>) + RuiSetFloat3(bar, "basicImageColor", GetControlColorForMod( modName ) ) + Hud_SetVisible( bar_element, true ) +} + +vector function GetControlColorForMod( string modName ) +{ + if ( NSIsModEnabled( modName ) ) + switch ( GetConVarInt( "colorblind_mode" ) ) + { + case 1: + case 2: + case 3: + default: + return <0,1,0> + } + else + switch ( GetConVarInt( "colorblind_mode" ) ) + { + case 1: + case 2: + return <0.29,0,0.57> + case 3: + default: + return <1,0,0> + } + unreachable } string function FormatModDescription( string modName ) { string ret // version - ret += format( "Version %s\n", NSGetModVersionByModName( modName ) ) - - // download link - string modLink = NSGetModDownloadLinkByModName( modName ) - if ( modLink.len() != 0 ) - ret += format( "Download link: \"%s\"\n", modLink ) - + ret += format( "Version %s\n", NSGetModVersionByModName( modName ) ) + // load priority ret += format( "Load Priority: %i\n", NSGetModLoadPriority( modName ) ) - - // todo: add ClientRequired here - + // convars array<string> modCvars = NSGetModConvarsByModName( modName ) - if ( modCvars.len() != 0 ) + if ( modCvars.len() != 0 && GetConVarBool( "modlist_show_convars" ) ) { ret += "ConVars: " - + for ( int i = 0; i < modCvars.len(); i++ ) { if ( i != modCvars.len() - 1 ) @@ -294,76 +520,34 @@ string function FormatModDescription( string modName ) else ret += format( "\"%s\"", modCvars[ i ] ) } - + ret += "\n" } - + // description ret += format( "\n%s\n", NSGetModDescriptionByModName( modName ) ) - - return ret -} - -void function OnReloadModsButtonPressed( var button ) -{ - ReloadMods() -} - -void function ReloadMods() -{ - NSReloadMods() - ClientCommand( "reload_localization" ) - ClientCommand( "loadPlaylists" ) - - bool svCheatsOriginal = GetConVarBool( "sv_cheats" ) - SetConVarBool( "sv_cheats", true ) - ClientCommand( "weapon_reparse" ) // weapon_reparse only works if a server is running and sv_cheats is 1, gotta figure this out eventually - SetConVarBool( "sv_cheats", svCheatsOriginal ) - - // note: the logic for this seems really odd, unsure why it doesn't seem to update, since the same code seems to get run irregardless of whether we've read weapon data before - ClientCommand( "uiscript_reset" ) -} -void function OnAuthenticationAgreementButtonPressed( var button ) -{ - NorthstarMasterServerAuthDialog() + return ret } +//////////// +// SLIDER +//////////// -void function OnBtnFiltersClear_Activate( var button ) -{ - Hud_SetText( Hud_GetChild( file.menu, "BtnModsSearch" ), "" ) - - SetConVarInt( "filter_mods", 0 ) - - OnFiltersChange(0) -} - -////////////////////////////// -// Slider -////////////////////////////// void function UpdateMouseDeltaBuffer(int x, int y) { - mouseDeltaBuffer.deltaX += x - mouseDeltaBuffer.deltaY += y + mouseDeltaBuffer.deltaX = x + mouseDeltaBuffer.deltaY = y + UpdateListSliderHeight() SliderBarUpdate() } -void function FlushMouseDeltaBuffer() -{ - mouseDeltaBuffer.deltaX = 0 - mouseDeltaBuffer.deltaY = 0 -} - void function SliderBarUpdate() { - if ( file.modsArrayFiltered.len() <= 17 ) - { - FlushMouseDeltaBuffer() + if ( file.mods.len() <= 15 ) return - } var sliderButton = Hud_GetChild( file.menu , "BtnModListSlider" ) var sliderPanel = Hud_GetChild( file.menu , "BtnModListSliderPanel" ) @@ -376,12 +560,11 @@ void function SliderBarUpdate() float maxYPos = minYPos - (maxHeight - Hud_GetHeight( sliderPanel )) float useableSpace = (maxHeight - Hud_GetHeight( sliderPanel )) - float jump = minYPos - (useableSpace / ( float( file.modsArrayFiltered.len()))) + float jump = minYPos - (useableSpace / ( float( file.mods.len()))) // got local from official respaw scripts, without untyped throws an error local pos = Hud_GetPos(sliderButton)[1] local newPos = pos - mouseDeltaBuffer.deltaY - FlushMouseDeltaBuffer() if ( newPos < maxYPos ) newPos = maxYPos if ( newPos > minYPos ) newPos = minYPos @@ -390,22 +573,42 @@ void function SliderBarUpdate() Hud_SetPos( sliderPanel , 2, newPos ) Hud_SetPos( movementCapture , 2, newPos ) - file.scrollOffset = -int( ( (newPos - minYPos) / useableSpace ) * ( file.modsArrayFiltered.len() - BUTTONS_PER_PAGE) ) + file.scrollOffset = -int( ( (newPos - minYPos) / useableSpace ) * ( file.mods.len() - PANELS_LEN) ) UpdateList() } +void function UpdateListSliderPosition() +{ + var sliderButton = Hud_GetChild( file.menu , "BtnModListSlider" ) + var sliderPanel = Hud_GetChild( file.menu , "BtnModListSliderPanel" ) + var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) + + float mods = float ( file.mods.len() ) + + float minYPos = -40.0 * (GetScreenSize()[1] / 1080.0) + float useableSpace = (604.0 * (GetScreenSize()[1] / 1080.0) - Hud_GetHeight( sliderPanel )) + + float jump = minYPos - (useableSpace / ( mods - float( PANELS_LEN ) ) * file.scrollOffset) + + if ( jump > minYPos ) jump = minYPos + + Hud_SetPos( sliderButton , 2, jump ) + Hud_SetPos( sliderPanel , 2, jump ) + Hud_SetPos( movementCapture , 2, jump ) +} + void function UpdateListSliderHeight() { var sliderButton = Hud_GetChild( file.menu , "BtnModListSlider" ) var sliderPanel = Hud_GetChild( file.menu , "BtnModListSliderPanel" ) var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) - - float mods = float ( file.modsArrayFiltered.len() ) + + float mods = float ( file.mods.len() ) float maxHeight = 604.0 * (GetScreenSize()[1] / 1080.0) float minHeight = 80.0 * (GetScreenSize()[1] / 1080.0) - float height = maxHeight * ( float( BUTTONS_PER_PAGE ) / mods ) + float height = maxHeight * ( float( PANELS_LEN ) / mods ) if ( height > maxHeight ) height = maxHeight if ( height < minHeight ) height = minHeight @@ -415,68 +618,75 @@ void function UpdateListSliderHeight() Hud_SetHeight( movementCapture , height ) } - -void function UpdateListSliderPosition() +void function OnScrollDown( var button ) { - var sliderButton = Hud_GetChild( file.menu , "BtnModListSlider" ) - var sliderPanel = Hud_GetChild( file.menu , "BtnModListSliderPanel" ) - var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) - - float mods = float ( file.modsArrayFiltered.len() ) - - float minYPos = -40.0 * (GetScreenSize()[1] / 1080.0) - float useableSpace = (604.0 * (GetScreenSize()[1] / 1080.0) - Hud_GetHeight( sliderPanel )) - - float jump = minYPos - (useableSpace / ( mods - float( BUTTONS_PER_PAGE ) ) * file.scrollOffset) - - //jump = jump * (GetScreenSize()[1] / 1080.0) - - if ( jump > minYPos ) jump = minYPos + if ( file.mods.len() <= PANELS_LEN ) return + file.scrollOffset += 5 + if (file.scrollOffset + PANELS_LEN > file.mods.len()) + file.scrollOffset = file.mods.len() - PANELS_LEN + Hud_SetFocused( Hud_GetChild( file.menu, "BtnModListSlider" ) ) + ValidateScrollOffset() +} - Hud_SetPos( sliderButton , 2, jump ) - Hud_SetPos( sliderPanel , 2, jump ) - Hud_SetPos( movementCapture , 2, jump ) +void function OnScrollUp( var button ) +{ + file.scrollOffset -= 5 + if (file.scrollOffset < 0) + file.scrollOffset = 0 + Hud_SetFocused( Hud_GetChild( file.menu, "BtnModListSlider" ) ) + ValidateScrollOffset() } void function OnDownArrowSelected( var button ) { - if ( file.modsArrayFiltered.len() <= BUTTONS_PER_PAGE ) return + if ( file.mods.len() <= PANELS_LEN ) return file.scrollOffset += 1 - if (file.scrollOffset + BUTTONS_PER_PAGE > file.modsArrayFiltered.len()) { - file.scrollOffset = file.modsArrayFiltered.len() - BUTTONS_PER_PAGE - } - UpdateList() - UpdateListSliderPosition() + if (file.scrollOffset + PANELS_LEN > file.mods.len()) + file.scrollOffset = file.mods.len() - PANELS_LEN + ValidateScrollOffset() } - void function OnUpArrowSelected( var button ) { file.scrollOffset -= 1 - if (file.scrollOffset < 0) { + if (file.scrollOffset < 0) file.scrollOffset = 0 - } - UpdateList() - UpdateListSliderPosition() + ValidateScrollOffset() } -void function OnScrollDown( var button ) +void function ValidateScrollOffset() { - if ( file.modsArrayFiltered.len() <= BUTTONS_PER_PAGE ) return - file.scrollOffset += 5 - if (file.scrollOffset + BUTTONS_PER_PAGE > file.modsArrayFiltered.len()) { - file.scrollOffset = file.modsArrayFiltered.len() - BUTTONS_PER_PAGE - } - UpdateList() + RefreshMods() + if( file.scrollOffset + 15 > file.mods.len() ) + file.scrollOffset = file.mods.len() - 15 + if( file.scrollOffset < 0 ) + file.scrollOffset = 0 + HideAllPanels() + DisplayModPanels() + UpdateListSliderHeight() UpdateListSliderPosition() } -void function OnScrollUp( var button ) +// Static arrays don't have the .find method for some reason +bool function StaticFind( string mod ) { - file.scrollOffset -= 5 - if (file.scrollOffset < 0) { - file.scrollOffset = 0 - } - UpdateList() - UpdateListSliderPosition() + foreach( string smod in CORE_MODS ) + if ( mod == smod ) + return true + return false +} + +void function ReloadMods() +{ + NSReloadMods() + ClientCommand( "reload_localization" ) + ClientCommand( "loadPlaylists" ) + + bool svCheatsOriginal = GetConVarBool( "sv_cheats" ) + SetConVarBool( "sv_cheats", true ) + ClientCommand( "weapon_reparse" ) // weapon_reparse only works if a server is running and sv_cheats is 1, gotta figure this out eventually + SetConVarBool( "sv_cheats", svCheatsOriginal ) + + // note: the logic for this seems really odd, unsure why it doesn't seem to update, since the same code seems to get run irregardless of whether we've read weapon data before + ClientCommand( "uiscript_reset" ) }
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut index eb068374..cdeb8b3e 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -4,6 +4,9 @@ untyped global function AddNorthstarServerBrowserMenu global function ThreadedAuthAndConnectToServer +global function AddConnectToServerCallback +global function RemoveConnectToServerCallback +global function TriggerConnectToServerCallbacks // Stop peeking @@ -38,7 +41,7 @@ enum sortingBy PLAYERS, MAP, GAMEMODE, - LATENCY + REGION } // Column sort direction, only one of these can be aplied at once @@ -48,8 +51,8 @@ struct { bool serverPlayers = true bool serverMap = true bool serverGamemode = true - bool serverLatency = true - // 0 = none; 1 = default; 2 = name; 3 = players; 4 = map; 5 = gamemode; 6 = latency + bool serverRegion = true + // 0 = none; 1 = default; 2 = name; 3 = players; 4 = map; 5 = gamemode; 6 = region int sortingBy = 1 } filterDirection @@ -61,13 +64,12 @@ struct serverStruct { int serverPlayersMax string serverMap string serverGamemode - int serverLatency + string serverRegion } struct { // UI state vars var menu - int lastSelectedServer = 999 int focusedServerIndex = 0 int scrollOffset = 0 bool serverListRequestFailed = false @@ -79,6 +81,10 @@ struct { // filtered array of servers array<serverStruct> serversArrayFiltered + + array<ServerInfo> filteredServers + ServerInfo& focusedServer + ServerInfo& lastSelectedServer // UI references array<var> serverButtons @@ -87,7 +93,9 @@ struct { array<var> serversProtected array<var> serversMap array<var> serversGamemode - array<var> serversLatency + array<var> serversRegion + + array< void functionref( ServerInfo ) > connectCallbacks } file @@ -142,7 +150,7 @@ void function InitServerBrowserMenu() { file.menu = GetMenu( "ServerBrowserMenu" ) - AddMouseMovementCaptureHandler( file.menu, UpdateMouseDeltaBuffer ) + AddMouseMovementCaptureHandler( Hud_GetChild(file.menu, "MouseMovementCapture"), UpdateMouseDeltaBuffer ) // Get menu stuff file.serverButtons = GetElementsByClassname( file.menu, "ServerButton" ) @@ -151,7 +159,7 @@ void function InitServerBrowserMenu() file.serversProtected = GetElementsByClassname( file.menu, "ServerLock" ) file.serversMap = GetElementsByClassname( file.menu, "ServerMap" ) file.serversGamemode = GetElementsByClassname( file.menu, "ServerGamemode" ) - file.serversLatency = GetElementsByClassname( file.menu, "ServerLatency" ) + file.serversRegion = GetElementsByClassname( file.menu, "Serverregion" ) filterArguments.filterMaps = [ "SWITCH_ANY" ] Hud_DialogList_AddListItem( Hud_GetChild( file.menu, "SwtBtnSelectMap" ), "SWITCH_ANY", "0" ) @@ -194,7 +202,7 @@ void function InitServerBrowserMenu() AddButtonEventHandler( Hud_GetChild( file.menu, "BtnServerPlayersTab"), UIE_CLICK, SortServerListByPlayers_Activate ) AddButtonEventHandler( Hud_GetChild( file.menu, "BtnServerMapTab"), UIE_CLICK, SortServerListByMap_Activate ) AddButtonEventHandler( Hud_GetChild( file.menu, "BtnServerGamemodeTab"), UIE_CLICK, SortServerListByGamemode_Activate ) - AddButtonEventHandler( Hud_GetChild( file.menu, "BtnServerLatencyTab"), UIE_CLICK, SortServerListByLatency_Activate ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnServerRegionTab"), UIE_CLICK, SortServerListByRegion_Activate ) AddButtonEventHandler( Hud_GetChild( file.menu, "SwtBtnSelectMap"), UIE_CHANGE, FilterAndUpdateList ) @@ -218,8 +226,6 @@ void function InitServerBrowserMenu() Hud_SetText( Hud_GetChild( file.menu, "BtnServerDescription"), "" ) Hud_SetText( Hud_GetChild( file.menu, "BtnServerMods"), "" ) - // Unfinished features - Hud_SetLocked( Hud_GetChild( file.menu, "BtnServerLatencyTab" ), true ) // Rui is a pain RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnHideFull") ), "buttonText", "" ) @@ -255,7 +261,7 @@ void function FlushMouseDeltaBuffer() void function SliderBarUpdate() { - if ( file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE ) + if ( file.filteredServers.len() <= BUTTONS_PER_PAGE ) { FlushMouseDeltaBuffer() return @@ -272,7 +278,7 @@ void function SliderBarUpdate() float maxYPos = minYPos - ( maxHeight - Hud_GetHeight( sliderPanel ) ) float useableSpace = ( maxHeight - Hud_GetHeight( sliderPanel ) ) - float jump = minYPos - ( useableSpace / ( float( file.serversArrayFiltered.len() ) ) ) + float jump = minYPos - ( useableSpace / ( float( file.filteredServers.len() ) ) ) // got local from official respaw scripts, without untyped throws an error local pos = Hud_GetPos( sliderButton )[1] @@ -286,7 +292,7 @@ void function SliderBarUpdate() Hud_SetPos( sliderPanel , 2, newPos ) Hud_SetPos( movementCapture , 2, newPos ) - file.scrollOffset = -int( ( ( newPos - minYPos ) / useableSpace ) * ( file.serversArrayFiltered.len() - BUTTONS_PER_PAGE ) ) + file.scrollOffset = -int( ( ( newPos - minYPos ) / useableSpace ) * ( file.filteredServers.len() - BUTTONS_PER_PAGE ) ) UpdateShownPage() } @@ -330,13 +336,13 @@ void function UpdateListSliderPosition( int servers ) void function OnScrollDown( var button ) { - if (file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE) return + if (file.filteredServers.len() <= BUTTONS_PER_PAGE) return file.scrollOffset += 5 - if (file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len()) { - file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE + if (file.scrollOffset + BUTTONS_PER_PAGE > file.filteredServers.len()) { + file.scrollOffset = file.filteredServers.len() - BUTTONS_PER_PAGE } UpdateShownPage() - UpdateListSliderPosition( file.serversArrayFiltered.len() ) + UpdateListSliderPosition( file.filteredServers.len() ) } void function OnScrollUp( var button ) @@ -346,7 +352,7 @@ void function OnScrollUp( var button ) file.scrollOffset = 0 } UpdateShownPage() - UpdateListSliderPosition( file.serversArrayFiltered.len() ) + UpdateListSliderPosition( file.filteredServers.len() ) } //////////////////////////// @@ -486,7 +492,7 @@ void function OnHitDummyTop( var button ) { // only update if list position changed UpdateShownPage() - UpdateListSliderPosition( file.serversArrayFiltered.len() ) + UpdateListSliderPosition( file.filteredServers.len() ) DisplayFocusedServerInfo( file.serverButtonFocusedID ) Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer1" ) ) } @@ -495,10 +501,10 @@ void function OnHitDummyTop( var button ) void function OnHitDummyBottom( var button ) { file.scrollOffset += 1 - if ( file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len() ) + if ( file.scrollOffset + BUTTONS_PER_PAGE > file.filteredServers.len() ) { // was at bottom already - file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE + file.scrollOffset = file.filteredServers.len() - BUTTONS_PER_PAGE Hud_SetFocused( Hud_GetChild( file.menu, "BtnServerSearch" ) ) HideServerInfo() } @@ -506,7 +512,7 @@ void function OnHitDummyBottom( var button ) { // only update if list position changed UpdateShownPage() - UpdateListSliderPosition( file.serversArrayFiltered.len() ) + UpdateListSliderPosition( file.filteredServers.len() ) DisplayFocusedServerInfo( file.serverButtonFocusedID ) Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer15" ) ) } @@ -520,15 +526,15 @@ void function OnHitDummyAfterFilterClear( var button ) void function OnDownArrowSelected( var button ) { - if ( file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE ) return + if ( file.filteredServers.len() <= BUTTONS_PER_PAGE ) return file.scrollOffset += 1 - if ( file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len() ) + if ( file.scrollOffset + BUTTONS_PER_PAGE > file.filteredServers.len() ) { - file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE + file.scrollOffset = file.filteredServers.len() - BUTTONS_PER_PAGE } UpdateShownPage() - UpdateListSliderPosition( file.serversArrayFiltered.len() ) + UpdateListSliderPosition( file.filteredServers.len() ) } @@ -541,7 +547,7 @@ void function OnUpArrowSelected( var button ) } UpdateShownPage() - UpdateListSliderPosition( file.serversArrayFiltered.len() ) + UpdateListSliderPosition( file.filteredServers.len() ) } //////////////////////// @@ -644,7 +650,7 @@ void function FilterAndUpdateList( var n ) filterArguments.hideProtected = GetConVarBool( "filter_hide_protected" ) file.scrollOffset = 0 - UpdateListSliderPosition( file.serversArrayFiltered.len() ) + UpdateListSliderPosition( file.filteredServers.len() ) HideServerInfo() FilterServerList() @@ -675,9 +681,9 @@ void function FilterAndUpdateList( var n ) filterDirection.serverGamemode = !filterDirection.serverGamemode SortServerListByGamemode_Activate(0) break - case sortingBy.LATENCY: - filterDirection.serverLatency = !filterDirection.serverLatency - SortServerListByLatency_Activate(0) + case sortingBy.REGION: + filterDirection.serverRegion = !filterDirection.serverRegion + SortServerListByRegion_Activate(0) break default: printt( "How the f did you get here" ) @@ -715,7 +721,7 @@ void function WaitForServerListRequest() Hud_SetText( file.playerCountLabels[ i ], "" ) Hud_SetText( file.serversMap[ i ], "" ) Hud_SetText( file.serversGamemode[ i ], "" ) - Hud_SetText( file.serversLatency[ i ], "" ) + Hud_SetText( file.serversRegion[ i ], "" ) } HideServerInfo() @@ -743,49 +749,42 @@ void function WaitForServerListRequest() void function FilterServerList() { - file.serversArrayFiltered.clear() + file.filteredServers.clear() int totalPlayers = 0 - for ( int i = 0; i < NSGetServerCount(); i++ ) - { - serverStruct tempServer - tempServer.serverIndex = i - tempServer.serverProtected = NSServerRequiresPassword( i ) - tempServer.serverName = NSGetServerName( i ) - tempServer.serverPlayers = NSGetServerPlayerCount( i ) - tempServer.serverPlayersMax = NSGetServerMaxPlayerCount( i ) - tempServer.serverMap = NSGetServerMap( i ) - tempServer.serverGamemode = GetGameModeDisplayName( NSGetServerPlaylist ( i ) ) - - totalPlayers += tempServer.serverPlayers + array<ServerInfo> servers = NSGetGameServers() + foreach ( ServerInfo server in servers ) + { + totalPlayers += server.playerCount // Filters - if ( filterArguments.hideEmpty && tempServer.serverPlayers == 0 ) + if ( filterArguments.hideEmpty && server.playerCount == 0 ) continue; - if ( filterArguments.hideFull && tempServer.serverPlayers == tempServer.serverPlayersMax ) + if ( filterArguments.hideFull && server.playerCount == server.maxPlayerCount ) continue; - if ( filterArguments.hideProtected && tempServer.serverProtected ) + if ( filterArguments.hideProtected && server.requiresPassword ) continue; - if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap != tempServer.serverMap ) + if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap != server.map ) continue; - if ( filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode != tempServer.serverGamemode ) + if ( filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode != GetGameModeDisplayName(server.playlist) ) continue; - + // Search if ( filterArguments.useSearch ) { array<string> sName - sName.append( tempServer.serverName.tolower() ) - sName.append( Localize( GetMapDisplayName( tempServer.serverMap ) ).tolower() ) - sName.append( tempServer.serverMap.tolower() ) - sName.append( tempServer.serverGamemode.tolower() ) - sName.append( Localize( tempServer.serverGamemode ).tolower() ) - sName.append( NSGetServerDescription( i ).tolower() ) + sName.append( server.name.tolower() ) + sName.append( Localize( GetMapDisplayName( server.map ) ).tolower() ) + sName.append( server.map.tolower() ) + sName.append( server.playlist.tolower() ) + sName.append( Localize( server.playlist ).tolower() ) + sName.append( server.description.tolower() ) + sName.append( server.region.tolower() ) string sTerm = filterArguments.searchTerm.tolower() @@ -799,9 +798,8 @@ void function FilterServerList() if ( !found ) continue; } - - // Server fits our requirements, add it to the list - file.serversArrayFiltered.append( tempServer ) + + file.filteredServers.append( server ) } // Update player and server count @@ -821,25 +819,25 @@ void function UpdateShownPage() Hud_SetText( file.playerCountLabels[ i ], "" ) Hud_SetText( file.serversMap[ i ], "" ) Hud_SetText( file.serversGamemode[ i ], "" ) - Hud_SetText( file.serversLatency[ i ], "" ) + Hud_SetText( file.serversRegion[ i ], "" ) } - int j = file.serversArrayFiltered.len() > BUTTONS_PER_PAGE ? BUTTONS_PER_PAGE : file.serversArrayFiltered.len() + int j = file.filteredServers.len() > BUTTONS_PER_PAGE ? BUTTONS_PER_PAGE : file.filteredServers.len() for ( int i = 0; i < j; i++ ) { - int buttonIndex = file.scrollOffset + i - int serverIndex = file.serversArrayFiltered[ buttonIndex ].serverIndex + ServerInfo server = file.filteredServers[ buttonIndex ] Hud_SetEnabled( file.serverButtons[ i ], true ) Hud_SetVisible( file.serverButtons[ i ], true ) - Hud_SetVisible( file.serversProtected[ i ], file.serversArrayFiltered[ buttonIndex ].serverProtected ) - Hud_SetText( file.serversName[ i ], file.serversArrayFiltered[ buttonIndex ].serverName ) - Hud_SetText( file.playerCountLabels[ i ], format( "%i/%i", file.serversArrayFiltered[ buttonIndex ].serverPlayers, file.serversArrayFiltered[ buttonIndex ].serverPlayersMax ) ) - Hud_SetText( file.serversMap[ i ], GetMapDisplayName( file.serversArrayFiltered[ buttonIndex ].serverMap ) ) - Hud_SetText( file.serversGamemode[ i ], file.serversArrayFiltered[ buttonIndex ].serverGamemode ) + Hud_SetVisible( file.serversProtected[ i ], server.requiresPassword ) + Hud_SetText( file.serversName[ i ], server.name ) + Hud_SetText( file.playerCountLabels[ i ], format( "%i/%i", server.playerCount, server.maxPlayerCount ) ) + Hud_SetText( file.serversMap[ i ], GetMapDisplayName( server.map ) ) + Hud_SetText( file.serversGamemode[ i ], GetGameModeDisplayName( server.playlist ) ) + Hud_SetText( file.serversRegion[ i ], server.region ) } @@ -849,7 +847,7 @@ void function UpdateShownPage() Hud_SetVisible( file.serverButtons[ 0 ], true ) Hud_SetText( file.serversName[ 0 ], "#NS_SERVERBROWSER_NOSERVERS" ) } - UpdateListSliderHeight( float( file.serversArrayFiltered.len() ) ) + UpdateListSliderHeight( float( file.filteredServers.len() ) ) } void function OnServerButtonFocused( var button ) @@ -859,8 +857,9 @@ void function OnServerButtonFocused( var button ) int scriptID = int ( Hud_GetScriptID( button ) ) file.serverButtonFocusedID = scriptID - if ( file.serversArrayFiltered.len() > 0 ) - file.focusedServerIndex = file.serversArrayFiltered[ file.scrollOffset + scriptID ].serverIndex + if ( file.filteredServers.len() > 0 ) + // file.focusedServerIndex = file.filteredServers[ file.scrollOffset + scriptID ].serverIndex + file.focusedServer = file.filteredServers[ file.scrollOffset + scriptID ] DisplayFocusedServerInfo( scriptID ) } @@ -881,13 +880,12 @@ void function CheckDoubleClick( int scriptID, bool wasClickNav ) int serverIndex = file.scrollOffset + scriptID bool sameServer = false - if ( file.lastSelectedServer == serverIndex ) sameServer = true - + if ( file.lastSelectedServer == file.filteredServers[ serverIndex ] ) sameServer = true file.serverSelectedTimeLast = file.serverSelectedTime file.serverSelectedTime = Time() - file.lastSelectedServer = serverIndex + file.lastSelectedServer = file.filteredServers[ serverIndex ] if ( wasClickNav && ( file.serverSelectedTime - file.serverSelectedTimeLast < DOUBLE_CLICK_TIME_MS ) && sameServer ) { @@ -899,7 +897,7 @@ void function DisplayFocusedServerInfo( int scriptID ) { if ( scriptID == 999 || scriptID == -1 || scriptID == 16 ) return - if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed || file.serversArrayFiltered.len() == 0 ) + if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed || file.filteredServers.len() == 0 ) return var menu = GetMenu( "ServerBrowserMenu" ) @@ -907,6 +905,7 @@ void function DisplayFocusedServerInfo( int scriptID ) int serverIndex = file.scrollOffset + scriptID if ( serverIndex < 0 ) serverIndex = 0 + ServerInfo server = file.filteredServers[ serverIndex ] Hud_SetVisible( Hud_GetChild( menu, "BtnServerDescription" ), true ) Hud_SetVisible( Hud_GetChild( menu, "BtnServerMods" ), true ) @@ -914,78 +913,153 @@ void function DisplayFocusedServerInfo( int scriptID ) // text panels Hud_SetVisible( Hud_GetChild( menu, "LabelDescription" ), true ) Hud_SetVisible( Hud_GetChild( menu, "LabelMods" ), false ) - Hud_SetText( Hud_GetChild( menu, "LabelDescription" ), NSGetServerDescription( file.serversArrayFiltered[ serverIndex ].serverIndex ) + "\n\nRequired Mods:\n" + FillInServerModsLabel( file.serversArrayFiltered[ serverIndex ].serverIndex ) ) + Hud_SetText( Hud_GetChild( menu, "LabelDescription" ), server.description + "\n\nRequired Mods:\n" + FillInServerModsLabel( server.requiredMods ) ) // map name/image/server name - string map = file.serversArrayFiltered[ serverIndex ].serverMap + string map = server.map Hud_SetVisible( Hud_GetChild( menu, "NextMapImage" ), true ) Hud_SetVisible( Hud_GetChild( menu, "NextMapBack" ), true ) RuiSetImage( Hud_GetRui( Hud_GetChild( menu, "NextMapImage" ) ), "basicImage", GetMapImageForMapName( map ) ) Hud_SetVisible( Hud_GetChild( menu, "NextMapName" ), true ) Hud_SetText( Hud_GetChild( menu, "NextMapName" ), GetMapDisplayName( map ) ) Hud_SetVisible( Hud_GetChild( menu, "ServerName" ), true ) - Hud_SetText( Hud_GetChild( menu, "ServerName" ), NSGetServerName( file.serversArrayFiltered[ serverIndex ].serverIndex ) ) + Hud_SetText( Hud_GetChild( menu, "ServerName" ), server.name ) // mode name/image - string mode = file.serversArrayFiltered[ serverIndex ].serverGamemode + string mode = server.playlist Hud_SetVisible( Hud_GetChild( menu, "NextModeIcon" ), true ) RuiSetImage( Hud_GetRui( Hud_GetChild( menu, "NextModeIcon" ) ), "basicImage", GetPlaylistThumbnailImage( mode ) ) Hud_SetVisible( Hud_GetChild( menu, "NextGameModeName" ), true ) if ( mode.len() != 0 ) - Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), mode ) + Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), GetGameModeDisplayName( mode ) ) else Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), "#NS_SERVERBROWSER_UNKNOWNMODE" ) } -string function FillInServerModsLabel( int server ) +string function FillInServerModsLabel( array<RequiredModInfo> mods ) { string ret - for ( int i = 0; i < NSGetServerRequiredModsCount( server ); i++ ) + foreach ( RequiredModInfo mod in mods ) { - ret += " " - ret += NSGetServerRequiredModName( server, i ) + " v" + NSGetServerRequiredModVersion( server, i ) + "\n" + ret += format( " %s v%s\n", mod.name, mod.version ) } + return ret } void function OnServerSelected( var button ) { + thread OnServerSelected_Threaded( button ) +} + +void function OnServerSelected_Threaded( var button ) +{ if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed ) return - int serverIndex = file.focusedServerIndex + ServerInfo server = file.focusedServer + file.lastSelectedServer = server + + // Count mods that have been successfully downloaded + bool autoDownloadAllowed = GetConVarBool( "allow_mod_auto_download" ) + int downloadedMods = 0; + + // Check out if there's any server-required mod that is not locally installed + array<string> modNames = NSGetModNames() + bool uninstalledModFound = false + foreach ( requiredModInfo in server.requiredMods ) + { + // Tolerate core mods having different versions + if ( requiredModInfo.name.len() > 10 && requiredModInfo.name.slice(0, 10) == "Northstar." ) + continue - file.lastSelectedServer = serverIndex + if ( !modNames.contains( requiredModInfo.name ) ) + { + print( format ( "\"%s\" was not found locally, triggering manifesto fetching.", requiredModInfo.name ) ) + uninstalledModFound = true + break + } else if ( NSGetModVersionByModName( requiredModInfo.name ) != requiredModInfo.version ) { + print( format ( "\"%s\" was found locally but has version \"%s\" while server requires \"%s\", triggering manifesto fetching.", requiredModInfo.name, NSGetModVersionByModName( requiredModInfo.name ), requiredModInfo.version ) ) + uninstalledModFound = true + break + } + } + + // If yes, we fetch the verified mods manifesto, to check whether uninstalled + // mods can be installed through auto-download + if ( uninstalledModFound && autoDownloadAllowed ) + { + print("Auto-download is allowed, checking if missing mods can be installed automatically.") + FetchVerifiedModsManifesto() + } - // check mods - for ( int i = 0; i < NSGetServerRequiredModsCount( serverIndex ); i++ ) + foreach ( RequiredModInfo mod in server.requiredMods ) { - if ( !NSGetModNames().contains( NSGetServerRequiredModName( serverIndex, i ) ) ) + // Tolerate core mods having different versions + if ( mod.name.len() > 10 && mod.name.slice(0, 10) == "Northstar." ) + continue + + if ( !NSGetModNames().contains( mod.name ) || NSGetModVersionByModName( mod.name ) != mod.version ) { - DialogData dialogData - dialogData.header = "#ERROR" - dialogData.message = "Missing mod \"" + NSGetServerRequiredModName( serverIndex, i ) + "\" v" + NSGetServerRequiredModVersion( serverIndex, i ) - dialogData.image = $"ui/menu/common/dialog_error" + // Auto-download mod + if ( autoDownloadAllowed ) + { + bool modIsVerified = NSIsModDownloadable( mod.name, mod.version ) - #if PC_PROG - AddDialogButton( dialogData, "#DISMISS" ) + // Display error message if mod is not verified + if ( !modIsVerified ) + { + DialogData dialogData + dialogData.header = "#ERROR" + dialogData.message = Localize( "#MISSING_MOD", mod.name, mod.version ) + dialogData.message += "\n" + Localize( "#MOD_NOT_VERIFIED" ) + dialogData.image = $"ui/menu/common/dialog_error" - AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) - #endif // PC_PROG - AddDialogFooter( dialogData, "#B_BUTTON_DISMISS_RUI" ) + AddDialogButton( dialogData, "#DISMISS" ) + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_DISMISS_RUI" ) + + OpenDialog( dialogData ) + return + } + else + { + if ( DownloadMod( mod ) ) + { + downloadedMods++ + } + else + { + DisplayModDownloadErrorDialog( mod.name ) + return + } + } + } + + // Mod not found, display error message + else + { + DialogData dialogData + dialogData.header = "#ERROR" + dialogData.message = Localize( "#MISSING_MOD", mod.name, mod.version ) + dialogData.image = $"ui/menu/common/dialog_error" - OpenDialog( dialogData ) + AddDialogButton( dialogData, "#DISMISS" ) + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_DISMISS_RUI" ) - return + OpenDialog( dialogData ) + return + } } else { // this uses semver https://semver.org - array<string> serverModVersion = split( NSGetServerRequiredModVersion( serverIndex, i ), "." ) - array<string> clientModVersion = split( NSGetModVersionByModName( NSGetServerRequiredModName( serverIndex, i ) ), "." ) + array<string> serverModVersion = split( mod.name, "." ) + array<string> clientModVersion = split( NSGetModVersionByModName( mod.name ), "." ) bool semverFail = false // if server has invalid semver don't bother checking @@ -1003,7 +1077,7 @@ void function OnServerSelected( var button ) { DialogData dialogData dialogData.header = "#ERROR" - dialogData.message = "Server has mod \"" + NSGetServerRequiredModName( serverIndex, i ) + "\" v" + NSGetServerRequiredModVersion( serverIndex, i ) + " while we have v" + NSGetModVersionByModName( NSGetServerRequiredModName( serverIndex, i ) ) + dialogData.message = Localize( "#WRONG_MOD_VERSION", mod.name, mod.version, NSGetModVersionByModName( mod.name ) ) dialogData.image = $"ui/menu/common/dialog_error" #if PC_PROG @@ -1020,24 +1094,25 @@ void function OnServerSelected( var button ) } } - if ( NSServerRequiresPassword( serverIndex ) ) + if ( server.requiresPassword ) { OnCloseServerBrowserMenu() AdvanceMenu( GetMenu( "ConnectWithPasswordMenu" ) ) } else - thread ThreadedAuthAndConnectToServer() + { + TriggerConnectToServerCallbacks() + thread ThreadedAuthAndConnectToServer( "", downloadedMods != 0 ) + } } -void function ThreadedAuthAndConnectToServer( string password = "" ) +void function ThreadedAuthAndConnectToServer( string password = "", bool modsChanged = false ) { if ( NSIsAuthenticatingWithServer() ) return - print( "trying to authenticate with server " + NSGetServerName( file.lastSelectedServer ) + " with password " + password ) - - NSTryAuthWithServer( file.lastSelectedServer, password ) + NSTryAuthWithServer( file.lastSelectedServer.index, password ) ToggleConnectingHUD( true ) @@ -1057,34 +1132,40 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) } file.cancelConnection = false - NSSetLoading( true ) - NSUpdateServerInfo( - NSGetServerID( file.lastSelectedServer ), - NSGetServerName( file.lastSelectedServer ), - password, - NSGetServerPlayerCount( file.lastSelectedServer ), - NSGetServerMaxPlayerCount( file.lastSelectedServer ), - NSGetServerMap( file.lastSelectedServer ), - Localize( GetMapDisplayName( NSGetServerMap( file.lastSelectedServer ) ) ), - NSGetServerPlaylist( file.lastSelectedServer ), - Localize( GetPlaylistDisplayName( NSGetServerPlaylist( file.lastSelectedServer ) ) ) - ) if ( NSWasAuthSuccessful() ) { - bool modsChanged - - array<string> requiredMods - for ( int i = 0; i < NSGetServerRequiredModsCount( file.lastSelectedServer ); i++ ) - requiredMods.append( NSGetServerRequiredModName( file.lastSelectedServer, i ) ) + // disable all RequiredOnClient mods that are not required by the server and are currently enabled + foreach ( string modName in NSGetModNames() ) + { + if ( NSIsModRequiredOnClient( modName ) && NSIsModEnabled( modName ) ) + { + // find the mod name in the list of server required mods + bool found = false + foreach ( RequiredModInfo mod in file.lastSelectedServer.requiredMods ) + { + if (mod.name == modName) + { + found = true + break + } + } + // if we didnt find the mod name, disable the mod + if (!found) + { + modsChanged = true + NSSetModEnabled( modName, false ) + } + } + } - // unload mods we don't need, load necessary ones and reload mods before connecting - foreach ( string mod in NSGetModNames() ) + // enable all RequiredOnClient mods that are required by the server and are currently disabled + foreach ( RequiredModInfo mod in file.lastSelectedServer.requiredMods ) { - if ( NSIsModRequiredOnClient( mod ) ) + if ( NSIsModRequiredOnClient( mod.name ) && !NSIsModEnabled( mod.name )) { - modsChanged = modsChanged || NSIsModEnabled( mod ) != requiredMods.contains( mod ) - NSSetModEnabled( mod, requiredMods.contains( mod ) ) + modsChanged = true + NSSetModEnabled( mod.name, true ) } } @@ -1096,9 +1177,11 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) } else { + string reason = NSGetAuthFailReason() + DialogData dialogData dialogData.header = "#ERROR" - dialogData.message = "Authentication Failed" + dialogData.message = reason dialogData.image = $"ui/menu/common/dialog_error" #if PC_PROG @@ -1115,7 +1198,7 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) ////////////////////////////////////// // Shadow realm ////////////////////////////////////// -int function ServerSortLogic ( serverStruct a, serverStruct b ) +int function ServerSortLogic ( ServerInfo a, ServerInfo b ) { var aTemp var bTemp @@ -1126,45 +1209,45 @@ int function ServerSortLogic ( serverStruct a, serverStruct b ) switch ( filterDirection.sortingBy ) { case sortingBy.DEFAULT: - aTemp = a.serverPlayers - bTemp = b.serverPlayers + aTemp = a.playerCount + bTemp = b.playerCount // `1000` is assumed to always be higher than `serverPlayersMax` - if (aTemp + 1 < a.serverPlayersMax) + if (aTemp + 1 < a.maxPlayerCount) aTemp = aTemp+2000 - if (bTemp + 1 < b.serverPlayersMax) + if (bTemp + 1 < b.maxPlayerCount) bTemp = bTemp+2000 - if (aTemp + 1 == a.serverPlayersMax) + if (aTemp + 1 == a.maxPlayerCount) aTemp = aTemp+1000 - if (bTemp + 1 == b.serverPlayersMax) + if (bTemp + 1 == b.maxPlayerCount) bTemp = bTemp+1000 direction = filterDirection.serverName break; case sortingBy.NAME: - aTemp = a.serverName.tolower() - bTemp = b.serverName.tolower() + aTemp = a.name.tolower() + bTemp = b.name.tolower() direction = filterDirection.serverName break; case sortingBy.PLAYERS: - aTemp = a.serverPlayers - bTemp = b.serverPlayers + aTemp = a.playerCount + bTemp = b.playerCount direction = filterDirection.serverPlayers break; case sortingBy.MAP: - aTemp = Localize( a.serverMap ).tolower() - bTemp = Localize( b.serverMap ).tolower() + aTemp = Localize( a.map ).tolower() + bTemp = Localize( b.map ).tolower() direction = filterDirection.serverMap break; case sortingBy.GAMEMODE: - aTemp = Localize( a.serverGamemode ).tolower() - bTemp = Localize( b.serverGamemode ).tolower() + aTemp = Localize( a.playlist ).tolower() + bTemp = Localize( b.playlist ).tolower() direction = filterDirection.serverGamemode break; - case sortingBy.LATENCY: - aTemp = a.serverLatency - bTemp = b.serverLatency - direction = filterDirection.serverLatency + case sortingBy.REGION: + aTemp = a.region + bTemp = b.region + direction = filterDirection.serverRegion break; default: return 0 @@ -1185,7 +1268,7 @@ void function SortServerListByDefault_Activate ( var button ) { filterDirection.sortingBy = sortingBy.DEFAULT - file.serversArrayFiltered.sort( ServerSortLogic ) + file.filteredServers.sort( ServerSortLogic ) filterDirection.serverName = !filterDirection.serverName @@ -1197,7 +1280,7 @@ void function SortServerListByName_Activate ( var button ) { filterDirection.sortingBy = sortingBy.NAME - file.serversArrayFiltered.sort( ServerSortLogic ) + file.filteredServers.sort( ServerSortLogic ) filterDirection.serverName = !filterDirection.serverName @@ -1209,7 +1292,7 @@ void function SortServerListByPlayers_Activate( var button ) { filterDirection.sortingBy = sortingBy.PLAYERS - file.serversArrayFiltered.sort( ServerSortLogic ) + file.filteredServers.sort( ServerSortLogic ) filterDirection.serverPlayers = !filterDirection.serverPlayers @@ -1220,7 +1303,7 @@ void function SortServerListByMap_Activate( var button ) { filterDirection.sortingBy = sortingBy.MAP - file.serversArrayFiltered.sort( ServerSortLogic ) + file.filteredServers.sort( ServerSortLogic ) filterDirection.serverMap = !filterDirection.serverMap @@ -1231,20 +1314,50 @@ void function SortServerListByGamemode_Activate( var button ) { filterDirection.sortingBy = sortingBy.GAMEMODE - file.serversArrayFiltered.sort( ServerSortLogic ) + file.filteredServers.sort( ServerSortLogic ) filterDirection.serverGamemode = !filterDirection.serverGamemode UpdateShownPage() } -void function SortServerListByLatency_Activate( var button ) +void function SortServerListByRegion_Activate( var button ) { - filterDirection.sortingBy = sortingBy.LATENCY + filterDirection.sortingBy = sortingBy.REGION - file.serversArrayFiltered.sort( ServerSortLogic ) + file.filteredServers.sort( ServerSortLogic ) - filterDirection.serverLatency = !filterDirection.serverLatency + filterDirection.serverRegion = !filterDirection.serverRegion UpdateShownPage() } + +////////////////////////////////////// +// Callbacks +////////////////////////////////////// + +void function AddConnectToServerCallback( void functionref( ServerInfo ) callback ) +{ + if ( file.connectCallbacks.find( callback ) >= 0 ) + throw "ConnectToServerCallback has been registered twice. Duplicate callbacks are not allowed." + file.connectCallbacks.append( callback ) +} + +void function RemoveConnectToServerCallback( void functionref( ServerInfo ) callback ) +{ + file.connectCallbacks.fastremovebyvalue( callback ) +} + +void function TriggerConnectToServerCallbacks( ServerInfo ornull targetServer = null ) +{ + ServerInfo server; + if (targetServer == null) + { + targetServer = file.lastSelectedServer + } + + foreach( callback in file.connectCallbacks ) + { + callback( expect ServerInfo( targetServer ) ) + } +} 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 00000000..f0139e04 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_pilot_loadouts_shared.nut @@ -0,0 +1,300 @@ + +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<var> 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 = GetItemImageFromWeaponRefAndPersistenceValue( loadout.primary, loadout.primarySkinIndex, "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 = GetItemImageFromWeaponRefAndPersistenceValue( loadout.secondary, loadout.secondarySkinIndex, "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 = GetItemImageFromWeaponRefAndPersistenceValue( loadout.weapon3, loadout.weapon3SkinIndex, "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<var> 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%" ) ) +} + +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 ) +} 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 d7c7442f..e3c1f268 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/ns_slider.nut b/Northstar.Client/mod/scripts/vscripts/ui/ns_slider.nut new file mode 100644 index 00000000..33a79cdc --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/ns_slider.nut @@ -0,0 +1,52 @@ +// ModSettings_Slider +// since we are missing some utility functions (e.g. GetMax, GetMin, SetValue), this is basically a collection of workarounds. +global struct MS_Slider +{ + var slider + float min = 0.0 + float max = 1.0 + float stepSize = 0.05 +} + +globalize_all_functions + +MS_Slider function MS_Slider_Setup( var slider, float min = 0.0, float max = 1.0, float startVal = 0.0, float stepSize = 0.05 ) +{ + MS_Slider result + result.slider = slider + result.min = min + result.max = max + result.stepSize = stepSize + Hud_SliderControl_SetMin( slider, startVal ) + Hud_SliderControl_SetMax( slider, startVal ) + Hud_SliderControl_SetStepSize( slider, stepSize ) + Hud_SliderControl_SetMin( slider, min ) + Hud_SliderControl_SetMax( slider, max ) + return result +} + +void function MS_Slider_SetValue( MS_Slider slider, float val ) +{ + Hud_SliderControl_SetMin( slider.slider, val ) + Hud_SliderControl_SetMax( slider.slider, val ) + Hud_SliderControl_SetMin( slider.slider, slider.min ) + Hud_SliderControl_SetMax( slider.slider, slider.max ) +} + +void function MS_Slider_SetMin( MS_Slider slider, float min ) +{ + slider.min = min + Hud_SliderControl_SetMin( slider.slider, min ) +} + +void function MS_Slider_SetMax( MS_Slider slider, float max ) +{ + slider.max = max + Hud_SliderControl_SetMax( slider.slider, max ) +} + +void function MS_Slider_SetStepSize( MS_Slider slider, float stepSize ) +{ + slider.stepSize = stepSize + Hud_SliderControl_SetStepSize( slider.slider, stepSize ) +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/openinvites.nut b/Northstar.Client/mod/scripts/vscripts/ui/openinvites.nut index 4b3d0f55..f91231b6 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 95b7bdae..2f1bcf02 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -81,8 +81,9 @@ void function InitMainMenuPanel() headerIndex++ buttonIndex = 0 var multiplayerHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MULTIPLAYER_ALLCAPS" ) - file.mpButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MULTIPLAYER_LAUNCH" ) - Hud_AddEventHandler( file.mpButton, UIE_CLICK, OnPlayMPButton_Activate ) + // "Launch Multiplayer" button removed because we don't support vanilla yet :clueless: + //file.mpButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MULTIPLAYER_LAUNCH" ) + //Hud_AddEventHandler( file.mpButton, UIE_CLICK, OnPlayMPButton_Activate ) file.fdButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_LAUNCH_NORTHSTAR" ) Hud_AddEventHandler( file.fdButton, UIE_CLICK, OnPlayFDButton_Activate ) Hud_SetLocked( file.fdButton, true ) @@ -101,6 +102,10 @@ void function InitMainMenuPanel() var videoButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#VIDEO" ) Hud_AddEventHandler( videoButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "VideoMenu" ) ) ) #endif + + // MOD SETTINGS + var modSettingsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MOD_SETTINGS" ) + Hud_AddEventHandler( modSettingsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ModSettings" ) ) ) var spotlightLargeButton = Hud_GetChild( file.spotlightPanel, "SpotlightLarge" ) spotlightLargeButton.SetNavLeft( file.spButtons[0] ) @@ -165,7 +170,8 @@ void function OnShowMainMenuPanel() #endif // PS4_PROG UpdateSPButtons() - thread UpdatePlayButton( file.mpButton ) + // dont try and update the launch multiplayer button, because it doesn't exist + //thread UpdatePlayButton( file.mpButton ) thread UpdatePlayButton( file.fdButton ) thread MonitorTrialVersionChange() @@ -455,7 +461,8 @@ void function UpdatePlayButton( var button ) message = "" } - ComboButton_SetText( file.mpButton, buttonText ) + // dont try and update the launch multiplayer button, because it doesn't exist + //ComboButton_SetText( file.mpButton, buttonText ) ComboButton_SetText( file.fdButton, "#MENU_LAUNCH_NORTHSTAR" ) //Hud_SetEnabled( file.fdButton, false ) @@ -527,7 +534,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() @@ -571,12 +577,12 @@ void function TryAuthWithLocalServer() { CloseAllDialogs() - var reason = NSGetAuthFailReason() + string reason = NSGetAuthFailReason() DialogData dialogData dialogData.image = $"ui/menu/common/dialog_error" dialogData.header = "#ERROR" - dialogData.message = Localize("#NS_SERVERBROWSER_CONNECTIONFAILED") + "\nERROR: " + reason + "\n" + Localize("#" + reason) + dialogData.message = reason AddDialogButton( dialogData, "#OK", null ) OpenDialog( dialogData ) @@ -597,7 +603,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.Client/mod/scripts/vscripts/ui/ui_mouse_capture.nut b/Northstar.Client/mod/scripts/vscripts/ui/ui_mouse_capture.nut new file mode 100644 index 00000000..fa5c9217 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/ui_mouse_capture.nut @@ -0,0 +1,60 @@ +untyped // untyped purely so I can index into a table with var + +global function AddMouseMovementCaptureHandler +global function UICodeCallback_MouseMovementCapture + +struct +{ + // a table of capturePanels and menus, each of which contains an array of callbacks + table< var, array< void functionref( int deltaX, int deltaY ) > > mouseMovementCaptureCallbacks = {} +} file + +// this function registers a callback (or "handler") function for a MouseMovementCapture menu panel +// use this for scrollbars, sliders, etc. +void function AddMouseMovementCaptureHandler( var capturePanelOrMenu, void functionref( int deltaX, int deltaY ) func ) +{ + // if the capturePanel or menu already has an array in the table, we append to the array + // if not, we should create the array, [func] just turns func into an array + if ( capturePanelOrMenu in file.mouseMovementCaptureCallbacks ) + file.mouseMovementCaptureCallbacks[capturePanelOrMenu].append( func ) + else + file.mouseMovementCaptureCallbacks[capturePanelOrMenu] <- [func] +} + +void function RunMouseMovementCallbacks( var capturePanelOrMenu, int deltaX, int deltaY ) +{ + // check that the capturePanelOrMenu is in the table before trying anything stupid + if ( capturePanelOrMenu in file.mouseMovementCaptureCallbacks ) + { + // iterate through the different callback functions + foreach ( void functionref( int deltaX, int deltaY ) callback in file.mouseMovementCaptureCallbacks[capturePanelOrMenu] ) + { + // run the callback function + callback( deltaX, deltaY ) + } + } +} + +void function UICodeCallback_MouseMovementCapture( var capturePanel, int deltaX, int deltaY ) +{ + // run callbacks for the capturePanel + RunMouseMovementCallbacks( capturePanel, deltaX, deltaY ) + + // get the current menu and run callbacks, this preserves backwards compatibility + RunMouseMovementCallbacks( GetActiveMenu(), deltaX, deltaY ) + + // everything below here originally existed in vanilla sh_menu_models.gnut and is meant to be used for like all of their rotation stuff + // its easier to move this here than to add a shared callback for all of the vanilla capture handlers (there are like >20) + + // this const was moved instead of made global because it was literally only used in the code below + const MOUSE_ROTATE_MULTIPLIER = 25.0 + + float screenScaleXModifier = 1920.0 / GetScreenSize()[0] // 1920 is base screen width + float mouseXRotateDelta = deltaX * screenScaleXModifier * MOUSE_ROTATE_MULTIPLIER + //printt( "deltaX:", deltaX, "screenScaleModifier:", screenScaleModifier, "mouseRotateDelta:", mouseRotateDelta ) + + float screenScaleYModifier = 1080.0 / GetScreenSize()[1] // 1080 is base screen height + float mouseYRotationDelta = deltaY * screenScaleYModifier * MOUSE_ROTATE_MULTIPLIER + + RunMenuClientFunction( "UpdateMouseRotateDelta", mouseXRotateDelta, mouseYRotationDelta ) +} |