Bläddra i källkod

Merging latest dev and resolving conflic inside README.md

Signed-off-by: Gene Walters <[email protected]>
Gene Walters 2 år sedan
förälder
incheckning
f58ce49879
88 ändrade filer med 2639 tillägg och 791 borttagningar
  1. 3 0
      .github/dco.yml
  2. 20 0
      Documentation/GamplayConfiguration.md
  3. BIN
      Documentation/Media/2305_screenshot.png
  4. BIN
      Documentation/Media/wwise_installer_options.png
  5. BIN
      Documentation/Media/wwise_installer_version_selection.png
  6. 123 0
      Documentation/PackedAssetBuilds.md
  7. 29 0
      Documentation/ReleaseNotes.md
  8. 47 0
      Documentation/SettingsScreen.md
  9. 3 0
      Fonts/Anton/Anton-Regular.font
  10. 3 0
      Fonts/Anton/Anton-Regular.ttf
  11. 93 0
      Fonts/Anton/OFL.txt
  12. 1 0
      Fonts/Roboto/NOTICE.txt
  13. 3 0
      Fonts/Roboto/Roboto-Black.ttf
  14. 3 0
      Fonts/Roboto/Roboto-BlackItalic.ttf
  15. 3 0
      Fonts/Roboto/Roboto-Bold.ttf
  16. 3 0
      Fonts/Roboto/Roboto-BoldCondensed.ttf
  17. 3 0
      Fonts/Roboto/Roboto-BoldCondensedItalic.ttf
  18. 3 0
      Fonts/Roboto/Roboto-BoldItalic.ttf
  19. 3 0
      Fonts/Roboto/Roboto-Condensed.ttf
  20. 3 0
      Fonts/Roboto/Roboto-CondensedItalic.ttf
  21. 3 0
      Fonts/Roboto/Roboto-Italic.ttf
  22. 3 0
      Fonts/Roboto/Roboto-Light.ttf
  23. 3 0
      Fonts/Roboto/Roboto-LightItalic.ttf
  24. 3 0
      Fonts/Roboto/Roboto-Medium.ttf
  25. 3 0
      Fonts/Roboto/Roboto-MediumItalic.ttf
  26. 3 0
      Fonts/Roboto/Roboto-Regular.font
  27. 3 0
      Fonts/Roboto/Roboto-Regular.ttf
  28. 3 0
      Fonts/Roboto/Roboto-Thin.ttf
  29. 3 0
      Fonts/Roboto/Roboto-ThinItalic.ttf
  30. 3 5
      Gem/Code/Source/AutoGen/EnergyBallComponent.AutoComponent.xml
  31. 110 0
      Gem/Code/Source/Components/BackgroundMusicComponent.cpp
  32. 42 0
      Gem/Code/Source/Components/BackgroundMusicComponent.h
  33. 112 18
      Gem/Code/Source/Components/Multiplayer/EnergyBallComponent.cpp
  34. 15 1
      Gem/Code/Source/Components/Multiplayer/EnergyBallComponent.h
  35. 214 119
      Gem/Code/Source/Components/UI/UiSettingsComponent.cpp
  36. 26 22
      Gem/Code/Source/Components/UI/UiSettingsComponent.h
  37. 63 17
      Gem/Code/Source/Effects/GameEffect.cpp
  38. 18 9
      Gem/Code/Source/MultiplayerSampleModule.cpp
  39. 313 0
      Gem/Code/Source/UserSettings/MultiplayerSampleUserSettings.cpp
  40. 109 0
      Gem/Code/Source/UserSettings/MultiplayerSampleUserSettings.h
  41. 3 0
      Gem/Code/multiplayersample_files.cmake
  42. 3 0
      Gem/Code/multiplayersample_shared_files.cmake
  43. 22 67
      Levels/GameplayTest/GameplayTest.prefab
  44. 52 9
      Levels/NewStarbase/NewStarbase.prefab
  45. 2 2
      MPSGameLift/UICanvases/GameLiftConnectJson/QuitButton.png
  46. 2 2
      MPSGameLift/UICanvases/GameLiftConnectJson/QuitButtonDown.png
  47. 2 2
      MPSGameLift/UICanvases/GameLiftConnectJson/QuitButtonHover.png
  48. 41 13
      README.md
  49. 1 1
      Registry/multiplayersample.setreg
  50. 6 7
      Registry/settings.multiplayersample_gamelauncher.setreg
  51. 6 7
      Registry/settings.multiplayersample_unifiedlauncher.setreg
  52. 3 0
      Sounds/wwise/1070395499.wem
  53. 3 0
      Sounds/wwise/1073420800.wem
  54. 3 0
      Sounds/wwise/115250578.wem
  55. 3 0
      Sounds/wwise/655023540.wem
  56. 2 2
      Sounds/wwise/MultiplayerSample_SoundBank.bnk
  57. 192 0
      Sounds/wwise_project/Actor-Mixer Hierarchy/AMPS/LVL.wwu
  58. 14 0
      Sounds/wwise_project/Actor-Mixer Hierarchy/AMPS/MX.wwu
  59. 63 3
      Sounds/wwise_project/Events/AMPS/AMB.wwu
  60. 11 1
      Sounds/wwise_project/Events/Default O3DE Work Unit.wwu
  61. 3 0
      Sounds/wwise_project/Originals/SFX/Beauty Flow.wav
  62. 3 0
      Sounds/wwise_project/Originals/SFX/Future Gladiator.wav
  63. 3 0
      Sounds/wwise_project/Originals/SFX/Rocket.wav
  64. 3 0
      Sounds/wwise_project/Originals/SFX/incompetech/Dream Catcher.wav
  65. 12 0
      Sounds/wwise_project/Soundcaster Sessions/Default Work Unit.wwu
  66. 34 34
      UICanvases/BasicHUD.uicanvas
  67. 2 2
      UICanvases/InGameMenu/QuitButton.png
  68. 3 0
      UICanvases/InGameMenu/QuitButtonDown.png
  69. 2 2
      UICanvases/InGameMenu/QuitButtonHover.png
  70. 58 52
      UICanvases/Lobby.uicanvas
  71. 2 2
      UICanvases/Scoreboard/QuitButton.png
  72. 3 0
      UICanvases/Scoreboard/QuitButtonDown.png
  73. 2 2
      UICanvases/Scoreboard/QuitButtonHover.png
  74. 57 35
      UICanvases/Settings.uicanvas
  75. 312 272
      UICanvases/StartMenu.uicanvas
  76. 2 2
      UICanvases/StartMenu/HostGameButton.png
  77. 2 2
      UICanvases/StartMenu/HostGameButtonDown.png
  78. 2 2
      UICanvases/StartMenu/HostGameButtonHover.png
  79. 2 2
      UICanvases/StartMenu/IPWindow.png
  80. 2 2
      UICanvases/StartMenu/JoinGameButton.png
  81. 2 2
      UICanvases/StartMenu/JoinGameButtonDown.png
  82. 2 2
      UICanvases/StartMenu/JoinGameButtonHover.png
  83. 2 2
      UICanvases/StartMenu/QuitButton.png
  84. 2 2
      UICanvases/StartMenu/QuitButtonDown.png
  85. 2 2
      UICanvases/StartMenu/QuitButtonHover.png
  86. 40 0
      credits.md
  87. 9 0
      libs/gameaudio/wwise/multiplayersample_controls.xml
  88. 239 63
      scriptcanvas/ClientDisconnect.scriptcanvas

+ 3 - 0
.github/dco.yml

@@ -0,0 +1,3 @@
+allowRemediationCommits:
+  individual: true
+  thirdParty: true

+ 20 - 0
Documentation/GamplayConfiguration.md

@@ -37,6 +37,26 @@ Gem Spawn Points should be created wherever you want a gem to appear in the leve
 -   **Tag** - Here you will enter the tags that correspond with the gems you want to spawn in this location. Entry [0] should be the Gem Spawn tag (set above in the Gem Spawn Tables Per Round component). Additional entries correspond with the gem(s) type you want to spawn in this location. You can add more than one gem type here. When this happens, the Gem Weight will influence which gem spawns each time. e.g. If you add yellow and green gems and give each a weight of 1, there will be an even chance of either to spawn. If one is set to greater than 1, that gem is more likely to spawn.
 -   **Script Canvas & Mesh & Material components** - By default, gem spawn points have no visual indicator in the editor as gems only appear in those positions when the game is running. To allow you to visualize gem spawn points in the editor we add the mesh component and assign the gem model and a material that matches the gem that will appear in game. Then, when the game starts, we hide the placeholder gem models using the script canvas component
 
+## Tunable Registry Settings
+
+The file `Registry\multiplayersample.setreg` contains a number of tunable settings:
+
+```
+	"MultiplayerSample": {
+		"Settings": {
+			"WinningCoinCount": 400,              # Condition to win the game early
+			"EnergyBall": {                       # Controls the impact of the energy balls
+				"KnockbackDistanceMeters": 2.0,
+				"Speed": 15.0,
+				"ArmorDamage": 10
+			},
+			"EnergyCannon": {                     # Controls for energy cannons
+				"FiringPeriodMilliseconds": 2000
+			}
+```
+
+> Some of the code still references `coins` as an early build used coin pickups rather than gems.
+
 ## **Setting Up Teleporters**
 
 Teleporters are another new feature introduced in the MPS. These can be setup to teleport players anywhere in the level when they pass through the teleport volume.

BIN
Documentation/Media/2305_screenshot.png


BIN
Documentation/Media/wwise_installer_options.png


BIN
Documentation/Media/wwise_installer_version_selection.png


+ 123 - 0
Documentation/PackedAssetBuilds.md

@@ -0,0 +1,123 @@
+# Packaged MultiplayerSample Builds
+To make relocatable client and server builds for the MultiplayerSample, we recommend making packaged builds. These package builds will contain the Game or Server Launcher and the bundled assets needed to run the launcher outside of the developer environment.
+
+You can make both release packaged builds or profile packaged builds. For more information about creating release builds, see the O3DE documentation on [Creating a Project Game Release Layout for Windows](https://www.o3de.org/docs/user-guide/packaging/windows-release-builds/).
+
+The guide below covers how to make profile packaged builds which are very useful for early sharing and play testing.
+
+## Windows Profile PAK Setup
+
+### Install WWise
+Go to https://www.audiokinetic.com/download/, create a login, log in, and download the installer. WWise is needed to process and package audio assets in the project.
+
+![WWise installer options](Media/wwise_installer_options.png)
+
+Inside the installer select the version to use.  Install version **2021.1.11.7933**, select both Authoring and SDK, Microsoft platform.
+
+![WWise version selection](Media/wwise_installer_version_selection.png)
+
+> REBOOT (or logout / login). Otherwise, the environment settings won't get picked up for any builds in Visual Studio. They will only apply to command-line builds, and only for any command-line windows that have been opened after the installer finishes.
+
+### Build profile build and process assets
+
+Build and run MPS as per the [README.md](../README.md) and ensure all assets are built.
+
+### Test the profile build
+
+* Open the game in editor
+    * load `NewStarBase` level
+    * Verify that game can launch and connect to local server from editor
+* Validate local game launcher can connect to local server
+
+### Build AssetBuilder
+
+You will need to build the [AssetBundler](https://www.o3de.org/docs/user-guide/packaging/asset-bundler/overview/) tool if not built.
+
+For example:
+```shell
+cmake --build build\windows --target AssetBundler --config profile -- /m /nologo
+```
+
+### Build monolithic game
+
+Build a second version of the executables as monolithic pak builds.
+
+``` shell
+# Create build files for a monolithic build that also disables all user/project registry settings overrides
+cmake -B build\windows_mono -S . -G "Visual Studio 16" -DLY_3RDPARTY_PATH=c:\your\path\to\3rdParty -DLY_MONOLITHIC_GAME=1 -DALLOW_SETTINGS_REGISTRY_DEVELOPMENT_OVERRIDES=0
+
+# Build the profile versions of all the executables
+cmake --build build\windows_mono --target MultiplayerSample.GameLauncher MultiplayerSample.ServerLauncher MultiplayerSample.UnifiedLauncher --config profile -- /m /nologo
+```
+
+The outputs in windows_mono\bin\profile can be copied and run anywhere, once the pak files are put in the proper location.
+
+
+### Bundle Content
+
+Run the AssetBundler
+
+```
+build\windows\bin\profile\AssetBundler.exe --project-path="c:\your\path\to\o3de-multiplayersample"
+```
+
+Follow steps for "Create a bundle for game assets", "Create a bundle for engine assets" and "Add bundles to the release game layout" from https://www.o3de.org/docs/user-guide/packaging/asset-bundler/bundle-assets-for-release/
+
+* The "default seed lists" choice should choose all but 4 seed lists to make the `engine_pc.pak`
+* The other [seed lists](https://github.com/o3de/o3de-multiplayersample/tree/development/AssetBundling/SeedLists) should all get selected to make the `game_pc.pak`.
+
+> It's important to make sure that the bootstrap.game.profile.setreg file has been added to one of the seed files. (also add debug if you want to support debug builds)
+
+### Create the Launcher Zip file
+
+Use the following .bat file or equivalent copy steps to create a directory with the launchers in it:
+```shell
+rem Use this by calling 'make_release D:\my\output\dir' to make a release directory
+mkdir %1
+mkdir %1\Cache
+mkdir %1\Cache\pc
+mkdir %1\Gems
+mkdir %1\Gems\AWSCore
+ 
+rem Copy the pak files
+copy c:\your\path\to\o3de-multiplayersample\AssetBundling\Bundles\*.pak %1\Cache\pc
+ 
+rem Copy the executables and DLLs
+copy c:\your\path\to\o3de-multiplayersample\build\windows_mono\bin\profile\*.* %1
+ 
+rem Copy the AWSCore files
+copy c:\your\path\to\o3de-multiplayersample\build\windows_mono\bin\profile\Gems\AWSCore\*.* %1\Gems\AWSCore
+ 
+rem Copy the launch_client / launch_server files
+copy c:\your\path\to\o3de-multiplayersample\launch_*.* %1
+ 
+rem Copy the PIX DLLs if PIX is enabled in the build
+:: copy c:\your\path\to\3rdParty\WinPixEventRuntime\bin\x64 %1
+```
+
+Note: The script above will copy everything from the profile directory. You can either remove files you don't require such as .pdb files to save space, or modify the script to copy just whats needed.
+
+It's recommended during testing that you include source information for your build, such as the commit IDs for o3de, o3de-multiplayersample, and o3de-multiplayersample-assets.
+You can add this as .txt file in the build folder.
+
+Zip up the directory before running it to make sure the zip is "pure" without any logs or artifacts.
+
+### Run the final build to verify it
+
+```shell
+MultiplayerSample.ServerLauncher.exe --console-command-file=launch_server.cfg --rhi=null -NullRenderer -bg_ConnectToAssetProcessor=0 -sys_PakPriority=2 -sv_terminateOnPlayerExit=false
+MultiplayerSample.GameLauncher.exe --console-command-file=launch_client.cfg -bg_ConnectToAssetProcessor=0 -sys_PakPriority=2
+```
+
+After running, check the output logs to verify there aren't any crashes, missing assets, etc. If any assets are missing, go back to the AssetBundler step, add the assets, and repeat.
+
+## Linux profile packaged builds
+
+Instructions for Linux are similar to Windows instructions above. All examples are Ubuntu 22.04 which is the primary Linux platform for O3DE. See https://www.o3de.org/docs/welcome-guide/requirements/ for more details.
+
+## Install WWise
+See instructions above but install Wwise for Linux Ubuntu
+
+### Build profile build and process assets
+
+Build and run MPS as per the [README_LINUX.md](../README_LINUX.md) and ensure all assets are built.

+ 29 - 0
Documentation/ReleaseNotes.md

@@ -0,0 +1,29 @@
+# Release Notes for MultiplayerSample
+
+## O3DE 2305 Release
+
+![2305 Screenshot](Media/2305_screenshot.png)
+
+2305 is the base version of the game. It is expected to be functional and support up to 10 players. 
+
+### Testing Notes
+
+| Platform         | In Editor    | Profile PAKs | Release + PAKs |
+|------------------|--------------|--------------|----------------|
+| Windows          | yes - stable | yes - stable | no             |
+| Ubuntu           | yes -stable  | no           | no             |
+| Mobile Platforms | n/a          | no           | no             |
+
+MPS was tested using both LAN hosted servers and using AWS EC2 for remote server testing.
+
+### Known Issues
+
+There are some notable known issues:
+
+* On Linux there's a problem with some actor motionsets appearing to have root motion applied: https://github.com/o3de/o3de-multiplayersample/issues/315
+* For the ServerLauncher there are serialization warnings in the log relating to PopcornFX which are harmless, as PopcornFX is ignored on the Server by design.
+* The game has fixed support for 10 players: https://github.com/o3de/o3de-multiplayersample/issues/351. More than 10 players can join the server, but they will not be able to play the game (nor show correctly in UX).
+* Opening ImGUI can block player input: https://github.com/o3de/o3de-multiplayersample/issues/353
+
+For the complete and up-to-date list of issues, please see [MPS issues](https://github.com/o3de/o3de-multiplayersample/issues?q=is%3Aissue+is%3Aopen+label%3Akind%2Fbug) and [MPS SampleAssets issue](https://github.com/o3de/o3de-multiplayersample-assets/issues).
+

+ 47 - 0
Documentation/SettingsScreen.md

@@ -0,0 +1,47 @@
+# Settings screen
+
+The settings screen contains a set of controls for modifying various options in O3DE. This screen demonstrates how to expose settings from O3DE to the user and how to persist those settings to a file. 
+
+## User settings
+### Graphics api
+
+O3DE supports running with multiple different graphics APIs, depending on the platform. The full set of APIs currently supported are the following:
+
+* "null" - A null renderer, nothing is drawn to the screen
+* "dx12" - The DirectX 12 API (Windows only)
+* "vulkan" - The Vulkan API (all platforms)
+* "metal" - The Metal API (iOS / Mac platforms only)
+
+The different APIs use different OS-level and driver-level code, which can result in performance differences based on a user's specific operating system, graphics card, and graphics drivers.
+
+Normally the API is selected through a command-line argument, such as `-rhi="null"`. The setting on the settings screen provides the ability to specify the default API to use on subsequent runs of the launcher.
+
+The implementation of this setting is more complex than the other settings due to how early the setting needs to be applied. The user setting needs to be read in after enough of the engine has been initialized to be able to load in settings from project-specific code, but before the renderer itself has been initialized; the API choice cannot be changed once the renderer is initialized. This timing occurs during the construction of the project's Module class. This setting is implemented by modifying a settings registry key that controls what priority the renderer should use to select an API.
+
+### Texture quality
+
+The Texture Quality setting controls the "mip bias", which is the highest mip level to load for each streamed texture. A value of `0` is the highest-resolution mipmap, `1` is the second-highest mipmap, and so on. This value exposes the tradeoff between quality and memory - the highest-resolution textures look the best but use the most VRAM. The user can choose to lower the quality and lower the VRAM usage, which can help with performance.
+
+In O3DE, the mip bias is exposed through a [CVAR](https://www.o3de.org/docs/user-guide/appendix/cvars/), a settings registry key, and an API. The settings screen uses the API to directly modify the setting.
+
+### Audio volume
+
+The Audio Volume setting controls the master volume for the entire audio system, from `0` (min) to `100` (max). The audio system has data-driven volume channels; each project's audio setup may have a different set of more granular volume controls, such as for music, sound effects, voice, and ambient noise. This setting implements a master volume control, but any of the more granular controls would be implemented in a similar way.
+
+Volume controls for the audio system are exposed through an API, and not through any CVAR or settings registry keys. The settings screen uses the API directly to modify the value.
+
+### Fullscreen
+
+The Fullscreen setting controls whether the launcher is running in a window on the desktop or in fullscreen mode.
+
+The fullscreen/windowed mode selection is controlled by the `r_fullscreen` CVAR. The settings screen demonstrates how to set the cvar from a user setting.
+
+## Modifying and extending the settings screen
+
+See the following source files for the settings screen implementation:
+* [https://github.com/o3de/o3de-multiplayersample/blob/development/Gem/Code/Source/UserSettings/MultiplayerSampleUserSettings.cpp](https://github.com/o3de/o3de-multiplayersample/blob/development/Gem/Code/Source/UserSettings/MultiplayerSampleUserSettings.cpp)
+* [https://github.com/o3de/o3de-multiplayersample/blob/development/Gem/Code/Source/Components/UI/UiSettingsComponent.cpp](https://github.com/o3de/o3de-multiplayersample/blob/development/Gem/Code/Source/Components/UI/UiSettingsComponent.cpp)
+
+The `MultiplayerSampleUserSettings.cpp` file contains the backend logic for loading and saving the user settings and applying the settings to the engine. The default values for each setting can be found here as well. More settings could be exposed and implemented here.
+
+The `UiSettingsComponent.cpp` file contains the UX logic for turning the setting values into user-friendly names and toggle controls. The names and specific choices of which values to expose can be found here. For example, the Master Volume control exposes the volume in increments of 10, but it could be modified to expose more volume values to increment it by 5 or by 1. Similarly, the Graphics API control could be modified to only expose APIs that exist for that platform.

+ 3 - 0
Fonts/Anton/Anton-Regular.font

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ac071ff50bcefdee49315d3e585f7b38215bc8031321e1925c500464c6cd2921
+size 271

+ 3 - 0
Fonts/Anton/Anton-Regular.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:28beb8f6542f642ba4143bd4a1d1cfc7be7b1dedc951096efd8e0942502ea1bf
+size 161588

+ 93 - 0
Fonts/Anton/OFL.txt

@@ -0,0 +1,93 @@
+Copyright 2020 The Anton Project Authors (https://github.com/googlefonts/AntonFont.git)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded, 
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.

+ 1 - 0
Fonts/Roboto/NOTICE.txt

@@ -0,0 +1 @@
+You may use the materials in this file without restriction to develop your apps and to use in your apps.

+ 3 - 0
Fonts/Roboto/Roboto-Black.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c78ce438e9d91ea8c16341aaf2c6cf07f9c347eb1130bd922796ad4fb78fe885
+size 164936

+ 3 - 0
Fonts/Roboto/Roboto-BlackItalic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5e7928c14bbddea37ec9ba2453f00bd8f4d73c42c20528e42abc5b89d2732db1
+size 166320

+ 3 - 0
Fonts/Roboto/Roboto-Bold.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:24571503140760240924dcd1238f77e7cd0454c0d8b0793990cefa2fad71471f
+size 163448

+ 3 - 0
Fonts/Roboto/Roboto-BoldCondensed.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2c9245c0246a9c745793c7eaa9cc1fc964a12570009031ea0223115bec6e9426
+size 161308

+ 3 - 0
Fonts/Roboto/Roboto-BoldCondensedItalic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1117eab9f490123cf8a656fa936a4c9a7e4918b88ae576d64d3d79507096f7b9
+size 163584

+ 3 - 0
Fonts/Roboto/Roboto-BoldItalic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:165a6d02fd8973703787feeef5319b7fd8cb3f665a3c1e702ef0ca49701547c9
+size 165864

+ 3 - 0
Fonts/Roboto/Roboto-Condensed.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2efe5301b93d1e4aa90fed89f766a88be1b80be64873f853c1b6e089cab19fea
+size 158284

+ 3 - 0
Fonts/Roboto/Roboto-CondensedItalic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c2d5ec131c1a767138d09f77383b4bf68051c02164dd83e4b6c58feb25c473ed
+size 161792

+ 3 - 0
Fonts/Roboto/Roboto-Italic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:470123c6fb5d6c0005431c0f5390742497c55087361a7636b7e82eb35635ded7
+size 160736

+ 3 - 0
Fonts/Roboto/Roboto-Light.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:94df4e4976db8ddaec27f8e8c33eef912e744fb200ca09051794b38e5a502fc0
+size 162636

+ 3 - 0
Fonts/Roboto/Roboto-LightItalic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:709ab3c8feaa5640b3a14493e1c2d27509df5aa5d14b8b86bd431ab60ac53a69
+size 163248

+ 3 - 0
Fonts/Roboto/Roboto-Medium.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:02868d6a7e80d4e7836b6263dd50d26a63e923a1223c9e027aad6dc2501c27cc
+size 160696

+ 3 - 0
Fonts/Roboto/Roboto-MediumItalic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:27f4345bc02f3cdec1522bfeae70aced6bdf217d40878108cfe2baa535d04fa4
+size 163940

+ 3 - 0
Fonts/Roboto/Roboto-Regular.font

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b34c757371cfa3d19dedde1ce1db5fafe0928e07453562e803f51190dcbc0d13
+size 272

+ 3 - 0
Fonts/Roboto/Roboto-Regular.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:16466ef65064e6f3885a6d2806b8949ac1ac38b524dd0cf8fc96565eb4cc28e8
+size 158604

+ 3 - 0
Fonts/Roboto/Roboto-Thin.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2843669daf030733f6b7c541a98ebbff5ce5c2d8cbae423bd8d278a36e169399
+size 122512

+ 3 - 0
Fonts/Roboto/Roboto-ThinItalic.ttf

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:55031ef14f6c49947255ab6e0ef7112938cb1ecb903f85553ddc7842422a5841
+size 125884

+ 3 - 5
Gem/Code/Source/AutoGen/EnergyBallComponent.AutoComponent.xml

@@ -17,7 +17,9 @@
     <ArchetypeProperty Type="GatherParams" Name="GatherParams" Init="" ExposeToEditor="true" Description="Specifies the types of intersections to test for on the projectile" />
     <ArchetypeProperty Type="HitEffect" Name="HitEffect" Init="" ExposeToEditor="true" Description="Specifies the damage effects to apply on hit" />
 
-    <RemoteProcedure Name="RPC_LaunchBall" InvokeFrom="Server" HandleOn="Authority" IsPublic="true" IsReliable="true" GenerateEventBindings="true" Description="Launching an energy from a specified position in a specified direction.">
+    <NetworkProperty Type="bool" Name="BallActive" Init="false" ReplicateFrom="Authority" ReplicateTo="Client" Container="Object" IsPublic="true" IsRewindable="true" IsPredictable="false" ExposeToScript="false" ExposeToEditor="false" GenerateEventBindings="true" Description="Track whether or not the energy ball is currently active" />
+
+  <RemoteProcedure Name="RPC_LaunchBall" InvokeFrom="Server" HandleOn="Authority" IsPublic="true" IsReliable="true" GenerateEventBindings="true" Description="Launch an energy ball from a specified position in a specified direction.">
         <Param Type="AZ::Vector3" Name="StartingPosition"/>
         <Param Type="AZ::Vector3" Name="Direction"/>
         <Param Type="Multiplayer::NetEntityId" Name="OwningNetEntityId" />
@@ -25,10 +27,6 @@
 
     <RemoteProcedure Name="RPC_KillBall" InvokeFrom="Server" HandleOn="Authority" IsPublic="true" IsReliable="true" GenerateEventBindings="true" Description="Kills a launched energy ball." />
 
-    <RemoteProcedure Name="RPC_BallLaunched" InvokeFrom="Authority" HandleOn="Client" IsPublic="true" IsReliable="true" GenerateEventBindings="true" Description="Triggered on clients whenever an energy ball launches.">
-        <Param Type="AZ::Vector3" Name="Location"/>
-    </RemoteProcedure>
-
     <RemoteProcedure Name="RPC_BallExplosion" InvokeFrom="Authority" HandleOn="Client" IsPublic="true" IsReliable="true" GenerateEventBindings="true" Description="Triggered on clients whenever an energy ball explodes.">
         <Param Type="HitEvent" Name="HitEvent"/>
     </RemoteProcedure>

+ 110 - 0
Gem/Code/Source/Components/BackgroundMusicComponent.cpp

@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <Source/Components/BackgroundMusicComponent.h>
+#include <AzCore/Serialization/EditContext.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <LmbrCentral/Audio/AudioProxyComponentBus.h>
+#include <AzCore/Console/ILogger.h>
+
+namespace MultiplayerSample
+{
+    void BackgroundMusicComponent::Reflect(AZ::ReflectContext* context)
+    {
+        AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
+        if (serializeContext)
+        {
+            serializeContext->Class<BackgroundMusicComponent, AZ::Component>()
+                ->Field("Shuffle", &BackgroundMusicComponent::m_shuffle)
+                ->Field("Playlist", &BackgroundMusicComponent::m_playlist)
+                ->Version(1);
+
+            AZ::EditContext* editContext = serializeContext->GetEditContext();
+            if (editContext)
+            {
+                editContext->Class<BackgroundMusicComponent>("BackgroundMusicComponent", "Plays a sequence of background music tracks in sequence")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                    ->Attribute(AZ::Edit::Attributes::Category, "MultiplayerSample")
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &BackgroundMusicComponent::m_shuffle, "Shuffle", "If true, the playlist will be shuffled and play in a randomized ordering")
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &BackgroundMusicComponent::m_playlist, "Playlist", "The set of background music audio triggers to play");
+            }
+        }
+    }
+
+    void BackgroundMusicComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
+    {
+        services.push_back(AZ_CRC_CE("BackgroundMusicComponent"));
+    }
+
+    void BackgroundMusicComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
+    {
+        required.push_back(AZ_CRC("AudioProxyService", 0x7da4c79c));
+    }
+
+    void BackgroundMusicComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
+    {
+        services.push_back(AZ_CRC_CE("BackgroundMusicComponent"));
+    }
+
+    void BackgroundMusicComponent::Activate()
+    {
+#if AZ_TRAIT_CLIENT
+        m_audioSystem = AZ::Interface<Audio::IAudioSystem>::Get();
+
+        if (m_shuffle)
+        {
+            // Basic Knuth shuffle
+            for (size_t index = m_playlist.size() - 1; index >= 1; --index)
+            {
+                size_t shuffleElement = rand() % (index + 1);
+                AZStd::swap(m_playlist[index], m_playlist[shuffleElement]);
+            }
+        }
+
+        if (m_audioSystem != nullptr)
+        {
+            m_trackIndex = size_t(-1);
+            ReportTriggerFinished(INVALID_AUDIO_CONTROL_ID);
+        }
+#endif
+
+        Audio::AudioTriggerNotificationBus::Handler::BusConnect(Audio::TriggerNotificationIdType{ GetEntityId() });
+    }
+
+    void BackgroundMusicComponent::Deactivate()
+    {
+        Audio::AudioTriggerNotificationBus::Handler::BusDisconnect(Audio::TriggerNotificationIdType{ GetEntityId() });
+    }
+
+    void BackgroundMusicComponent::ReportTriggerFinished([[maybe_unused]] Audio::TAudioControlID triggerId)
+    {
+        if (m_playlist.empty())
+        {
+            return;
+        }
+
+#if AZ_TRAIT_CLIENT
+        m_trackIndex = ++m_trackIndex % m_playlist.size();
+
+        if (m_audioSystem != nullptr)
+        {
+            const AZStd::string& trackName = m_playlist[m_trackIndex];
+            m_currentTrackTriggerId = m_audioSystem->GetAudioTriggerID(trackName.c_str());
+
+            if (m_currentTrackTriggerId != INVALID_AUDIO_CONTROL_ID)
+            {
+                LmbrCentral::AudioProxyComponentRequestBus::Event(
+                    GetEntityId(),
+                    &LmbrCentral::AudioProxyComponentRequests::ExecuteTrigger,
+                    m_currentTrackTriggerId);
+            }
+        }
+#endif
+    }
+}

+ 42 - 0
Gem/Code/Source/Components/BackgroundMusicComponent.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <IAudioSystem.h>
+
+namespace MultiplayerSample
+{
+    class BackgroundMusicComponent
+        : public AZ::Component
+        , protected Audio::AudioTriggerNotificationBus::Handler
+    {
+    public:
+        AZ_COMPONENT(MultiplayerSample::BackgroundMusicComponent, "{FA774915-3CDD-4370-B7C9-8F891A006973}");
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
+        static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services);
+
+        void Activate() override;
+        void Deactivate() override;
+
+    protected:
+        void ReportTriggerFinished(Audio::TAudioControlID triggerId) override;
+
+    private:
+        size_t m_trackIndex = 0;
+        bool m_shuffle = false;
+        AZStd::vector<AZStd::string> m_playlist;
+        Audio::IAudioSystem* m_audioSystem = nullptr;
+        Audio::TATLIDType m_currentTrackTriggerId = INVALID_AUDIO_CONTROL_ID;
+    };
+}

+ 112 - 18
Gem/Code/Source/Components/Multiplayer/EnergyBallComponent.cpp

@@ -11,16 +11,19 @@
 #include <Multiplayer/Components/NetworkRigidBodyComponent.h>
 #include <MultiplayerSampleTypes.h>
 #include <AzCore/Component/TransformBus.h>
+#include <AzFramework/Physics/Components/SimulatedBodyComponentBus.h>
 #include <AzFramework/Physics/RigidBodyBus.h>
 #include <WeaponNotificationBus.h>
 
 #if AZ_TRAIT_CLIENT
 #   include <PopcornFX/PopcornFXBus.h>
+#   include <DebugDraw/DebugDrawBus.h>
 #endif
 
 namespace MultiplayerSample
 {
     AZ_CVAR(float, sv_EnergyBallImpulseScalar, 500.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "A fudge factor for imparting impulses on rigid bodies due to weapon hits");
+    AZ_CVAR(bool, cl_EnergyBallDebugDraw, false, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "When turned on this will draw the current energy ball location");
 
     void EnergyBallComponent::Reflect(AZ::ReflectContext* context)
     {
@@ -37,27 +40,62 @@ namespace MultiplayerSample
     {
         m_effect = GetExplosionEffect();
         m_effect.Initialize();
+
+#if AZ_TRAIT_CLIENT
+        BallActiveAddEvent(m_ballActiveHandler);
+#endif
     }
 
     void EnergyBallComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
     {
+#if AZ_TRAIT_CLIENT
+        m_ballActiveHandler.Disconnect();
+#endif
     }
 
 #if AZ_TRAIT_CLIENT
-    void EnergyBallComponent::HandleRPC_BallLaunched([[maybe_unused]] AzNetworking::IConnection* invokingConnection, [[maybe_unused]] const AZ::Vector3& location)
+    void EnergyBallComponent::OnBallActiveChanged(bool active)
     {
-        PopcornFX::PopcornFXEmitterComponentRequests* emitterRequests = PopcornFX::PopcornFXEmitterComponentRequestBus::FindFirstHandler(GetEntity()->GetId());
-        if (emitterRequests != nullptr)
+        if (active)
+        {
+            bool startSuccess = false;
+
+            // Set to true to call "Kill" which is deferred, or false to call "Terminate" which is immediate.
+            constexpr bool KillOnRestart = true;
+
+            PopcornFX::PopcornFXEmitterComponentRequestBus::EventResult(startSuccess,
+                GetEntity()->GetId(), &PopcornFX::PopcornFXEmitterComponentRequestBus::Events::Restart, KillOnRestart);
+
+            AZ_Error("EnergyBall", startSuccess, "Restart call for Energy Ball was unsuccessful.");
+
+            if (cl_EnergyBallDebugDraw)
+            {
+                m_debugDrawEvent.Enqueue(AZ::TimeMs{ 0 }, true);
+            }
+        }
+        else
         {
-            emitterRequests->Start();
+            bool killSuccess = false;
+
+            // This would ideally use Kill instead of Terminate, but there is a bug in PopcornFX 2.15.4 that if Kill is
+            // called on the first tick (which can happen), then the effect will get stuck in a permanent waiting-to-die state,
+            // and no amount of Restart calls will ever make it show up again.
+            PopcornFX::PopcornFXEmitterComponentRequestBus::EventResult(killSuccess,
+                GetEntity()->GetId(), &PopcornFX::PopcornFXEmitterComponentRequestBus::Events::Terminate);
+
+            AZ_Error("EnergyBall", killSuccess, "Kill call for Energy Ball was unsuccessful.");
+
+            m_debugDrawEvent.RemoveFromQueue();
         }
     }
 
     void EnergyBallComponent::HandleRPC_BallExplosion([[maybe_unused]] AzNetworking::IConnection* invokingConnection, const HitEvent& hitEvent)
     {
+        // Crate an explosion effect wherever the ball was last at.
         AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateIdentity(), hitEvent.m_target);
         m_effect.TriggerEffect(transform);
 
+        // Notify every entity that was hit that they've received a weapon impact.
         for (const HitEntity& hitEntity : hitEvent.m_hitEntities)
         {
             const AZ::Transform hitTransform = AZ::Transform::CreateLookAt(hitEntity.m_hitPosition, hitEntity.m_hitPosition + hitEntity.m_hitNormal, AZ::Transform::Axis::ZPositive);
@@ -65,11 +103,49 @@ namespace MultiplayerSample
             const AZ::EntityId hitEntityId = handle.Exists() ? handle.GetEntity()->GetId() : AZ::EntityId();
             WeaponNotificationBus::Broadcast(&WeaponNotificationBus::Events::OnWeaponImpact, GetEntity()->GetId(), hitTransform, hitEntityId);
         }
+    }
 
-        PopcornFX::PopcornFXEmitterComponentRequests* emitterRequests = PopcornFX::PopcornFXEmitterComponentRequestBus::FindFirstHandler(GetEntity()->GetId());
-        if (emitterRequests != nullptr)
+    void EnergyBallComponent::DebugDraw()
+    {
+        if (cl_EnergyBallDebugDraw)
         {
-            emitterRequests->Kill();
+            // Each draw only lasts one frame.
+            constexpr float DrawDuration = 0.0f;
+
+            auto* shapeConfig = GetGatherParams().GetCurrentShapeConfiguration();
+            if (shapeConfig->GetShapeType() == Physics::ShapeType::Sphere)
+            {
+                const Physics::SphereShapeConfiguration* sphere = static_cast<const Physics::SphereShapeConfiguration*>(shapeConfig);
+                float debugRadius = sphere->m_radius;
+
+                DebugDraw::DebugDrawRequestBus::Broadcast(
+                    &DebugDraw::DebugDrawRequestBus::Events::DrawSphereAtLocation,
+                    GetEntity()->GetTransform()->GetWorldTM().GetTranslation(),
+                    debugRadius,
+                    AZ::Colors::Green,
+                    DrawDuration
+                );
+            }
+            else if (shapeConfig->GetShapeType() == Physics::ShapeType::Box)
+            {
+                const Physics::BoxShapeConfiguration* box = static_cast<const Physics::BoxShapeConfiguration*>(shapeConfig);
+                AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(
+                    GetEntity()->GetTransform()->GetWorldTM().GetTranslation(),
+                    GetEntity()->GetTransform()->GetWorldTM().GetRotation(),
+                    box->m_dimensions / 2.0f
+                );
+
+                DebugDraw::DebugDrawRequestBus::Broadcast(
+                    &DebugDraw::DebugDrawRequestBus::Events::DrawObb,
+                    obb,
+                    AZ::Colors::Green,
+                    DrawDuration
+                );
+            }
+            else if (shapeConfig->GetShapeType() == Physics::ShapeType::Capsule)
+            {
+                AZ_Error("EnergyBall", false, "Capsule shape type not currently supported with energy ball debug visualization.");
+            }
         }
     }
 #endif
@@ -83,20 +159,29 @@ namespace MultiplayerSample
     void EnergyBallComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
     {
 #if AZ_TRAIT_SERVER
-        m_collisionCheckEvent.Enqueue(AZ::TimeMs{ 10 }, true);
+        SetBallActive(false);
 #endif
     }
 
     void EnergyBallComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
     {
 #if AZ_TRAIT_SERVER
-        m_collisionCheckEvent.RemoveFromQueue();
+        SetBallActive(false);
 #endif
     }
 
 #if AZ_TRAIT_SERVER
-    void EnergyBallComponentController::HandleRPC_LaunchBall([[maybe_unused]] AzNetworking::IConnection* invokingConnection, const AZ::Vector3& startingPosition, const AZ::Vector3& direction, const Multiplayer::NetEntityId& owningNetEntityId)
+    void EnergyBallComponentController::HandleRPC_LaunchBall(AzNetworking::IConnection* invokingConnection, const AZ::Vector3& startingPosition, const AZ::Vector3& direction, const Multiplayer::NetEntityId& owningNetEntityId)
     {
+        if (GetBallActive())
+        {
+            return;
+        }
+
+        m_collisionCheckEvent.Enqueue(AZ::TimeMs{ 10 }, true);
+
+        SetBallActive(true);
+
         m_shooterNetEntityId = owningNetEntityId;
         m_hitEvent.m_hitEntities.clear();
 
@@ -106,15 +191,14 @@ namespace MultiplayerSample
         m_direction = direction;
 
         // Move the entity to the start position
-        GetEntity()->GetTransform()->SetWorldTranslation(startingPosition);
+        GetNetworkTransformComponentController()->HandleMultiplayerTeleport(invokingConnection, startingPosition);
 
         // We want to sweep our transform during intersect tests to avoid the ball tunneling through targets
         m_lastSweepTransform = GetEntity()->GetTransform()->GetWorldTM();
 
-        Physics::RigidBodyRequestBus::Event(GetEntityId(), &Physics::RigidBodyRequestBus::Events::EnablePhysics);
+        AzPhysics::SimulatedBodyComponentRequestsBus::Event(GetEntityId(), &AzPhysics::SimulatedBodyComponentRequestsBus::Events::EnablePhysics);
         Physics::RigidBodyRequestBus::Event(GetEntityId(), &Physics::RigidBodyRequestBus::Events::SetLinearVelocity, direction * GetGatherParams().m_travelSpeed);
 
-        RPC_BallLaunched(startingPosition);
     }
 
     void EnergyBallComponentController::HandleRPC_KillBall([[maybe_unused]] AzNetworking::IConnection* invokingConnection)
@@ -124,6 +208,11 @@ namespace MultiplayerSample
 
     void EnergyBallComponentController::CheckForCollisions()
     {
+        if (!GetBallActive())
+        {
+            return;
+        }
+
         const AZ::Vector3& position = GetEntity()->GetTransform()->GetWorldTM().GetTranslation();
         const HitEffect& effect = GetHitEffect();
 
@@ -174,17 +263,22 @@ namespace MultiplayerSample
 
     void EnergyBallComponentController::HideEnergyBall()
     {
+        if (!GetBallActive())
+        {
+            return;
+        }
+
+        SetBallActive(false);
+        m_collisionCheckEvent.RemoveFromQueue();
+
         m_hitEvent.m_target = GetEntity()->GetTransform()->GetWorldTM().GetTranslation();
         m_hitEvent.m_shooterNetEntityId = m_shooterNetEntityId;
         m_hitEvent.m_projectileNetEntityId = GetNetEntityId();
-        RPC_BallExplosion(m_hitEvent);
 
-        Physics::RigidBodyRequestBus::Event(GetEntityId(), &Physics::RigidBodyRequestBus::Events::DisablePhysics);
+        AzPhysics::SimulatedBodyComponentRequestsBus::Event(GetEntityId(), &AzPhysics::SimulatedBodyComponentRequestsBus::Events::DisablePhysics);
         Physics::RigidBodyRequestBus::Event(GetEntityId(), &Physics::RigidBodyRequestBus::Events::SetLinearVelocity, AZ::Vector3::CreateZero());
 
-        // move self and increment resetCount to prevent transform interpolation
-        AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3::CreateAxisZ(-1000.f));
-        GetNetworkTransformComponentController()->ModifyResetCount()++;
+        RPC_BallExplosion(m_hitEvent);
     }
 #endif
 }

+ 15 - 1
Gem/Code/Source/Components/Multiplayer/EnergyBallComponent.h

@@ -24,11 +24,25 @@ namespace MultiplayerSample
         void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
 
 #if AZ_TRAIT_CLIENT
-        void HandleRPC_BallLaunched(AzNetworking::IConnection* invokingConnection, const AZ::Vector3& location) override;
         void HandleRPC_BallExplosion(AzNetworking::IConnection* invokingConnection, const HitEvent& hitEvent) override;
 #endif
 
     private:
+#if AZ_TRAIT_CLIENT
+        void DebugDraw();
+        void OnBallActiveChanged(bool active);
+
+        AZ::ScheduledEvent m_debugDrawEvent{ [this]()
+        {
+            DebugDraw();
+        }, AZ::Name("EnergyBallDebugDraw") };
+
+        AZ::Event<bool>::Handler m_ballActiveHandler{ [this](bool active)
+        {
+            OnBallActiveChanged(active);
+        } };
+#endif
+
         GameEffect m_effect;
     };
 

+ 214 - 119
Gem/Code/Source/Components/UI/UiSettingsComponent.cpp

@@ -6,30 +6,16 @@
  */
 
 #include <Atom/RHI/Factory.h>
-#include <AzCore/Console/IConsole.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Serialization/EditContext.h>
-#include <IAudioSystem.h>
 #include <LyShine/Bus/UiButtonBus.h>
 #include <LyShine/Bus/UiElementBus.h>
 #include <LyShine/Bus/UiTextBus.h>
 #include <Source/Components/UI/UiSettingsComponent.h>
+#include <Source/UserSettings/MultiplayerSampleUserSettings.h>
 
 namespace MultiplayerSample
 {
-    void MpsSettings::Reflect(AZ::ReflectContext* context)
-    {
-        if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
-        {
-            serializeContext->Class<MpsSettings>()
-                ->Version(0)
-                ->Field("GraphicsApi", &MpsSettings::m_atomApiType)
-                ->Field("MasterVolume", &MpsSettings::m_masterVolume)
-                ->Field("TextureQuality", &MpsSettings::m_streamingImageMipBias)
-                ;
-        }
-    }
-
     void UiToggle::Reflect(AZ::ReflectContext* context)
     {
         if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
@@ -41,7 +27,6 @@ namespace MultiplayerSample
                 ->Field("RightButton", &UiToggle::m_rightButtonEntity)
                 ;
 
-
             if (AZ::EditContext* editContext = serializeContext->GetEditContext())
             {
                 editContext->Class<UiToggle>("Ui Toggle", "Manages the user settings")
@@ -56,7 +41,6 @@ namespace MultiplayerSample
 
     void UiSettingsComponent::Reflect(AZ::ReflectContext* context)
     {
-        MpsSettings::Reflect(context);
         UiToggle::Reflect(context);
 
         if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
@@ -66,6 +50,8 @@ namespace MultiplayerSample
                 ->Field("GraphicsApi", &UiSettingsComponent::m_graphicsApiToggle)
                 ->Field("TextureQuality", &UiSettingsComponent::m_textureQualityToggle)
                 ->Field("MasterVolume", &UiSettingsComponent::m_masterVolumeToggle)
+                ->Field("Fullscreen", &UiSettingsComponent::m_fullscreenToggle)
+                ->Field("Resolution", &UiSettingsComponent::m_resolutionToggle)
                 ;
 
             if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -76,155 +62,264 @@ namespace MultiplayerSample
                     ->DataElement(AZ::Edit::UIHandlers::Default, &UiSettingsComponent::m_graphicsApiToggle, "Graphics Api", "The Graphics Api toggle elements.")
                     ->DataElement(AZ::Edit::UIHandlers::Default, &UiSettingsComponent::m_textureQualityToggle, "Texture Quality", "The Texture Quality toggle elements.")
                     ->DataElement(AZ::Edit::UIHandlers::Default, &UiSettingsComponent::m_masterVolumeToggle, "Master Volume", "The Master Volume toggle elements.")
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &UiSettingsComponent::m_fullscreenToggle, "Fullscreen", "The Fullscreen toggle elements.")
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &UiSettingsComponent::m_resolutionToggle, "Resolution", "The Resolution toggle elements.")
                     ;
             }
         }
     }
 
-    void UiSettingsComponent::Activate()
+    AzFramework::NativeWindowHandle UiSettingsComponent::GetWindowHandle()
     {
-        // Initialize our user settings 
+        AzFramework::NativeWindowHandle windowHandle = nullptr;
+        AzFramework::WindowSystemRequestBus::BroadcastResult(
+            windowHandle,
+            &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
 
-        // Initialize the current streaming image mip bias setting.
-        if (AZ::IConsole* console = AZ::Interface<AZ::IConsole>::Get(); console)
-        {
-            int16_t mipBias = 0;
-            console->GetCvarValue("r_streamingImageMipBias", mipBias);
-            m_settings.m_streamingImageMipBias = aznumeric_cast<uint8_t>(mipBias);
-        }
+        return windowHandle;
+    }
 
-        // Initialize the graphics API type
-        m_settings.m_atomApiType = AZ::RHI::Factory::Get().GetAPIUniqueIndex();
+    void UiSettingsComponent::Activate()
+    {
+        // Listen for window notifications so that we can detect fullscreen/windowed changes.
+        AzFramework::WindowNotificationBus::Handler::BusConnect(GetWindowHandle());
 
-        // There's currently no way to initialize the master volume, this doesn't seem to be fetchable anywhere.
+        // Loads and applies the current user settings when this component activates.
+        // The user settings should *already* be loaded and applied at Launcher startup, but connecting to the server
+        // and switching levels can cause some engine settings to reset themselves, so this will reapply the desired
+        // user settings again.
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(&MultiplayerSampleUserSettingsRequestBus::Events::Load);
 
         // Initialize the toggles to the current values
-        OnGraphicsApiToggle(ToggleDirection::None);
-        OnTextureQualityToggle(ToggleDirection::None);
-        OnMasterVolumeToggle(ToggleDirection::None);
-
-        // Start listening for button presses
-        UiButtonBus::Event(m_graphicsApiToggle.m_leftButtonEntity, &UiButtonInterface::SetOnClickCallback,
-            [this]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position) 
-            { 
-                OnGraphicsApiToggle(ToggleDirection::Left); 
-            });
-        UiButtonBus::Event(m_graphicsApiToggle.m_rightButtonEntity, &UiButtonInterface::SetOnClickCallback,
-            [this]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position)
-            {
-                OnGraphicsApiToggle(ToggleDirection::Right);
-            });
-        UiButtonBus::Event(m_textureQualityToggle.m_leftButtonEntity, &UiButtonInterface::SetOnClickCallback,
-            [this]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position)
-            {
-                OnTextureQualityToggle(ToggleDirection::Left);
-            });
-        UiButtonBus::Event(m_textureQualityToggle.m_rightButtonEntity, &UiButtonInterface::SetOnClickCallback,
-            [this]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position)
-            {
-                OnTextureQualityToggle(ToggleDirection::Right);
-            });
-        UiButtonBus::Event(m_masterVolumeToggle.m_leftButtonEntity, &UiButtonInterface::SetOnClickCallback,
-            [this]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position)
+        InitializeToggle(m_graphicsApiToggle, OnGraphicsApiToggle);
+        InitializeToggle(m_textureQualityToggle, OnTextureQualityToggle);
+        InitializeToggle(m_masterVolumeToggle, OnMasterVolumeToggle);
+        InitializeToggle(m_fullscreenToggle, OnFullscreenToggle);
+        InitializeToggle(m_resolutionToggle, OnResolutionToggle);
+    }
+
+    void UiSettingsComponent::Deactivate()
+    {
+        AzFramework::WindowNotificationBus::Handler::BusDisconnect();
+    }
+
+    void UiSettingsComponent::InitializeToggle(UiToggle& toggle, AZStd::function<void(UiToggle&, ToggleDirection)> toggleUpdateFn)
+    {
+        toggleUpdateFn(toggle, ToggleDirection::None);
+
+        UiButtonBus::Event(toggle.m_leftButtonEntity, &UiButtonInterface::SetOnClickCallback,
+            [&toggle, toggleUpdateFn]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position)
             {
-                OnMasterVolumeToggle(ToggleDirection::Left);
+                toggleUpdateFn(toggle, ToggleDirection::Left);
             });
-        UiButtonBus::Event(m_masterVolumeToggle.m_rightButtonEntity, &UiButtonInterface::SetOnClickCallback,
-            [this]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position)
+        UiButtonBus::Event(toggle.m_rightButtonEntity, &UiButtonInterface::SetOnClickCallback,
+            [&toggle, toggleUpdateFn]([[maybe_unused]] AZ::EntityId buttonEntityId, [[maybe_unused]] AZ::Vector2 position)
             {
-                OnMasterVolumeToggle(ToggleDirection::Right);
+                toggleUpdateFn(toggle, ToggleDirection::Right);
             });
     }
 
-    void UiSettingsComponent::Deactivate()
+    template<typename ValueType>
+    uint32_t UiSettingsComponent::GetRotatedIndex(
+        const AZStd::vector<AZStd::pair<ValueType, AZStd::string>>& valuesToLabels,
+        const ValueType& value, ToggleDirection toggleDirection)
     {
+        const size_t totalValues = valuesToLabels.size();
+
+        uint32_t curIndex = 0;
+
+        // Loop through and look for the correct value
+        for (size_t index = 0; index < totalValues; index++)
+        {
+            if (value == valuesToLabels[index].first)
+            {
+                curIndex = aznumeric_cast<uint32_t>(index);
+                break;
+            }
+        }
+
+        switch (toggleDirection)
+        {
+        case ToggleDirection::Left:
+            return aznumeric_cast<uint32_t>((curIndex + (totalValues - 1)) % totalValues);
+        case ToggleDirection::Right:
+            return aznumeric_cast<uint32_t>((curIndex + 1) % totalValues);
+        default:
+            return curIndex;
+        }
     }
 
-    void UiSettingsComponent::OnGraphicsApiToggle(ToggleDirection toggleDirection)
+    void UiSettingsComponent::OnGraphicsApiToggle(UiToggle& toggle, ToggleDirection toggleDirection)
     {
         // This list is expected to match the values in AZ::RHI::ApiIndex.
-        const char* labels[] =
+        const AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>> valuesToLabels =
         {
-            "Null",
-            "DirectX 12",
-            "Vulkan",
-            "Metal"
+            { "null", "Null" },
+            { "dx12", "DirectX 12" },
+            { "vulkan", "Vulkan" },
+            { "metal", "Metal" }
         };
 
-        const size_t NumLabels = AZ_ARRAY_SIZE(labels);
+        // Get the current api selection.
+        AZStd::string graphicsApi;
+        MultiplayerSampleUserSettingsRequestBus::BroadcastResult(
+            graphicsApi, &MultiplayerSampleUserSettingsRequestBus::Events::GetGraphicsApi);
 
-        if (toggleDirection != ToggleDirection::None)
+        // If there isn't anything stored in the user settings yet, default to the currently-loaded api.
+        if (graphicsApi.empty())
         {
-            m_settings.m_atomApiType = (toggleDirection == ToggleDirection::Right)
-                ? (m_settings.m_atomApiType + 1) % NumLabels
-                : (m_settings.m_atomApiType + (NumLabels - 1)) % NumLabels
-                ;
+            graphicsApi = AZ::RHI::Factory::Get().GetName().GetStringView();
         }
 
-        UiTextBus::Event(m_graphicsApiToggle.m_labelEntity, &UiTextInterface::SetText, labels[m_settings.m_atomApiType]);
+        // Rotate the index based on toggle direction.
+        uint32_t graphicsApiIndex = GetRotatedIndex(valuesToLabels, graphicsApi, toggleDirection);
+
+        UiTextBus::Event(toggle.m_labelEntity, &UiTextInterface::SetText, valuesToLabels[graphicsApiIndex].second);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(
+            &MultiplayerSampleUserSettingsRequestBus::Events::SetGraphicsApi, valuesToLabels[graphicsApiIndex].first);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(&MultiplayerSampleUserSettingsRequestBus::Events::Save);
     }
 
-    void UiSettingsComponent::OnTextureQualityToggle(ToggleDirection toggleDirection)
+    void UiSettingsComponent::OnTextureQualityToggle(UiToggle& toggle, ToggleDirection toggleDirection)
     {
-        const char* labels[] =
+        const AZStd::vector<AZStd::pair<int16_t, AZStd::string>> valuesToLabels =
         {
-            "Ultra (4K)",
-            "High (2K)",
-            "Medium (1K)",
-            "Low (512)",
-            "Very Low (256)",
-            "Extremely Low (128)",
-            "Rock Bottom (64)"
+            { aznumeric_cast<int16_t>(6), "Rock Bottom (64)" },
+            { aznumeric_cast<int16_t>(5), "Extremely Low (128)" },
+            { aznumeric_cast<int16_t>(4), "Very Low (256)" },
+            { aznumeric_cast<int16_t>(3), "Low (512)" },
+            { aznumeric_cast<int16_t>(2), "Medium (1K)" },
+            { aznumeric_cast<int16_t>(1), "High (2K)" },
+            { aznumeric_cast<int16_t>(0), "Ultra (4K)" },
         };
 
-        const size_t NumLabels = AZ_ARRAY_SIZE(labels);
+        // Get the current texture quality value.
+        int16_t textureQuality = 0;
+        MultiplayerSampleUserSettingsRequestBus::BroadcastResult(
+            textureQuality, &MultiplayerSampleUserSettingsRequestBus::Events::GetTextureQuality);
 
-        if (toggleDirection != ToggleDirection::None)
-        {
-            // As we go from left to right on our settings, we want our textureQuality number to go from 6 down to 0
-            // because smaller mip bias numbers mean higher-resolution textures.
-            m_settings.m_streamingImageMipBias = (toggleDirection == ToggleDirection::Right)
-                ? (m_settings.m_streamingImageMipBias + (NumLabels - 1)) % NumLabels
-                : (m_settings.m_streamingImageMipBias + 1) % NumLabels
-                ;
-        }
+        // Rotate the index based on toggle direction.
+        uint32_t textureQualityIndex = GetRotatedIndex(valuesToLabels, textureQuality, toggleDirection);
+
+        UiTextBus::Event(toggle.m_labelEntity, &UiTextInterface::SetText, valuesToLabels[textureQualityIndex].second);
 
-        AZ::IConsole* console = AZ::Interface<AZ::IConsole>::Get();
-        if (console)
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(
+            &MultiplayerSampleUserSettingsRequestBus::Events::SetTextureQuality, valuesToLabels[textureQualityIndex].first);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(&MultiplayerSampleUserSettingsRequestBus::Events::Save);
+    }
+
+    void UiSettingsComponent::OnMasterVolumeToggle(UiToggle& toggle, ToggleDirection toggleDirection)
+    {
+        const AZStd::vector<AZStd::pair<uint8_t, AZStd::string>> valuesToLabels =
         {
-            AZ::CVarFixedString commandString = AZ::CVarFixedString::format("r_streamingImageMipBias %" PRId16, m_settings.m_streamingImageMipBias);
-            console->PerformCommand(commandString.c_str());
-        }
+            { aznumeric_cast<uint8_t>(0), "0 (off)" },
+            { aznumeric_cast<uint8_t>(10), "10" },
+            { aznumeric_cast<uint8_t>(20), "20" },
+            { aznumeric_cast<uint8_t>(30), "30" },
+            { aznumeric_cast<uint8_t>(40), "40" },
+            { aznumeric_cast<uint8_t>(50), "50" },
+            { aznumeric_cast<uint8_t>(60), "60" },
+            { aznumeric_cast<uint8_t>(70), "70" },
+            { aznumeric_cast<uint8_t>(80), "80" },
+            { aznumeric_cast<uint8_t>(90), "90" },
+            { aznumeric_cast<uint8_t>(100), "100 (max)" },
+        };
+
+        // Get the current master volume value.
+        uint8_t masterVolume = 0;
+        MultiplayerSampleUserSettingsRequestBus::BroadcastResult(
+            masterVolume, &MultiplayerSampleUserSettingsRequestBus::Events::GetMasterVolume);
+
+        // Make sure our master volume is a multiple of 10.
+        masterVolume = (masterVolume / 10) * 10;
+
+        // Rotate the index based on toggle direction.
+        uint32_t masterVolumeIndex = GetRotatedIndex(valuesToLabels, masterVolume, toggleDirection);
+
+        UiTextBus::Event(toggle.m_labelEntity, &UiTextInterface::SetText, valuesToLabels[masterVolumeIndex].second);
 
-        UiTextBus::Event(m_textureQualityToggle.m_labelEntity, &UiTextInterface::SetText, labels[m_settings.m_streamingImageMipBias]);
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(
+            &MultiplayerSampleUserSettingsRequestBus::Events::SetMasterVolume, valuesToLabels[masterVolumeIndex].first);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(&MultiplayerSampleUserSettingsRequestBus::Events::Save);
     }
 
-    void UiSettingsComponent::OnMasterVolumeToggle(ToggleDirection toggleDirection)
+    void UiSettingsComponent::OnFullscreenToggle(UiToggle& toggle, ToggleDirection toggleDirection)
     {
-        if (toggleDirection != ToggleDirection::None)
+        const AZStd::vector<AZStd::pair<bool, AZStd::string>> valuesToLabels =
         {
-            m_settings.m_masterVolume = (toggleDirection == ToggleDirection::Right)
-                ? (m_settings.m_masterVolume + 10) % 110
-                : (m_settings.m_masterVolume + 100) % 110
-                ;
-        }
+            { false, "Windowed" },
+            { true, "Fullscreen" },
+        };
+
+        // Get the current fullscreen state. Unlike the other settings, we'll get this from the current window state so that we
+        // handle things like Alt-enter that can change our windowing state regardless of what our user settings thinks.
 
-        auto audioSystem = AZ::Interface<Audio::IAudioSystem>::Get();
-        if (audioSystem)
+        // Start by defaulting to the user setting.
+        bool fullscreen = false;
+        MultiplayerSampleUserSettingsRequestBus::BroadcastResult(
+            fullscreen, &MultiplayerSampleUserSettingsRequestBus::Events::GetFullscreen);
+
+        // Next, try to get the current state from the window. If it fails to get the state, we'll auto-default to the
+        // user setting value that we fetched above.
+        AzFramework::WindowRequestBus::EventResult(fullscreen,
+            GetWindowHandle(), &AzFramework::WindowRequestBus::Events::GetFullScreenState);
+
+        // Rotate the index based on toggle direction.
+        uint32_t fullscreenIndex = GetRotatedIndex(valuesToLabels, fullscreen, toggleDirection);
+
+        UiTextBus::Event(toggle.m_labelEntity, &UiTextInterface::SetText, valuesToLabels[fullscreenIndex].second);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(
+            &MultiplayerSampleUserSettingsRequestBus::Events::SetFullscreen, valuesToLabels[fullscreenIndex].first);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(&MultiplayerSampleUserSettingsRequestBus::Events::Save);
+    }
+
+    void UiSettingsComponent::OnResolutionToggle(UiToggle& toggle, ToggleDirection toggleDirection)
+    {
+        const AZStd::vector<AZStd::pair<AZStd::pair<uint32_t, uint32_t>, AZStd::string>> valuesToLabels =
         {
-            Audio::TAudioObjectID rtpcId = audioSystem->GetAudioRtpcID("Volume_Master");
+            { {1280, 720}, "1280 x 720" },
+            { {1920, 1080}, "1920 x 1080" },
+            { {1920, 1200}, "1920 x 1200" },
+            { {2560, 1440}, "2560 x 1440" },
+            { {2560, 1600}, "2560 x 1600" },
+            { {3840, 2160}, "3840 x 2160" },
+            { {3840, 2400}, "3840 x 2400" },
+        };
 
-            if (rtpcId != INVALID_AUDIO_CONTROL_ID)
-            {
-                Audio::ObjectRequest::SetParameterValue setParameter;
-                setParameter.m_audioObjectId = INVALID_AUDIO_OBJECT_ID;
-                setParameter.m_parameterId = rtpcId;
-                setParameter.m_value = m_settings.m_masterVolume / 100.0f;
-                AZ::Interface<Audio::IAudioSystem>::Get()->PushRequest(AZStd::move(setParameter));
-            }
-        }
+        // Get the current resolution value.
+        AZStd::pair<uint32_t, uint32_t> resolution = { 1920, 1080 };
+        MultiplayerSampleUserSettingsRequestBus::BroadcastResult(
+            resolution, &MultiplayerSampleUserSettingsRequestBus::Events::GetResolution);
+
+        // Rotate the index based on toggle direction.
+        uint32_t resolutionIndex = GetRotatedIndex(valuesToLabels, resolution, toggleDirection);
+
+        UiTextBus::Event(toggle.m_labelEntity, &UiTextInterface::SetText, valuesToLabels[resolutionIndex].second);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(
+            &MultiplayerSampleUserSettingsRequestBus::Events::SetResolution, valuesToLabels[resolutionIndex].first);
+
+        MultiplayerSampleUserSettingsRequestBus::Broadcast(&MultiplayerSampleUserSettingsRequestBus::Events::Save);
+    }
 
-        UiTextBus::Event(m_masterVolumeToggle.m_labelEntity, &UiTextInterface::SetText, AZStd::string::format("%d", m_settings.m_masterVolume));
+    void UiSettingsComponent::OnWindowResized([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
+    {
+        // Refresh the windowed / fullscreen setting. There is no direct notification for fullscreen changes,
+        // so we detect it indirectly by listening for OnWindowResized and OnRefreshRateChanged messages.
+        OnFullscreenToggle(m_fullscreenToggle, ToggleDirection::None);
+    }
+
+    void UiSettingsComponent::OnRefreshRateChanged([[maybe_unused]] uint32_t refreshRate)
+    {
+        // Refresh the windowed / fullscreen setting. There is no direct notification for fullscreen changes,
+        // so we detect it indirectly by listening for OnWindowResized and OnRefreshRateChanged messages.
+        OnFullscreenToggle(m_fullscreenToggle, ToggleDirection::None);
     }
 
 }

+ 26 - 22
Gem/Code/Source/Components/UI/UiSettingsComponent.h

@@ -9,26 +9,10 @@
 
 
 #include <AzCore/Component/Component.h>
+#include <AzFramework/Windowing/WindowBus.h>
 
 namespace MultiplayerSample
 {
-    //! These are all of the user settings that MPS supports.
-    struct MpsSettings
-    {
-        AZ_TYPE_INFO(MpsSettings, "{1E545ABF-6650-41D8-AC69-9C50BB5561F0}");
-        static void Reflect(AZ::ReflectContext* context);
-
-        //! The API type that Atom should use at startup. (This value comes from AZ::RHI::APIIndex)
-        uint32_t m_atomApiType = 0;
-
-        //! The master audio volume (0 - 100). 0 is silent, 100 is max volume.
-        uint8_t m_masterVolume = 100;
-
-        //! The streaming image texture mip bias (0 - N). This affects the max mipmap level that will be loaded for streaming images.
-        //! This doesn't affect other types of images like UI or VFX.
-        uint8_t m_streamingImageMipBias = 1;
-    };
-
     struct UiToggle
     {
         AZ_TYPE_INFO(UiToggle, "{60AD7DDE-1730-41D8-BB82-630FF8008370}");
@@ -39,8 +23,13 @@ namespace MultiplayerSample
         AZ::EntityId m_rightButtonEntity;
     };
 
+    // This component is attached to the UI Settings screen and handles the logic for changing the user setting values
+    // when the UI toggles are toggled. It activates on level load, not on settings screen navigation as one might think.
+    // On activation, it reapplies all of the MPS user settings while initializing the toggles to help ensure that the
+    // previously-applied settings weren't overridden by the server or by level loads.
     class UiSettingsComponent
         : public AZ::Component
+        , public AzFramework::WindowNotificationBus::Handler
     {
     public:
         AZ_COMPONENT(UiSettingsComponent, "{6F0F5495-E766-444C-808E-4EB91AD891D6}");
@@ -50,6 +39,12 @@ namespace MultiplayerSample
         void Activate() override;
         void Deactivate() override;
     private:
+        // WindowNotificationBus overrides
+        void OnWindowResized(uint32_t width, uint32_t height) override;
+        void OnRefreshRateChanged([[maybe_unused]] uint32_t refreshRate) override;
+
+        static AzFramework::NativeWindowHandle GetWindowHandle();
+
         enum class ToggleDirection
         {
             None,
@@ -57,14 +52,23 @@ namespace MultiplayerSample
             Right
         };
 
-        void OnGraphicsApiToggle(ToggleDirection toggleDirection);
-        void OnTextureQualityToggle(ToggleDirection toggleDirection);
-        void OnMasterVolumeToggle(ToggleDirection toggleDirection);
+        void InitializeToggle(UiToggle& toggle, AZStd::function<void(UiToggle&, ToggleDirection)> toggleUpdateFn);
+
+        static void OnGraphicsApiToggle(UiToggle& toggle, ToggleDirection toggleDirection);
+        static void OnTextureQualityToggle(UiToggle& toggle, ToggleDirection toggleDirection);
+        static void OnMasterVolumeToggle(UiToggle& toggle, ToggleDirection toggleDirection);
+        static void OnFullscreenToggle(UiToggle& toggle, ToggleDirection toggleDirection);
+        static void OnResolutionToggle(UiToggle& toggle, ToggleDirection toggleDirection);
+
+        template<typename ValueType>
+        static uint32_t GetRotatedIndex(
+            const AZStd::vector<AZStd::pair<ValueType, AZStd::string>>& valuesToLabels,
+            const ValueType& value, ToggleDirection toggleDirection);
 
         UiToggle m_graphicsApiToggle;
         UiToggle m_textureQualityToggle;
         UiToggle m_masterVolumeToggle;
-
-        MpsSettings m_settings;
+        UiToggle m_fullscreenToggle;
+        UiToggle m_resolutionToggle;
     };
 }

+ 63 - 17
Gem/Code/Source/Effects/GameEffect.cpp

@@ -48,7 +48,10 @@ namespace MultiplayerSample
 #if AZ_TRAIT_CLIENT
         if (m_popcornFx != nullptr)
         {
-            m_popcornFx->DestroyEffect(m_emitter);
+            if (m_popcornFx->IsEffectAlive(m_emitter))
+            {
+                m_popcornFx->DestroyEffect(m_emitter);
+            }
             m_emitter = nullptr;
         }
 
@@ -72,8 +75,11 @@ namespace MultiplayerSample
 
         if (m_popcornFx != nullptr)
         {
-            const PopcornFX::SpawnParams params = PopcornFX::SpawnParams(true, false, AZ::Transform::CreateIdentity());
-            m_emitter = m_popcornFx->SpawnEffectById(m_particleAssetId, params);
+            if (m_particleAssetId.IsValid())
+            {
+                const PopcornFX::SpawnParams params = PopcornFX::SpawnParams(true, false, AZ::Transform::CreateIdentity());
+                m_emitter = m_popcornFx->SpawnEffectById(m_particleAssetId, params);
+            }
         }
 
         if (m_audioSystem != nullptr)
@@ -91,10 +97,18 @@ namespace MultiplayerSample
 #if AZ_TRAIT_CLIENT
         if (m_popcornFx != nullptr)
         {
-            int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
-            if (attrId >= 0)
+            if (m_popcornFx->IsEffectAlive(m_emitter))
+            {
+                int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
+                if (attrId >= 0)
+                {
+                    return m_popcornFx->EffectSetAttributeAsFloat(m_emitter, attrId, value);
+                }
+            }
+            else
             {
-                return m_popcornFx->EffectSetAttributeAsFloat(m_emitter, attrId, value);
+                AZ_Assert(false, "Setting attribute on an emitter that isn't active.");
+                return false;
             }
         }
 #endif
@@ -106,10 +120,18 @@ namespace MultiplayerSample
 #if AZ_TRAIT_CLIENT
         if (m_popcornFx != nullptr)
         {
-            int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
-            if (attrId >= 0)
+            if (m_popcornFx->IsEffectAlive(m_emitter))
             {
-                return m_popcornFx->EffectSetAttributeAsFloat2(m_emitter, attrId, value);
+                int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
+                if (attrId >= 0)
+                {
+                    return m_popcornFx->EffectSetAttributeAsFloat2(m_emitter, attrId, value);
+                }
+            }
+            else
+            {
+                AZ_Assert(false, "Setting attribute on an emitter that isn't active.");
+                return false;
             }
         }
 #endif
@@ -121,10 +143,18 @@ namespace MultiplayerSample
 #if AZ_TRAIT_CLIENT
         if (m_popcornFx != nullptr)
         {
-            int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
-            if (attrId >= 0)
+            if (m_popcornFx->IsEffectAlive(m_emitter))
+            {
+                int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
+                if (attrId >= 0)
+                {
+                    return m_popcornFx->EffectSetAttributeAsFloat3(m_emitter, attrId, value);
+                }
+            }
+            else
             {
-                return m_popcornFx->EffectSetAttributeAsFloat3(m_emitter, attrId, value);
+                AZ_Assert(false, "Setting attribute on an emitter that isn't active.");
+                return false;
             }
         }
 #endif
@@ -136,10 +166,18 @@ namespace MultiplayerSample
 #if AZ_TRAIT_CLIENT
         if (m_popcornFx != nullptr)
         {
-            int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
-            if (attrId >= 0)
+            if (m_popcornFx->IsEffectAlive(m_emitter))
+            {
+                int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
+                if (attrId >= 0)
+                {
+                    return m_popcornFx->EffectSetAttributeAsFloat4(m_emitter, attrId, value);
+                }
+            }
+            else
             {
-                return m_popcornFx->EffectSetAttributeAsFloat4(m_emitter, attrId, value);
+                AZ_Assert(false, "Setting attribute on an emitter that isn't active.");
+                return false;
             }
         }
 #endif
@@ -156,8 +194,16 @@ namespace MultiplayerSample
         {
             if (PopcornFX::PopcornFXRequests* popcornFx = PopcornFX::PopcornFXRequestBus::FindFirstHandler())
             {
-                popcornFx->EffectSetTransform(m_emitter, transformOffset);
-                popcornFx->EffectRestart(m_emitter, cl_KillEffectOnRestart);
+                if (m_popcornFx->IsEffectAlive(m_emitter))
+                {
+                    popcornFx->EffectSetTransform(m_emitter, transformOffset);
+                    popcornFx->EffectSetTeleportThisFrame(m_emitter);
+                    popcornFx->EffectRestart(m_emitter, cl_KillEffectOnRestart);
+                }
+                else
+                {
+                    AZ_Assert(false, "Triggering an inactive emitter.");
+                }
             }
         }
 

+ 18 - 9
Gem/Code/Source/MultiplayerSampleModule.cpp

@@ -13,18 +13,19 @@
 #include <Components/UI/UiCoinCountComponent.h>
 #include <Components/UI/UiGameOverComponent.h>
 #include <Components/UI/UiPlayerArmorComponent.h>
+#include <Components/BackgroundMusicComponent.h>
 #include <Components/ScriptableDecalComponent.h>
-#if AZ_TRAIT_CLIENT
-    #include <Components/UI/HUDComponent.h>
-    #include <Components/UI/UiMatchPlayerCoinCountsComponent.h>
-    #include <Components/UI/UiRestBetweenRoundsComponent.h>
-    #include <Components/UI/UiSettingsComponent.h>
-    #include <Components/UI/UiStartMenuComponent.h>
-#endif
-
 #include <Source/AutoGen/AutoComponentTypes.h>
+#include <MultiplayerSampleSystemComponent.h>
 
-#include "MultiplayerSampleSystemComponent.h"
+#if AZ_TRAIT_CLIENT
+#   include <Components/UI/HUDComponent.h>
+#   include <Components/UI/UiMatchPlayerCoinCountsComponent.h>
+#   include <Components/UI/UiRestBetweenRoundsComponent.h>
+#   include <Components/UI/UiSettingsComponent.h>
+#   include <Components/UI/UiStartMenuComponent.h>
+    #include <UserSettings/MultiplayerSampleUserSettings.h>
+#endif
 
 namespace MultiplayerSample
 {
@@ -45,6 +46,7 @@ namespace MultiplayerSample
                 ExampleFilteredEntityComponent::CreateDescriptor(),
                 NetworkPrefabSpawnerComponent::CreateDescriptor(),
                 UiCoinCountComponent::CreateDescriptor(),
+                BackgroundMusicComponent::CreateDescriptor(),
                 ScriptableDecalComponent::CreateDescriptor(),
                 #if AZ_TRAIT_CLIENT
                     HUDComponent::CreateDescriptor(),
@@ -69,6 +71,13 @@ namespace MultiplayerSample
                 azrtti_typeid<MultiplayerSampleSystemComponent>(),
             };
         }
+
+#if AZ_TRAIT_CLIENT
+        // This needs to be created as a part of the MultiplayerSampleModule, not during any sort of System Component activation.
+        // It will affect registry keys that get read by System Components as a part of their activation and we can't guarantee
+        // that those other core System Components will get started after our game-specific one.
+        MultiplayerSampleUserSettings m_userSettings;
+#endif
     };
 }
 

+ 313 - 0
Gem/Code/Source/UserSettings/MultiplayerSampleUserSettings.cpp

@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <Atom/RPI.Public/Image/ImageSystem.h>
+#include <Atom/RPI.Public/Image/StreamingImage.h>
+#include <Atom/RPI.Public/Image/StreamingImagePool.h>
+
+#include <AzCore/Console/IConsole.h>
+#include <AzCore/IO/GenericStreams.h>
+#include <AzCore/Settings/SettingsRegistry.h>
+#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
+#include <AzCore/Utils/Utils.h>
+#include <AzFramework/FileFunc/FileFunc.h>
+#include <AzFramework/Windowing/WindowBus.h>
+#include <IAudioSystem.h>
+#include <UserSettings/MultiplayerSampleUserSettings.h>
+
+namespace MultiplayerSample
+{
+    MultiplayerSampleUserSettings::MultiplayerSampleUserSettings()
+        : m_graphicsApiKey(BaseRegistryKey + FixedString("/ApiName"))
+        , m_masterVolumeKey(BaseRegistryKey + FixedString("/MasterVolume"))
+        , m_textureQualityKey(BaseRegistryKey + FixedString("/TextureQuality"))
+        , m_fullscreenKey(BaseRegistryKey + FixedString("/Fullscreen"))
+        , m_resolutionWidthKey(BaseRegistryKey + FixedString("/Resolution/Width"))
+        , m_resolutionHeightKey(BaseRegistryKey + FixedString("/Resolution/Height"))
+    {
+        MultiplayerSampleUserSettingsRequestBus::Handler::BusConnect();
+
+        // Create a full path including filename for the user settings file.
+        m_userSettingsPath = AZ::Utils::GetProjectUserPath();
+        m_userSettingsPath /= "Registry";
+        m_userSettingsPath /= "MultiplayerSampleUserSettings.setreg";
+
+        // Load all of our settings keys, create default values if they don't exist and initialize the engine settings as appropriate.
+        Load();
+    }
+
+    MultiplayerSampleUserSettings::~MultiplayerSampleUserSettings()
+    {
+        MultiplayerSampleUserSettingsRequestBus::Handler::BusDisconnect();
+
+        // Always auto-save the user settings on destruction.
+        Save();
+    }
+
+    void MultiplayerSampleUserSettings::Load()
+    {
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            // Read the setreg file from a loose file into a string in memory. This isn't technically a "cfg" file,
+            // but the method does the exact set of steps needed here to read a loose file into memory, so even though
+            // it has a slightly misleading name, it keeps us from duplicating the code.
+            AZ::Outcome<AZStd::string, AZStd::string> userSettings = 
+                AzFramework::FileFunc::GetCfgFileContents(AZStd::string(m_userSettingsPath.FixedMaxPathString()));
+
+            if (userSettings.IsSuccess())
+            {
+                // Merge the user settings file under the base "/O3DE/MultiplayerSample/User/Settings" key.
+                // This will ensure that it cannot overwrite any other engine settings.
+                // MergeSettings() is used here instead of MergeSettingsFile() because MergeSettingsFile() uses
+                // FileIOBase to read in the file, which will attempt to read it from a PAK file in PAK file builds.
+                // Our settings file will always be a loose file, so we instead read it into a buffer beforehand and then
+                // apply it here from the in-memory buffer.
+                [[maybe_unused]] auto mergeSuccess = registry->MergeSettings(userSettings.GetValue(),
+                    AZ::SettingsRegistryInterface::Format::JsonMergePatch, BaseRegistryKey);
+
+                AZ_Error("UserSettings", mergeSuccess, "Failed to merge user settings into the O3DE registry.");
+            }
+
+            // Get the current settings values or the defaults if the keys don't exist.
+            AZStd::string apiName = GetGraphicsApi();
+            uint8_t masterVolume = GetMasterVolume();
+            int16_t textureQuality = GetTextureQuality();
+            bool fullscreen = GetFullscreen();
+            AZStd::pair<uint32_t, uint32_t> resolution = GetResolution();
+
+            // Set the settings values, which will notify the engine as well as write the keys back into the registry.
+            SetGraphicsApi(apiName);
+            SetMasterVolume(masterVolume);
+            SetTextureQuality(textureQuality);
+            SetFullscreen(fullscreen);
+            SetResolution(resolution);
+        }
+    }
+
+    AZStd::string MultiplayerSampleUserSettings::GetGraphicsApi()
+    {
+        // Default to an empty string, which will just use the default API.
+        AZStd::string apiName;
+
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            registry->Get(apiName, m_graphicsApiKey.c_str());
+        }
+
+        return apiName;
+    }
+
+    void MultiplayerSampleUserSettings::SetGraphicsApi(const AZStd::string& apiName)
+    {
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            // Set the requested api name as the highest (and only) user priority in the registry.
+            // Atom will select this api at startup as long as it exists and nothing was passed in via command-line.
+            // If the passed-in apiName is empty, just let Atom use its standard default priorities for api selection.
+            // If the passed-in apiName doesn't match one supported by Atom on this platform, Atom will ignore it and use
+            // its standard default priorities as well.
+            if (!apiName.empty())
+            {
+                AZStd::vector<AZStd::string> factoriesPriority;
+                factoriesPriority.emplace_back(apiName);
+                registry->SetObject("/O3DE/Atom/RHI/FactoryManager/factoriesPriority", factoriesPriority);
+            }
+
+            registry->Set(m_graphicsApiKey.c_str(), apiName);
+        }
+    }
+
+    uint8_t MultiplayerSampleUserSettings::GetMasterVolume()
+    {
+        // Default to full volume (100)
+        AZ::u64 masterVolume = 100;
+
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            registry->Get(masterVolume, m_masterVolumeKey.c_str());
+        }
+
+        // Make sure any hand-edited registry values stay within a valid range.
+        return AZStd::clamp(aznumeric_cast<uint8_t>(masterVolume), aznumeric_cast<uint8_t>(0), aznumeric_cast<uint8_t>(100));
+    }
+
+    void MultiplayerSampleUserSettings::SetMasterVolume(uint8_t masterVolume)
+    {
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            // Send a request to the audio system to change the master volume.
+            auto audioSystem = AZ::Interface<Audio::IAudioSystem>::Get();
+            if (audioSystem)
+            {
+                Audio::TAudioObjectID rtpcId = audioSystem->GetAudioRtpcID("Volume_Master");
+
+                if (rtpcId != INVALID_AUDIO_CONTROL_ID)
+                {
+                    Audio::ObjectRequest::SetParameterValue setParameter;
+                    setParameter.m_audioObjectId = INVALID_AUDIO_OBJECT_ID;
+                    setParameter.m_parameterId = rtpcId;
+                    // Master volume in the audio system is expected to be 0.0 (min) - 1.0 (max), but we're using 0 - 100 as integers,
+                    // so convert it from 0 - 100 to the 0 - 1 range.
+                    setParameter.m_value = masterVolume / 100.0f;
+                    AZ::Interface<Audio::IAudioSystem>::Get()->PushRequest(AZStd::move(setParameter));
+                }
+            }
+
+            registry->Set(m_masterVolumeKey.c_str(), aznumeric_cast<AZ::u64>(masterVolume));
+        }
+    }
+
+    int16_t MultiplayerSampleUserSettings::GetTextureQuality()
+    {
+        AZ::s64 textureQuality = 1;
+
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            registry->Get(textureQuality, m_textureQualityKey.c_str());
+        }
+
+        return AZStd::clamp(aznumeric_cast<int16_t>(textureQuality), aznumeric_cast<int16_t>(0), aznumeric_cast<int16_t>(10));
+    }
+
+    void MultiplayerSampleUserSettings::SetTextureQuality(int16_t textureQuality)
+    {
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            if (auto* imageSystem = AZ::RPI::ImageSystemInterface::Get())
+            {
+                AZ::Data::Instance<AZ::RPI::StreamingImagePool> pool = imageSystem->GetSystemStreamingPool();
+                pool->SetMipBias(textureQuality);
+            }
+
+            registry->Set(m_textureQualityKey.c_str(), aznumeric_cast<AZ::s64>(textureQuality));
+        }
+    }
+
+    bool MultiplayerSampleUserSettings::GetFullscreen()
+    {
+        bool fullscreen = false;
+
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            registry->Get(fullscreen, m_fullscreenKey.c_str());
+        }
+
+        return fullscreen;
+    }
+
+    void MultiplayerSampleUserSettings::SetFullscreen(bool fullscreen)
+    {
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            if (AZ::IConsole* console = AZ::Interface<AZ::IConsole>::Get(); console)
+            {
+                // Change the fullscreen state if we haven't created the window yet.
+                AZ::CVarFixedString commandString = AZ::CVarFixedString::format("r_fullscreen %u", fullscreen ? 1 : 0);
+                console->PerformCommand(commandString.c_str());
+
+                // Change the fullscreen state if the window already exists
+                AzFramework::NativeWindowHandle windowHandle = nullptr;
+                AzFramework::WindowSystemRequestBus::BroadcastResult(
+                    windowHandle,
+                    &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
+
+                AzFramework::WindowRequestBus::Event(
+                    windowHandle,
+                    &AzFramework::WindowRequestBus::Events::SetFullScreenState, fullscreen);
+            }
+
+            registry->Set(m_fullscreenKey.c_str(), fullscreen);
+        }
+    }
+
+    AZStd::pair<uint32_t, uint32_t> MultiplayerSampleUserSettings::GetResolution()
+    {
+        AZ::u64 width = 1920;
+        AZ::u64 height = 1080;
+
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            registry->Get(width, m_resolutionWidthKey.c_str());
+            registry->Get(height, m_resolutionHeightKey.c_str());
+        }
+
+        return { aznumeric_cast<uint32_t>(width), aznumeric_cast<uint32_t>(height) };
+    }
+
+    void MultiplayerSampleUserSettings::SetResolution(AZStd::pair<uint32_t, uint32_t> resolution)
+    {
+        if (auto* registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            if (AZ::IConsole* console = AZ::Interface<AZ::IConsole>::Get(); console)
+            {
+                // This will technically change the window resolution to whatever is requrested, but it should 
+                // ideally take into account the current DPI scaling and what the maximum resolution of the monitor is.
+                
+                // Change the resolution if the window doesn't exist yet.
+                AZ::CVarFixedString commandString = AZ::CVarFixedString::format("r_width %u", resolution.first);
+                console->PerformCommand(commandString.c_str());
+
+                commandString = AZ::CVarFixedString::format("r_height %u", resolution.second);
+                console->PerformCommand(commandString.c_str());
+
+                // Change the resolution if the window already exists.
+                AzFramework::NativeWindowHandle windowHandle = nullptr;
+                AzFramework::WindowSystemRequestBus::BroadcastResult(
+                    windowHandle,
+                    &AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
+
+                bool fullscreen = false;
+                AzFramework::WindowRequestBus::EventResult(
+                    fullscreen, windowHandle,
+                    &AzFramework::WindowRequestBus::Events::GetFullScreenState);
+
+                // Don't resize if we're in fullscreen mode.
+                if (!fullscreen)
+                {
+                    AzFramework::WindowRequestBus::Event(
+                        windowHandle,
+                        &AzFramework::WindowRequestBus::Events::ResizeClientArea,
+                        AzFramework::WindowSize(resolution.first, resolution.second), AzFramework::WindowPosOptions());
+                }
+            }
+
+            registry->Set(m_resolutionWidthKey.c_str(), aznumeric_cast<AZ::u64>(resolution.first));
+            registry->Set(m_resolutionHeightKey.c_str(), aznumeric_cast<AZ::u64>(resolution.second));
+        }
+    }
+
+    void MultiplayerSampleUserSettings::Save()
+    {
+        AZ::IO::FixedMaxPath userSettingsSavePath = m_userSettingsPath;
+        userSettingsSavePath.ReplaceExtension("setreg.tmp");
+
+        constexpr AZ::IO::OpenMode openMode = AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath;
+
+        // Write to a temporary file and then move the file to the final location
+        if (AZ::IO::SystemFileStream userSettingsStream(userSettingsSavePath.c_str(), openMode); userSettingsStream.IsOpen())
+        {
+            auto settingsRegistry = AZ::SettingsRegistry::Get();
+
+            // Remove the .tmp extension from the user settings path
+            // This results in the final path where the settings will actually be saved
+            userSettingsSavePath.ReplaceExtension();
+            AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings;
+            dumperSettings.m_prettifyOutput = true;
+            if (AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(
+                *settingsRegistry, BaseRegistryKey, userSettingsStream, dumperSettings))
+            {
+                // Use SystemFile::Rename to move the file to the final destination
+                userSettingsStream.Close();
+                bool renameSuccess = AZ::IO::SystemFile::Rename(userSettingsStream.GetFilename(), userSettingsSavePath.c_str(), true);
+                AZ_Error("UserSettings", renameSuccess, 
+                    "Renaming '%s' to '%s' failed.", userSettingsStream.GetFilename(), userSettingsSavePath.c_str());
+            }
+        }
+    }
+
+} // namespace MultiplayerSample

+ 109 - 0
Gem/Code/Source/UserSettings/MultiplayerSampleUserSettings.h

@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+#include <AzCore/EBus/EBus.h>
+#include <AzCore/IO/Path/Path.h>
+
+namespace MultiplayerSample
+{
+    // This provides a way to get/set every user setting that MultiplayerSample supports, and to save the user settings file.
+    // Getting the values pulls them out of the saved user settings data, and setting the values both sets them in the user
+    // settings and communicates the change to the appropriate part of the game engine to make the change take effect.
+    class MultiplayerSampleUserSettingsRequests
+        : public AZ::EBusTraits
+    {
+    public:
+        static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+
+        virtual ~MultiplayerSampleUserSettingsRequests() = default;
+
+        // Load the user settings and refresh the game engine based on the settings. They automatically get loaded and applied
+        // on launcher startup, but this might need to be called to refresh the settings after connecting to the server and loading
+        // the level in case any engine systems get reset by server cvars and level data.
+        virtual void Load() = 0;
+
+        // Save the user settings file out to disk.
+        virtual void Save() = 0;
+
+        // Change the default graphics API between dx12/vulkan/metal/null on the next restart of the game.
+        virtual AZStd::string GetGraphicsApi() = 0;
+        virtual void SetGraphicsApi(const AZStd::string& apiName) = 0;
+
+        // Change the master volume from 0 - 100.
+        virtual uint8_t GetMasterVolume() = 0;
+        virtual void SetMasterVolume(uint8_t masterVolume) = 0;
+
+        // Change the texture quality. 0 = highest quality (highest mipmap), N = lowest quality (lowest mipmap).
+        // There's no well-defined value for lowest quality so we'll just arbitrarily cap it at 6 (64x64 if mip 0 is 4096x4096). 
+        // Anything lower doesn't really provide any benefit.
+        virtual int16_t GetTextureQuality() = 0;
+        virtual void SetTextureQuality(int16_t textureQuality) = 0;
+
+        // Change between fullscreen and windowed.
+        virtual bool GetFullscreen() = 0;
+        virtual void SetFullscreen(bool fullscreen) = 0;
+
+        // Change the rendering resolution (width, height)
+        virtual AZStd::pair<uint32_t, uint32_t> GetResolution() = 0;
+        virtual void SetResolution(AZStd::pair<uint32_t, uint32_t> resolution) = 0;
+    };
+
+    using MultiplayerSampleUserSettingsRequestBus = AZ::EBus<MultiplayerSampleUserSettingsRequests>;
+
+    // This implements the bus provided above. The user settings get auto-loaded at construction and auto-saved at destruction,
+    // though saves can also be triggered at other times as well. Because one of the settings is the default graphics API, these
+    // settings need to be loaded before system components are initialized because the Atom system components load the graphics
+    // API. All of the other settings are changeable at any time and would have allowed this class to get created later in the
+    // boot process.
+    class MultiplayerSampleUserSettings : public MultiplayerSampleUserSettingsRequestBus::Handler
+    {
+    public:
+        MultiplayerSampleUserSettings();
+        ~MultiplayerSampleUserSettings() override;
+
+        void Load() override;
+        void Save() override;
+
+        AZStd::string GetGraphicsApi() override;
+        void SetGraphicsApi(const AZStd::string& apiName) override;
+
+        uint8_t GetMasterVolume() override;
+        void SetMasterVolume(uint8_t masterVolume) override;
+
+        int16_t GetTextureQuality() override;
+        void SetTextureQuality(int16_t textureQuality) override;
+
+        bool GetFullscreen() override;
+        void SetFullscreen(bool fullscreen) override;
+
+
+        AZStd::pair<uint32_t, uint32_t> GetResolution() override;
+        void SetResolution(AZStd::pair<uint32_t, uint32_t> resolution) override;
+
+    private:
+        using FixedString = AZStd::fixed_string<256>;
+
+        // The base registry key that all our user settings will live underneath.
+        // We keep them separate from the rest of the registry hierarchy to ensure that users can't
+        // edit their settings file by hand to overwrite any other registry keys that weren't intentionally exposed.
+        static inline constexpr FixedString BaseRegistryKey = "/O3DE/MultiplayerSample/User/Settings";
+
+        // These keep track of the specific registry keys used for each setting.
+        const FixedString m_graphicsApiKey;
+        const FixedString m_textureQualityKey;
+        const FixedString m_masterVolumeKey;
+        const FixedString m_fullscreenKey;
+        const FixedString m_resolutionWidthKey;
+        const FixedString m_resolutionHeightKey;
+
+        // The path to the user settings file.
+        AZ::IO::FixedMaxPath m_userSettingsPath;
+    };
+
+} // namespace MultiplayerSample

+ 3 - 0
Gem/Code/multiplayersample_files.cmake

@@ -73,6 +73,9 @@ set(FILES
     Source/Components/Multiplayer/EnergyCannonComponent.cpp
     Source/Components/Multiplayer/EnergyCannonComponent.h
 
+    Source/Components/BackgroundMusicComponent.cpp
+    Source/Components/BackgroundMusicComponent.h
+
     Source/Components/RpcTesterComponent.cpp
     Source/Components/RpcTesterComponent.h
     

+ 3 - 0
Gem/Code/multiplayersample_shared_files.cmake

@@ -6,5 +6,8 @@
 #
 
 set(FILES
+
     Source/MultiplayerSampleModule.cpp
+    Source/UserSettings/MultiplayerSampleUserSettings.h
+    Source/UserSettings/MultiplayerSampleUserSettings.cpp
 )

+ 22 - 67
Levels/GameplayTest/GameplayTest.prefab

@@ -120,14 +120,14 @@
                     "Entity_[15464591867054]",
                     "Entity_[15473181801646]",
                     "Entity_[15481771736238]",
-                    "Entity_[873004712589]",
                     "Instance_[1238918361381]/ContainerEntity",
                     "Instance_[990233405078]/ContainerEntity",
                     "Instance_[44514490248300]/ContainerEntity",
                     "Instance_[2090718165100]/ContainerEntity",
                     "Entity_[58675766534237]",
                     "Entity_[65620728651869]",
-                    "Instance_[6302654760100]/ContainerEntity"
+                    "Instance_[6302654760100]/ContainerEntity",
+                    "Instance_[10391347535934]/ContainerEntity"
                 ]
             }
         }
@@ -11842,17 +11842,6 @@
                         "$type": "MultiplayerSample::MatchPlayerCoinsComponent"
                     }
                 },
-                "Component_[3709937876037180985]": {
-                    "$type": "GenericComponentWrapper",
-                    "Id": 3709937876037180985,
-                    "m_template": {
-                        "$type": "UiCanvasAssetRefComponent",
-                        "CanvasAssetRef": {
-                            "AssetPath": "uicanvases/basichud.uicanvas"
-                        },
-                        "IsAutoLoad": true
-                    }
-                },
                 "Component_[5143246854913296527]": {
                     "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
                     "Id": 5143246854913296527,
@@ -12040,60 +12029,6 @@
                     "Id": 9914289529455341679
                 }
             }
-        },
-        "Entity_[873004712589]": {
-            "Id": "Entity_[873004712589]",
-            "Name": "In Game Menu",
-            "Components": {
-                "Component_[10973769579758943127]": {
-                    "$type": "EditorInspectorComponent",
-                    "Id": 10973769579758943127
-                },
-                "Component_[13892978883605229067]": {
-                    "$type": "EditorPendingCompositionComponent",
-                    "Id": 13892978883605229067
-                },
-                "Component_[16221779430861293146]": {
-                    "$type": "EditorDisabledCompositionComponent",
-                    "Id": 16221779430861293146
-                },
-                "Component_[16377069407396552235]": {
-                    "$type": "EditorVisibilityComponent",
-                    "Id": 16377069407396552235
-                },
-                "Component_[199753144438342893]": {
-                    "$type": "EditorEntitySortComponent",
-                    "Id": 199753144438342893
-                },
-                "Component_[2280755623652026535]": {
-                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
-                    "Id": 2280755623652026535,
-                    "Parent Entity": "Entity_[356758116574]"
-                },
-                "Component_[4368122420119951993]": {
-                    "$type": "EditorEntityIconComponent",
-                    "Id": 4368122420119951993
-                },
-                "Component_[438967016699456639]": {
-                    "$type": "EditorLockComponent",
-                    "Id": 438967016699456639
-                },
-                "Component_[5604360131636598685]": {
-                    "$type": "EditorOnlyEntityComponent",
-                    "Id": 5604360131636598685
-                },
-                "Component_[9355518200202427665]": {
-                    "$type": "GenericComponentWrapper",
-                    "Id": 9355518200202427665,
-                    "m_template": {
-                        "$type": "UiCanvasAssetRefComponent",
-                        "CanvasAssetRef": {
-                            "AssetPath": "uicanvases/ingamemenu.uicanvas"
-                        },
-                        "IsAutoLoad": true
-                    }
-                }
-            }
         }
     },
     "Instances": {
@@ -12122,6 +12057,26 @@
                 }
             ]
         },
+        "Instance_[10391347535934]": {
+            "Source": "Prefabs/UI.prefab",
+            "Patches": [
+                {
+                    "op": "replace",
+                    "path": "/ContainerEntity/Components/Component_[11968026641926863763]/Parent Entity",
+                    "value": "../Entity_[356758116574]"
+                },
+                {
+                    "op": "replace",
+                    "path": "/ContainerEntity/Components/Component_[11968026641926863763]/Transform Data/Translate/1",
+                    "value": 12.499994277954102
+                },
+                {
+                    "op": "replace",
+                    "path": "/ContainerEntity/Components/Component_[11968026641926863763]/Transform Data/Translate/2",
+                    "value": 4.017059803009033
+                }
+            ]
+        },
         "Instance_[1154437282147]": {
             "Source": "Prefabs/Diamond_Gem.prefab",
             "Patches": [

+ 52 - 9
Levels/NewStarbase/NewStarbase.prefab

@@ -2535,6 +2535,11 @@
                     "$type": "EditorPendingCompositionComponent",
                     "Id": 16817453197198982078
                 },
+                "Component_[2619917249643206097]": {
+                    "$type": "EditorCommentComponent",
+                    "Id": 2619917249643206097,
+                    "Configuration": "For more information about lighting please see the level design guide in the multiplayersample documentation folder."
+                },
                 "Component_[376094705505411548]": {
                     "$type": "EditorEntitySortComponent",
                     "Id": 376094705505411548,
@@ -4487,6 +4492,11 @@
                     "Id": 7186247374812053450,
                     "Parent Entity": "Entity_[60274689909647]"
                 },
+                "Component_[7963844296059785842]": {
+                    "$type": "EditorCommentComponent",
+                    "Id": 7963844296059785842,
+                    "Configuration": "This is a simple 1x1 tile terrain. The spawners operate within the bounds of the box for the terrain spawner. The child entity height is an image gradient signal that loads a height map asset to generate the height map, which is then sampled by the parent terrain entity, via the terrain height gradient list component. The matching macro color map and macro normal map are loaded in the terrain macro material component."
+                },
                 "Component_[9388349147874105140]": {
                     "$type": "EditorTerrainLayerSpawnerComponent",
                     "Id": 9388349147874105140
@@ -7097,6 +7107,11 @@
                     "$type": "EditorInspectorComponent",
                     "Id": 17057238313917441482
                 },
+                "Component_[17703777834056015433]": {
+                    "$type": "EditorCommentComponent",
+                    "Id": 17703777834056015433,
+                    "Configuration": "This is currently not contributing to global illumination. This is where we would add one or more reflection probes to bake reflections for the level geometry."
+                },
                 "Component_[2149849594454303666]": {
                     "$type": "EditorOnlyEntityComponent",
                     "Id": 2149849594454303666
@@ -8528,6 +8543,11 @@
                     "$type": "EditorDisabledCompositionComponent",
                     "Id": 15744299950611104828
                 },
+                "Component_[1684972590650734165]": {
+                    "$type": "EditorCommentComponent",
+                    "Id": 1684972590650734165,
+                    "Configuration": "The sun properties of the sky atmosphere contain a  reference to the child sun entity. The transform of the child sun entity determines the position of the sun in the sky atmoshpere. The sky atmosphere is baked into the image-based lighting that is loaded into the Global illlumination sample's lighting information from the sky light, the sky atmosphere and the sun entity."
+                },
                 "Component_[1728065122520318572]": {
                     "$type": "EditorLockComponent",
                     "Id": 1728065122520318572
@@ -11239,6 +11259,11 @@
                     "$type": "EditorEntityIconComponent",
                     "Id": 11895140916889160460
                 },
+                "Component_[13025475667675684062]": {
+                    "$type": "EditorCommentComponent",
+                    "Id": 13025475667675684062,
+                    "Configuration": "This 3rd person spring-arm camera is controlled by each client's player."
+                },
                 "Component_[16880285896855930892]": {
                     "$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent",
                     "Id": 16880285896855930892,
@@ -11246,7 +11271,7 @@
                         "Configuration": {
                             "Field of View": 55.0,
                             "Far Clip Plane Distance": 4096.0,
-                            "EditorEntityId": 10557690388680515673
+                            "EditorEntityId": 17729197467549002539
                         }
                     }
                 },
@@ -11577,6 +11602,19 @@
                     "$type": "EditorEntitySortComponent",
                     "Id": 14774980749977237053
                 },
+                "Component_[14919200452665967980]": {
+                    "$type": "GenericComponentWrapper",
+                    "Id": 14919200452665967980,
+                    "m_template": {
+                        "$type": "MultiplayerSample::BackgroundMusicComponent",
+                        "Shuffle": true,
+                        "Playlist": [
+                            "rocket",
+                            "beauty_flow",
+                            "future_gladiator"
+                        ]
+                    }
+                },
                 "Component_[17049943556665966323]": {
                     "$type": "EditorEntityIconComponent",
                     "Id": 17049943556665966323
@@ -11613,6 +11651,11 @@
                     "$type": "EditorPendingCompositionComponent",
                     "Id": 612576140938853376
                 },
+                "Component_[7829044378931254902]": {
+                    "$type": "EditorCommentComponent",
+                    "Id": 7829044378931254902,
+                    "Configuration": "Global ambient \"background\" audio for the level is hooked up here. Individual prefabs may have their own ambient sounds."
+                },
                 "Component_[9778753844251016872]": {
                     "$type": "EditorBoxShapeComponent",
                     "Id": 9778753844251016872
@@ -30814,7 +30857,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",
@@ -30854,7 +30897,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",
@@ -30894,7 +30937,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",
@@ -30934,7 +30977,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",
@@ -30974,7 +31017,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",
@@ -31014,7 +31057,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",
@@ -31054,7 +31097,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",
@@ -31094,7 +31137,7 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[2563122736071885678]/Transform Data/Rotate/1",
-                    "value": 1.2738307587564779e-12
+                    "value": 1.273830758756478e-12
                 },
                 {
                     "op": "replace",

+ 2 - 2
MPSGameLift/UICanvases/GameLiftConnectJson/QuitButton.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3b4fe44deccce80cbc52135c1ae2d54c3bc440152dd397a86ca46b5f89a9948a
-size 94616
+oid sha256:32fd4b86cbb3d0e94f30dc9b7581657d0654b7808c288e55f5e8229e9a889b96
+size 78073

+ 2 - 2
MPSGameLift/UICanvases/GameLiftConnectJson/QuitButtonDown.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c05bf1c014c7dea29ca188f0f57ff8a4b8b9a40cb23d125744be35c1e4d459ab
-size 93711
+oid sha256:229750df82f1f8c6748a8e7d52ad3ff6688643287fc9c3385acc7886852912ee
+size 80048

+ 2 - 2
MPSGameLift/UICanvases/GameLiftConnectJson/QuitButtonHover.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9908ca5c6047589f704508d3dce04cf315504cd82b425df12925d27326d36277
-size 91710
+oid sha256:3bc30c61221e6fe40669474b54b8a85dca3be234e9ce0f74f9d966ab9af986a5
+size 85039

+ 41 - 13
README.md

@@ -20,11 +20,14 @@ Game features:
 * Jump pads to boost players high into the air
 * A configurable number of rounds (default: 3 rounds)
 * Configurable gem spawning patterns per round to drive player exploration
-* Support for 1 to 15 players
+* Support for 1 to 10 players
 * Rich sounds and visual effects support
-* Teleporters to aid player exploration
+* Teleporters to aid player exploration and to demonstrate moving players.
+* [User Settings screen](Documentation/SettingsScreen.md)
 * Many points of extensibility
 
+> A player can win the whole game early by reaching a score of 400. See the [Gameplay Configuration](Documentation/GamplayConfiguration.md) docs.
+
 ### Player controls
 
 * Move using: **W,A,S,D**
@@ -71,7 +74,7 @@ These instructions use the following installation paths. Be sure to substitute y
    Cloning into 'o3de-multiplayersample'...
    ```
 
-3. Clone the assets. In this example the assets are cloned beside the muliplayersample project.
+3. Clone the assets. In this example the assets are cloned beside the multiplayersample project.
 
    ```shell
    git clone https://github.com/o3de/o3de-multiplayersample-assets.git
@@ -115,6 +118,28 @@ These instructions use the following installation paths. Be sure to substitute y
    echo o3de-multiplayersample-assets > C:/o3de/.git/info/exclude
    ```
 
+### Step 1a. Ensure your branches match
+
+Before building the project, ensure that o3de, o3de-multiplayersample and o3de-multiplayersample-assets are all cloned from the same named branches. For example, if you are using the **development** branch of o3de-multiplayersample, then it must be matched with the **development** branches of o3de, and o3de-multiplayersample-assets. Ensure that you update the submodules in o3de-multiplayersample-assets when switching branches in that repository.
+
+If you're using a release or installer version of O3DE, then you must checkout versions of the sample repositories that match the release. O3DE uses standard Git [tags](https://git-scm.com/book/en/v2/Git-Basics-Tagging) to identify the release-compatible version of each repository. 
+
+For each O3DE release, repositories that have been updated to match the release should have a matching tag for the release. You can see all defined tags using the [Tags](https://github.com/o3de/o3de-multiplayersample/tags] view in each repository.
+
+Branches can be checked out using standard Git commands, for example, `git checkout tags/<tag> -b <local branch name>`.
+
+### Step 1b. Verify you have the LFS files.
+
+Verify that you have all the files from the LFS endpoint. For each cloned repository, run:
+
+```
+git lfs pull
+```
+
+If using your own fork, complete LFS setup by updating the [LFS Url](https://www.o3de.org/docs/welcome-guide/setup/setup-from-github/#fork-and-clone). 
+
+If you have problems with working with LFS, see the troubleshooting guide: https://github.com/o3de/o3de/wiki/Git-LFS-Troubleshooting.
+
 ## Step 2. Register the engine, the project, and the Gems
 
 ### Option #1 - Use the CLI
@@ -147,7 +172,7 @@ If you've already built the O3DE engine, use the O3DE project manager to open an
 
 1. Run `o3de.exe`. If you used the engine build instructions from the [Getting Started](https://www.o3de.org/docs/welcome-guide/) guide, `o3de.exe` can be found at `C:/o3de/build/windows/bin/profile/o3de.exe`.
 
-1. (Optional) If MultiplayerSample is not in the **My Projects** view, then click the **New Project...** drop down and select **Open Existing Project**. Select the o3de-mulitplayersample project. See the [Project Manager User Guide](https://www.o3de.org/docs/user-guide/project-config/project-manager/#projects) for details.
+1. (Optional) If MultiplayerSample is not in the **My Projects** view, then click the **New Project...** drop down and select **Open Existing Project**. Select the o3de-multiplayersample project. See the [Project Manager User Guide](https://www.o3de.org/docs/user-guide/project-config/project-manager/#projects) for details.
 
 1. You can choose **Build** in Project Manager to build the project, and skip the following **Step 3. Configure and build** steps.
 
@@ -277,9 +302,9 @@ When debugging set `net_UdpTimeoutConnections` to false. This prevents connectio
 
 This project ships with several levels, the ones of note are:
 
-1. `NewStarBase` - The main game level. Also the default level.
-2. `GamePlayTest` - Everything needed for gameplay, but in a tiny, fast-loading level. All game objects (Gems, HUD, and so on) are included.
-3. `StartMenu` - An example menu to join, host, and connect to servers.
+1. `NewStarBase` - The main game level (the default level for gameplay).
+2. `StartMenu` - An example menu to join, host, and connect to servers.
+3. `GamePlayTest` - Everything needed for gameplay, but in a tiny, fast-loading level. All game objects (Gems, HUD, and so on) are included.
 4. `MultiplayerScriptingSample` - An example of scripts for Multiplayer.
 
 Other levels in the project are used for testing or performance evaluation purposes and are considered experimental.
@@ -294,12 +319,15 @@ You can contribute by [reporting issues and making feature requests](https://git
 
 ## Documentation
 
-| Link                                                                             | Description                       |
-|----------------------------------------------------------------------------------|-----------------------------------|
-| [README_LINUX](README_LINUX.md)                                                  | Linux specific setup instructions |
-| [Gameplay Configuration](Documentation/GamplayConfiguration.md)                  | How to adjust gameplay settings   |
-| [GameLift Setup](Documentation/Hosting/AmazonGameLift/GameLift.md)               | How to deploy to GameLift         |
-| [GameLift Local Setup](Documentation/Hosting/AmazonGameLift/GameLiftLocal.md)    | How to test GameLift locally      |
+| Link                                                                             | Description                                                               |
+|----------------------------------------------------------------------------------|---------------------------------------------------------------------------|
+| [README_LINUX](README_LINUX.md)                                                  | Linux specific setup instructions                                         |
+| [Release Notes](Documentation/ReleaseNotes.md)                                   | Release notes and known issues per major release                          |
+| [Gameplay Configuration](Documentation/GamplayConfiguration.md)                  | How to adjust gameplay settings                                           |
+| [SettingsScreen](Documentation/SettingsScreen.md)                                | How to use and extend the settings screen                                 |
+| [Packaging MPS](Documentation/PackedAssetBuilds.md)                              | How to build and package MPS for distribution or running servers remotely |
+| [GameLift Setup](Documentation/Hosting/AmazonGameLift/GameLift.md)               | How to deploy to GameLift                                                 |
+| [GameLift Local Setup](Documentation/Hosting/AmazonGameLift/GameLiftLocal.md)    | How to test GameLift locally                                              |
 
 ## O3DE Useful Links
 

+ 1 - 1
Registry/multiplayersample.setreg

@@ -1,7 +1,7 @@
 {
 	"MultiplayerSample": {
 		"Settings": {
-			"WinningCoinCount": 333,
+			"WinningCoinCount": 400,
 			"EnergyBall": {
 				"KnockbackDistanceMeters": 2.0,
 				"Speed": 15.0,

+ 6 - 7
Registry/settings.multiplayersample_gamelauncher.setreg

@@ -1,11 +1,10 @@
 {
-    "Amazon": {
-        "AzCore": {
-            "Runtime": {
-                "ConsoleCommands": {
-                    "cl_serverAddr": "127.0.0.1",
-                    "loadlevel": "startmenu"
-                }
+    "O3DE": {
+       "Autoexec": {
+            "ConsoleCommands": {
+                "r_displayInfo": 0,
+                "cl_serverAddr": "127.0.0.1",
+                "loadlevel": "startmenu"
             }
         }
     }

+ 6 - 7
Registry/settings.multiplayersample_unifiedlauncher.setreg

@@ -1,11 +1,10 @@
 {
-    "Amazon": {
-        "AzCore": {
-            "Runtime": {
-                "ConsoleCommands": {
-                    "cl_serverAddr": "127.0.0.1",
-                    "loadlevel": "startmenu"
-                }
+    "O3DE": {
+       "Autoexec": {
+            "ConsoleCommands": {
+                "r_displayInfo": 0,
+                "cl_serverAddr": "127.0.0.1",
+                "loadlevel": "newstarbase"
             }
         }
     }

+ 3 - 0
Sounds/wwise/1070395499.wem

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:45a644501a6762f30e5b7cef444f41bcc312d09f91398301dbd9e08d8671e87d
+size 66539584

+ 3 - 0
Sounds/wwise/1073420800.wem

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b1deeee7019c3eff5673cac9920dedef11f0feadf1553392a51628d5c1045ae0
+size 38283328

+ 3 - 0
Sounds/wwise/115250578.wem

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:708537b00f9a619c957a89d9c038512d169fe5301ebfe124515c1b14354b360b
+size 25924672

+ 3 - 0
Sounds/wwise/655023540.wem

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a1c4fe8e4e9c51054324c524ad049baa94774d56f9a9a1d5faf10bbcaa91417e
+size 76451392

+ 2 - 2
Sounds/wwise/MultiplayerSample_SoundBank.bnk

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e26efb95f47ba277d16fec0b7ce36c9b04ebcd836ace81782c64a13b9419f7de
-size 63086512
+oid sha256:21b03265f9118a1ea525635bf2663d100a947f5cb2795d0982d2ab9fbab73c47
+size 63087131

+ 192 - 0
Sounds/wwise_project/Actor-Mixer Hierarchy/AMPS/LVL.wwu

@@ -82,6 +82,198 @@
 									</ChildrenList>
 									<ObjectLists/>
 								</BlendContainer>
+								<ActorMixer Name="beauty_flow" ID="{9EC966BE-D68B-4A2D-A56C-4892CE97A77D}" ShortID="215290428">
+									<PropertyList>
+										<Property Name="3DSpatialization" Type="int16" Value="2"/>
+										<Property Name="BelowThresholdBehavior" Type="int16" Value="3"/>
+										<Property Name="PriorityDistanceFactor" Type="bool" Value="True"/>
+										<Property Name="UserAuxSendVolume0" Type="Real64">
+											<ValueList>
+												<Value>-3</Value>
+											</ValueList>
+										</Property>
+									</PropertyList>
+									<ReferenceList>
+										<Reference Name="Attenuation">
+											<ObjectRef Name="ATN_Default_20" ID="{9A356296-FB49-4226-8845-131AFAB59884}" WorkUnitID="{FF701137-ABB4-4FD9-800E-7C2F77E85689}"/>
+										</Reference>
+										<Reference Name="Conversion">
+											<ObjectRef Name="Default Conversion Settings" ID="{6D1B890C-9826-4384-BF07-C15223E9FB56}" WorkUnitID="{0119FCBC-B171-4B2F-BB85-593A23CC9CD0}"/>
+										</Reference>
+										<Reference Name="OutputBus">
+											<ObjectRef Name="SX" ID="{9BAD8B54-940E-473A-9DE7-E613A4F0BB4B}" WorkUnitID="{8B26C89C-CDEC-42FD-AE82-2A0A21AD7AAE}"/>
+										</Reference>
+										<Reference Name="UserAuxSend0">
+											<ObjectRef Name="RVB_EXT_Main" ID="{F8DF5907-D7A9-43AF-B130-2AB20EED85E3}" WorkUnitID="{8B26C89C-CDEC-42FD-AE82-2A0A21AD7AAE}"/>
+										</Reference>
+									</ReferenceList>
+									<ChildrenList>
+										<Sound Name="Beauty Flow" ID="{ECDF9185-197D-4EAD-BF3B-F3EAE8040A1E}" ShortID="1058521084">
+											<PropertyList>
+												<Property Name="IsStreamingEnabled" Type="bool">
+													<ValueList>
+														<Value>True</Value>
+													</ValueList>
+												</Property>
+												<Property Name="Volume" Type="Real64">
+													<ValueList>
+														<Value>-6</Value>
+													</ValueList>
+												</Property>
+											</PropertyList>
+											<ReferenceList>
+												<Reference Name="Conversion">
+													<ObjectRef Name="Default Conversion Settings" ID="{6D1B890C-9826-4384-BF07-C15223E9FB56}" WorkUnitID="{0119FCBC-B171-4B2F-BB85-593A23CC9CD0}"/>
+												</Reference>
+												<Reference Name="OutputBus">
+													<ObjectRef Name="Master Audio Bus" ID="{1514A4D8-1DA6-412A-A17E-75CA0C2149F3}" WorkUnitID="{F62C277B-2C60-43BB-A8B2-F1E94C3F98EC}"/>
+												</Reference>
+											</ReferenceList>
+											<ChildrenList>
+												<AudioFileSource Name="Beauty Flow" ID="{A46E9731-E1EB-42EE-BE7F-F6437FDF809C}">
+													<Language>SFX</Language>
+													<AudioFile>Beauty Flow.wav</AudioFile>
+													<MediaIDList>
+														<MediaID ID="655023540"/>
+													</MediaIDList>
+												</AudioFileSource>
+											</ChildrenList>
+											<ObjectLists/>
+											<ActiveSourceList>
+												<ActiveSource Name="Beauty Flow" ID="{A46E9731-E1EB-42EE-BE7F-F6437FDF809C}" Platform="Linked"/>
+											</ActiveSourceList>
+										</Sound>
+									</ChildrenList>
+									<ObjectLists/>
+								</ActorMixer>
+								<ActorMixer Name="future_gladiator" ID="{AAAFDCA3-E9CD-4C2A-8E30-8538B7B78B31}" ShortID="48597">
+									<PropertyList>
+										<Property Name="3DSpatialization" Type="int16" Value="2"/>
+										<Property Name="BelowThresholdBehavior" Type="int16" Value="3"/>
+										<Property Name="PriorityDistanceFactor" Type="bool" Value="True"/>
+										<Property Name="UserAuxSendVolume0" Type="Real64">
+											<ValueList>
+												<Value>-3</Value>
+											</ValueList>
+										</Property>
+									</PropertyList>
+									<ReferenceList>
+										<Reference Name="Attenuation">
+											<ObjectRef Name="ATN_Default_20" ID="{9A356296-FB49-4226-8845-131AFAB59884}" WorkUnitID="{FF701137-ABB4-4FD9-800E-7C2F77E85689}"/>
+										</Reference>
+										<Reference Name="Conversion">
+											<ObjectRef Name="Default Conversion Settings" ID="{6D1B890C-9826-4384-BF07-C15223E9FB56}" WorkUnitID="{0119FCBC-B171-4B2F-BB85-593A23CC9CD0}"/>
+										</Reference>
+										<Reference Name="OutputBus">
+											<ObjectRef Name="SX" ID="{9BAD8B54-940E-473A-9DE7-E613A4F0BB4B}" WorkUnitID="{8B26C89C-CDEC-42FD-AE82-2A0A21AD7AAE}"/>
+										</Reference>
+										<Reference Name="UserAuxSend0">
+											<ObjectRef Name="RVB_EXT_Main" ID="{F8DF5907-D7A9-43AF-B130-2AB20EED85E3}" WorkUnitID="{8B26C89C-CDEC-42FD-AE82-2A0A21AD7AAE}"/>
+										</Reference>
+									</ReferenceList>
+									<ChildrenList>
+										<Sound Name="Future Gladiator" ID="{2C0BD4CA-76EC-4714-9C88-C5364FD4361D}" ShortID="722579746">
+											<PropertyList>
+												<Property Name="IsStreamingEnabled" Type="bool">
+													<ValueList>
+														<Value>True</Value>
+													</ValueList>
+												</Property>
+												<Property Name="Volume" Type="Real64">
+													<ValueList>
+														<Value>-8</Value>
+													</ValueList>
+												</Property>
+											</PropertyList>
+											<ReferenceList>
+												<Reference Name="Conversion">
+													<ObjectRef Name="Default Conversion Settings" ID="{6D1B890C-9826-4384-BF07-C15223E9FB56}" WorkUnitID="{0119FCBC-B171-4B2F-BB85-593A23CC9CD0}"/>
+												</Reference>
+												<Reference Name="OutputBus">
+													<ObjectRef Name="Master Audio Bus" ID="{1514A4D8-1DA6-412A-A17E-75CA0C2149F3}" WorkUnitID="{F62C277B-2C60-43BB-A8B2-F1E94C3F98EC}"/>
+												</Reference>
+											</ReferenceList>
+											<ChildrenList>
+												<AudioFileSource Name="Future Gladiator" ID="{4FD3E458-FA8C-4F43-9523-66364BF7511F}">
+													<Language>SFX</Language>
+													<AudioFile>Future Gladiator.wav</AudioFile>
+													<MediaIDList>
+														<MediaID ID="1073420800"/>
+													</MediaIDList>
+												</AudioFileSource>
+											</ChildrenList>
+											<ObjectLists/>
+											<ActiveSourceList>
+												<ActiveSource Name="Future Gladiator" ID="{4FD3E458-FA8C-4F43-9523-66364BF7511F}" Platform="Linked"/>
+											</ActiveSourceList>
+										</Sound>
+									</ChildrenList>
+									<ObjectLists/>
+								</ActorMixer>
+								<ActorMixer Name="rocket" ID="{4D1305BD-E28A-49F1-8E91-D75EB6EA59FB}" ShortID="143389107">
+									<PropertyList>
+										<Property Name="3DSpatialization" Type="int16" Value="2"/>
+										<Property Name="BelowThresholdBehavior" Type="int16" Value="3"/>
+										<Property Name="PriorityDistanceFactor" Type="bool" Value="True"/>
+										<Property Name="UserAuxSendVolume0" Type="Real64">
+											<ValueList>
+												<Value>-3</Value>
+											</ValueList>
+										</Property>
+									</PropertyList>
+									<ReferenceList>
+										<Reference Name="Attenuation">
+											<ObjectRef Name="ATN_Default_20" ID="{9A356296-FB49-4226-8845-131AFAB59884}" WorkUnitID="{FF701137-ABB4-4FD9-800E-7C2F77E85689}"/>
+										</Reference>
+										<Reference Name="Conversion">
+											<ObjectRef Name="Default Conversion Settings" ID="{6D1B890C-9826-4384-BF07-C15223E9FB56}" WorkUnitID="{0119FCBC-B171-4B2F-BB85-593A23CC9CD0}"/>
+										</Reference>
+										<Reference Name="OutputBus">
+											<ObjectRef Name="SX" ID="{9BAD8B54-940E-473A-9DE7-E613A4F0BB4B}" WorkUnitID="{8B26C89C-CDEC-42FD-AE82-2A0A21AD7AAE}"/>
+										</Reference>
+										<Reference Name="UserAuxSend0">
+											<ObjectRef Name="RVB_EXT_Main" ID="{F8DF5907-D7A9-43AF-B130-2AB20EED85E3}" WorkUnitID="{8B26C89C-CDEC-42FD-AE82-2A0A21AD7AAE}"/>
+										</Reference>
+									</ReferenceList>
+									<ChildrenList>
+										<Sound Name="Rocket" ID="{E8258E1E-BB45-4281-9C81-3174071BEEB0}" ShortID="758395372">
+											<PropertyList>
+												<Property Name="IsStreamingEnabled" Type="bool">
+													<ValueList>
+														<Value>True</Value>
+													</ValueList>
+												</Property>
+												<Property Name="Volume" Type="Real64">
+													<ValueList>
+														<Value>-8</Value>
+													</ValueList>
+												</Property>
+											</PropertyList>
+											<ReferenceList>
+												<Reference Name="Conversion">
+													<ObjectRef Name="Default Conversion Settings" ID="{6D1B890C-9826-4384-BF07-C15223E9FB56}" WorkUnitID="{0119FCBC-B171-4B2F-BB85-593A23CC9CD0}"/>
+												</Reference>
+												<Reference Name="OutputBus">
+													<ObjectRef Name="Master Audio Bus" ID="{1514A4D8-1DA6-412A-A17E-75CA0C2149F3}" WorkUnitID="{F62C277B-2C60-43BB-A8B2-F1E94C3F98EC}"/>
+												</Reference>
+											</ReferenceList>
+											<ChildrenList>
+												<AudioFileSource Name="Rocket" ID="{3057E892-DA3F-4CB0-8A81-73AF30B052BD}">
+													<Language>SFX</Language>
+													<AudioFile>Rocket.wav</AudioFile>
+													<MediaIDList>
+														<MediaID ID="115250578"/>
+													</MediaIDList>
+												</AudioFileSource>
+											</ChildrenList>
+											<ObjectLists/>
+											<ActiveSourceList>
+												<ActiveSource Name="Rocket" ID="{3057E892-DA3F-4CB0-8A81-73AF30B052BD}" Platform="Linked"/>
+											</ActiveSourceList>
+										</Sound>
+									</ChildrenList>
+									<ObjectLists/>
+								</ActorMixer>
 							</ChildrenList>
 							<ObjectLists/>
 						</ActorMixer>

+ 14 - 0
Sounds/wwise_project/Actor-Mixer Hierarchy/AMPS/MX.wwu

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<WwiseDocument Type="WorkUnit" ID="{AA20B5BC-06AE-4EC5-A248-109D9EE35897}" SchemaVersion="103">
+	<AudioObjects>
+		<WorkUnit Name="MX" ID="{AA20B5BC-06AE-4EC5-A248-109D9EE35897}" PersistMode="Standalone">
+			<PropertyList>
+				<Property Name="Inclusion" Type="bool">
+					<ValueList>
+						<Value>False</Value>
+					</ValueList>
+				</Property>
+			</PropertyList>
+		</WorkUnit>
+	</AudioObjects>
+</WwiseDocument>

+ 63 - 3
Sounds/wwise_project/Events/AMPS/AMB.wwu

@@ -6,9 +6,6 @@
 				<Event Name="play_sx_amb_ext_general" ID="{118E75AA-7412-45A0-AAA9-52CD47DB9E41}">
 					<ChildrenList>
 						<Action Name="" ID="{E12EFB24-AB65-4232-BD67-8F6925C157F0}" ShortID="745775555">
-							<PropertyList>
-								<Property Name="FadeTime" Type="Real64" Value="0.3"/>
-							</PropertyList>
 							<ReferenceList>
 								<Reference Name="Target">
 									<ObjectRef Name="sx_amb_ext_generalWindLoop" ID="{F55CE3A4-96C3-4E54-8267-FBB6A47AAAE1}" WorkUnitID="{FF882DA0-D34E-47CD-9819-576540D5FB1C}"/>
@@ -56,6 +53,69 @@
 						</Action>
 					</ChildrenList>
 				</Event>
+				<Event Name="rocket" ID="{4060BEF8-E908-4BDE-AFD2-6E0FA057CD6B}">
+					<ChildrenList>
+						<Action Name="" ID="{13665353-3628-4162-B258-14BA5D07D49B}" ShortID="800090568">
+							<ReferenceList>
+								<Reference Name="Target">
+									<ObjectRef Name="Rocket" ID="{E8258E1E-BB45-4281-9C81-3174071BEEB0}" WorkUnitID="{FF882DA0-D34E-47CD-9819-576540D5FB1C}"/>
+								</Reference>
+							</ReferenceList>
+						</Action>
+						<Action Name="" ID="{6606CDFB-B3CA-40FA-B69C-FBFB4A2DBAFA}" ShortID="608537304">
+							<PropertyList>
+								<Property Name="ActionType" Type="int16" Value="36"/>
+							</PropertyList>
+							<ReferenceList>
+								<Reference Name="Target">
+									<ObjectRef Name="Rocket" ID="{E8258E1E-BB45-4281-9C81-3174071BEEB0}" WorkUnitID="{FF882DA0-D34E-47CD-9819-576540D5FB1C}"/>
+								</Reference>
+							</ReferenceList>
+						</Action>
+					</ChildrenList>
+				</Event>
+				<Event Name="future_gladiator" ID="{A437974A-51F1-4F3C-B623-6D17741CE162}">
+					<ChildrenList>
+						<Action Name="" ID="{54954584-C040-4E0F-A066-CF784DD6C169}" ShortID="1070131939">
+							<ReferenceList>
+								<Reference Name="Target">
+									<ObjectRef Name="Future Gladiator" ID="{2C0BD4CA-76EC-4714-9C88-C5364FD4361D}" WorkUnitID="{FF882DA0-D34E-47CD-9819-576540D5FB1C}"/>
+								</Reference>
+							</ReferenceList>
+						</Action>
+						<Action Name="" ID="{DB91EEB9-C99B-4004-9B5E-8BA71D82F265}" ShortID="285746269">
+							<PropertyList>
+								<Property Name="ActionType" Type="int16" Value="36"/>
+							</PropertyList>
+							<ReferenceList>
+								<Reference Name="Target">
+									<ObjectRef Name="Future Gladiator" ID="{2C0BD4CA-76EC-4714-9C88-C5364FD4361D}" WorkUnitID="{FF882DA0-D34E-47CD-9819-576540D5FB1C}"/>
+								</Reference>
+							</ReferenceList>
+						</Action>
+					</ChildrenList>
+				</Event>
+				<Event Name="beauty_flow" ID="{E24D72A5-1DCD-4C84-BA05-4D6ACA979ABC}">
+					<ChildrenList>
+						<Action Name="" ID="{67ECBB5C-B496-4BEF-80DC-C0BEDF31792E}" ShortID="780551046">
+							<ReferenceList>
+								<Reference Name="Target">
+									<ObjectRef Name="Beauty Flow" ID="{ECDF9185-197D-4EAD-BF3B-F3EAE8040A1E}" WorkUnitID="{FF882DA0-D34E-47CD-9819-576540D5FB1C}"/>
+								</Reference>
+							</ReferenceList>
+						</Action>
+						<Action Name="" ID="{2861746A-0B52-4070-87C9-45AE8E611975}" ShortID="163506992">
+							<PropertyList>
+								<Property Name="ActionType" Type="int16" Value="36"/>
+							</PropertyList>
+							<ReferenceList>
+								<Reference Name="Target">
+									<ObjectRef Name="Beauty Flow" ID="{ECDF9185-197D-4EAD-BF3B-F3EAE8040A1E}" WorkUnitID="{FF882DA0-D34E-47CD-9819-576540D5FB1C}"/>
+								</Reference>
+							</ReferenceList>
+						</Action>
+					</ChildrenList>
+				</Event>
 			</ChildrenList>
 		</WorkUnit>
 	</Events>

+ 11 - 1
Sounds/wwise_project/Events/Default O3DE Work Unit.wwu

@@ -67,7 +67,17 @@
 						</Action>
 					</ChildrenList>
 				</Event>
-				<Event Name="do_nothing" ID="{59644E92-2831-425C-ACD3-BF068AAE1F77}"/>
+				<Event Name="do_nothing" ID="{59644E92-2831-425C-ACD3-BF068AAE1F77}">
+					<ChildrenList>
+						<Action Name="" ID="{4599C36D-7735-41D4-B8C6-07C717506577}" ShortID="473161540"/>
+						<Action Name="" ID="{EA54B31A-9789-475C-B3D1-6BC334158C87}" ShortID="599963739">
+							<PropertyList>
+								<Property Name="ActionType" Type="int16" Value="36"/>
+							</PropertyList>
+							<ReferenceList/>
+						</Action>
+					</ChildrenList>
+				</Event>
 			</ChildrenList>
 		</WorkUnit>
 	</Events>

+ 3 - 0
Sounds/wwise_project/Originals/SFX/Beauty Flow.wav

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d62776f0e41ac60ad50bd82ac85c3c67b2eec5acc39cfdcdb0025a736c88c2d3
+size 76451506

+ 3 - 0
Sounds/wwise_project/Originals/SFX/Future Gladiator.wav

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:108c7168890b9bbd8b9fdac8fa66e5d85104f3b282d55c64babcaf07f2257890
+size 38283466

+ 3 - 0
Sounds/wwise_project/Originals/SFX/Rocket.wav

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:40c9d5fe79bfc3fdf40e98993b0a981c6dcad3a955af5af761a7f79c95a1fe25
+size 25924766

+ 3 - 0
Sounds/wwise_project/Originals/SFX/incompetech/Dream Catcher.wav

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3b48ae6dfc6ba1f35f5ca0fe3ffcdd2fbd768cb53bb4c3c6ec289a4bf65c4686
+size 66539678

+ 12 - 0
Sounds/wwise_project/Soundcaster Sessions/Default Work Unit.wwu

@@ -17,6 +17,10 @@
 							<ObjectRef Name="play_sx_int_defenseturret_projectile" ID="{445FBCD9-FCA2-41BE-B2E0-FF4E640AAC7B}" WorkUnitID="{CF19DCBF-DBAF-47EA-BB92-20770380FC6C}"/>
 							<Position X="0" Y="4"/>
 						</Module>
+						<Module>
+							<ObjectRef Name="beauty_flow" ID="{E24D72A5-1DCD-4C84-BA05-4D6ACA979ABC}" WorkUnitID="{DE9FC369-2076-4F07-9C00-6203DBF0184F}"/>
+							<Position X="0" Y="5"/>
+						</Module>
 						<Module>
 							<ObjectRef Name="play_sx_int_malfunctioningshieldgenerator_explo" ID="{A910A681-E6E6-47EF-9061-B9753C009A61}" WorkUnitID="{D49A7F17-5E56-4DE2-816D-4286ED6A3BE2}"/>
 							<Position X="1" Y="0"/>
@@ -29,6 +33,10 @@
 							<ObjectRef Name="stop_sx_int_defenseturret_projectile" ID="{ADF03BF2-DAFD-4FA1-BAC6-6CEC22FD0EFD}" WorkUnitID="{CF19DCBF-DBAF-47EA-BB92-20770380FC6C}"/>
 							<Position X="1" Y="4"/>
 						</Module>
+						<Module>
+							<ObjectRef Name="future_gladiator" ID="{A437974A-51F1-4F3C-B623-6D17741CE162}" WorkUnitID="{DE9FC369-2076-4F07-9C00-6203DBF0184F}"/>
+							<Position X="1" Y="5"/>
+						</Module>
 						<Module>
 							<ObjectRef Name="play_sx_player_footstep" ID="{1FFADD80-2B41-4080-BCCC-C50E8E9F54A4}" WorkUnitID="{6146481B-5849-48AD-9DBA-B2D263C55E44}"/>
 							<Position X="2" Y="1"/>
@@ -41,6 +49,10 @@
 							<ObjectRef Name="play_sx_wpn_laserpistol_fire" ID="{FA50B607-E2A8-4E18-B8FC-632C1F353C41}" WorkUnitID="{127FA651-B259-4F86-BC4D-A900F3A4CCA2}"/>
 							<Position X="2" Y="3"/>
 						</Module>
+						<Module>
+							<ObjectRef Name="rocket" ID="{4060BEF8-E908-4BDE-AFD2-6E0FA057CD6B}" WorkUnitID="{DE9FC369-2076-4F07-9C00-6203DBF0184F}"/>
+							<Position X="2" Y="5"/>
+						</Module>
 						<Module>
 							<ObjectRef Name="play_sx_player_pain" ID="{C4E4C612-D934-451D-873B-D9B4AE45A646}" WorkUnitID="{6146481B-5849-48AD-9DBA-B2D263C55E44}"/>
 							<Position X="3" Y="1"/>

+ 34 - 34
UICanvases/BasicHUD.uicanvas

@@ -504,13 +504,13 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="13558808334196379044" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Round" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="ROUND" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="32.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -6950,7 +6950,7 @@
 									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="IsExpandedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}">
 										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
 											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
@@ -11475,7 +11475,7 @@
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="32.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -12905,6 +12905,12 @@
 													<Class name="float" field="m_data" value="-142.0100250" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/SimpleAssetReference&lt;FontAsset&gt;({4953F80A-F59C-5F38-9E84-AFEB8F438CC4})::FontFileName·1/SimpleAssetReferenceBase({E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8})::BaseClass1·1/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::AssetPath·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="AZStd::string" field="m_data" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::Text·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -13074,6 +13080,12 @@
 													<Class name="float" field="m_data" value="-42.7549973" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/SimpleAssetReference&lt;FontAsset&gt;({4953F80A-F59C-5F38-9E84-AFEB8F438CC4})::FontFileName·1/SimpleAssetReferenceBase({E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8})::BaseClass1·1/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::AssetPath·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="AZStd::string" field="m_data" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::Text·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -13282,6 +13294,12 @@
 													<Class name="float" field="m_data" value="-75.0000153" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/SimpleAssetReference&lt;FontAsset&gt;({4953F80A-F59C-5F38-9E84-AFEB8F438CC4})::FontFileName·1/SimpleAssetReferenceBase({E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8})::BaseClass1·1/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::AssetPath·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="AZStd::string" field="m_data" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::Text·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -13354,6 +13372,12 @@
 													</Class>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/SimpleAssetReference&lt;FontAsset&gt;({4953F80A-F59C-5F38-9E84-AFEB8F438CC4})::FontFileName·1/SimpleAssetReferenceBase({E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8})::BaseClass1·1/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::AssetPath·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="AZStd::string" field="m_data" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17165234896122860168·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::Text·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -13579,12 +13603,6 @@
 													<Class name="Vector2" field="m_data" value="0.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 												</Class>
 											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#10132267487687110544·3/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsExpandedInEditor·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="bool" field="m_data" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-												</Class>
-											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiImageComponent({BDBEFD23-DBB4-4726-A32D-4FEAC24E51F6})#17217584308910145132·8/SimpleAssetReference&lt;TextureAsset&gt;({6E0B1C86-F66A-5D30-BCBB-0F9EA199E4AF})::SpritePath·1/SimpleAssetReferenceBase({E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8})::BaseClass1·1/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::AssetPath·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -14077,12 +14095,6 @@
 													<Class name="Vector2" field="m_data" value="1.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 												</Class>
 											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#10132267487687110544·3/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsExpandedInEditor·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="bool" field="m_data" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-												</Class>
-											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#10132267487687110544·3/AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;({0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62})::ChildEntityIdOrder·0/ChildEntityIdOrderEntry({D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2})#22899931024049·1/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -14580,12 +14592,6 @@
 													<Class name="Vector2" field="m_data" value="0.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 												</Class>
 											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#10132267487687110544·3/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsExpandedInEditor·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="bool" field="m_data" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-												</Class>
-											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#10132267487687110544·3/AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;({0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62})::ChildEntityIdOrder·0/ChildEntityIdOrderEntry({D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2})#22917110893233·1/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -14808,12 +14814,6 @@
 													<Class name="Vector2" field="m_data" value="0.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 												</Class>
 											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTransform2dComponent({2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6})#15333478216472190740·3/Anchors({65D4346C-FB16-4CB0-9BDC-1185B122C4A9})::Anchors·0/float({EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D})::right·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="float" field="m_data" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-												</Class>
-											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::MetadataEntities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#6767449941144·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/EditorInspectorComponent({47DE3DDA-50C5-4F50-B1DB-BA4AE66AB056})#16621177478594218240·2/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -14827,6 +14827,12 @@
 													</Class>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTransform2dComponent({2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6})#15333478216472190740·3/Anchors({65D4346C-FB16-4CB0-9BDC-1185B122C4A9})::Anchors·0/float({EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D})::right·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="float" field="m_data" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::MetadataEntities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#6922068763800·2/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsDependencyReady·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -14932,12 +14938,6 @@
 													<Class name="float" field="m_data" value="-10.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 												</Class>
 											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#10132267487687110544·3/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsExpandedInEditor·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="bool" field="m_data" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-												</Class>
-											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#14829820523140734107·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiImageComponent({BDBEFD23-DBB4-4726-A32D-4FEAC24E51F6})#17217584308910145132·8/Color({7894072A-9050-4F0F-901B-34B1A0D29417})::Color·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">

+ 2 - 2
UICanvases/InGameMenu/QuitButton.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:52055f14bb22309ec55c71a389027c498015ac6ae4c122792f175e78301fbe9d
-size 115844
+oid sha256:32fd4b86cbb3d0e94f30dc9b7581657d0654b7808c288e55f5e8229e9a889b96
+size 78073

+ 3 - 0
UICanvases/InGameMenu/QuitButtonDown.png

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:229750df82f1f8c6748a8e7d52ad3ff6688643287fc9c3385acc7886852912ee
+size 80048

+ 2 - 2
UICanvases/InGameMenu/QuitButtonHover.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:71d25fec5da059b2163ea7000f6501329077751e8e9ca0f834bf58611dbed878
-size 121208
+oid sha256:3bc30c61221e6fe40669474b54b8a85dca3be234e9ce0f74f9d966ab9af986a5
+size 85039

+ 58 - 52
UICanvases/Lobby.uicanvas

@@ -299,7 +299,7 @@
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/default-ui.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="32.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -374,7 +374,7 @@
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/default-ui.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="24.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -449,7 +449,7 @@
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/default-ui.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="24.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -1631,50 +1631,50 @@
 									<Class name="AZStd::unordered_map&lt;EntityId, EntityId, AZStd::hash&lt;EntityId&gt;, AZStd::equal_to&lt;EntityId&gt;, allocator&gt;" field="EntityIdMap" type="{D33569A9-EFFC-566C-8CCC-74D6E086A1B0}">
 										<Class name="AZStd::pair&lt;EntityId, EntityId&gt;" field="element" type="{30DDE93C-E899-5AB9-856D-FC456D054EDB}">
 											<Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="1849712387224" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="17225703251056972424" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 											<Class name="EntityId" field="value2" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="2819297901199" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="2802118032015" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 										</Class>
 										<Class name="AZStd::pair&lt;EntityId, EntityId&gt;" field="element" type="{30DDE93C-E899-5AB9-856D-FC456D054EDB}">
 											<Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="17225707533139366536" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="17225706347728392840" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 											<Class name="EntityId" field="value2" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="2815002933903" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="2810707966607" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 										</Class>
 										<Class name="AZStd::pair&lt;EntityId, EntityId&gt;" field="element" type="{30DDE93C-E899-5AB9-856D-FC456D054EDB}">
 											<Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="1854007354520" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="1845417419928" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 											<Class name="EntityId" field="value2" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="2823592868495" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="2827887835791" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 										</Class>
 										<Class name="AZStd::pair&lt;EntityId, EntityId&gt;" field="element" type="{30DDE93C-E899-5AB9-856D-FC456D054EDB}">
 											<Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="1845417419928" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="1854007354520" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 											<Class name="EntityId" field="value2" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="2827887835791" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="2823592868495" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 										</Class>
 										<Class name="AZStd::pair&lt;EntityId, EntityId&gt;" field="element" type="{30DDE93C-E899-5AB9-856D-FC456D054EDB}">
 											<Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="17225703251056972424" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="1849712387224" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 											<Class name="EntityId" field="value2" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="2802118032015" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="2819297901199" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 										</Class>
 										<Class name="AZStd::pair&lt;EntityId, EntityId&gt;" field="element" type="{30DDE93C-E899-5AB9-856D-FC456D054EDB}">
 											<Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="17225706347728392840" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="17225707533139366536" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 											<Class name="EntityId" field="value2" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-												<Class name="AZ::u64" field="id" value="2810707966607" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												<Class name="AZ::u64" field="id" value="2815002933903" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 											</Class>
 										</Class>
 									</Class>
@@ -1736,6 +1736,12 @@
 													</Class>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225706347728392840·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/SimpleAssetReference&lt;FontAsset&gt;({4953F80A-F59C-5F38-9E84-AFEB8F438CC4})::FontFileName·1/SimpleAssetReferenceBase({E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8})::BaseClass1·1/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::AssetPath·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="AZStd::string" field="m_data" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225703251056972424·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#16339829923336444153·3/unsigned int({43DA906B-7DEF-4CA8-9790-854106D3F983})::Id·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -1758,6 +1764,37 @@
 													<Class name="float" field="m_data" value="14.1209602" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225707533139366536·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTransform2dComponent({2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6})#12566577726618989226·3/Offsets({F681BA9D-245C-4630-B20E-05DD752FAD57})::Offsets·0/float({EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D})::left·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="float" field="m_data" value="14.7500000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+												</Class>
+											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225703251056972424·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextInputComponent({2CB3872B-D2B4-4DDB-B39A-97492310AE11})#18295482324565764378·8/UiInteractableComponent({A42EB486-1C89-434C-AD22-A3FC6CEEC46F})::BaseClass1·2/AZStd::vector&lt;UiInteractableStateAction*, allocator&gt;({BE13CF75-3B94-5569-AEAD-F31E0067762B})::HoverStateActions·0/UiInteractableStateAlpha({ABCD5D45-CC47-4C17-8D21-9471032618F6})#0·2/EntityId({6383F1D3-BB27-4E6B-A49A-6409B2059EAA})::TargetEntity·1/AZ::u64({D6597933-47CD-4FC8-B911-63F3E2B0993A})::id·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="AZ::u64" field="m_data" value="2806412999311" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+												</Class>
+											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::MetadataEntities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#1849712387224·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/EditorEntitySortComponent({6EA1E03D-68B2-466D-97F7-83998C8C27F0})#9875838147789556271·2/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="EditorEntitySortComponent" field="m_data" version="2" type="{6EA1E03D-68B2-466D-97F7-83998C8C27F0}">
+														<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+															<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+																<Class name="AZ::u64" field="Id" value="9875838147789556271" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+															</Class>
+														</Class>
+														<Class name="AZStd::vector&lt;EntityOrderEntry, allocator&gt;" field="ChildEntityOrderEntryArray" type="{BE163120-C1ED-5F69-A650-DC2528A8FF94}"/>
+													</Class>
+												</Class>
+											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::MetadataEntities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#1854007354520·2/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsDependencyReady·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="bool" field="m_data" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225706347728392840·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTransform2dComponent({2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6})#12566577726618989226·3/Offsets({F681BA9D-245C-4630-B20E-05DD752FAD57})::Offsets·0/float({EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D})::right·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -1807,6 +1844,12 @@
 													<Class name="int" field="m_data" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
 												</Class>
 											</Class>
+											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
+												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225707533139366536·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextComponent({5B3FB2A7-5DC4-4033-A970-001CEC85B6C4})#3068610810953516373·9/SimpleAssetReference&lt;FontAsset&gt;({4953F80A-F59C-5F38-9E84-AFEB8F438CC4})::FontFileName·1/SimpleAssetReferenceBase({E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8})::BaseClass1·1/AZStd::string({03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9})::AssetPath·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
+												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
+													<Class name="AZStd::string" field="m_data" value="fonts/roboto/roboto-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+												</Class>
+											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225703251056972424·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTransform2dComponent({2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6})#5295950372157630944·3/Offsets({F681BA9D-245C-4630-B20E-05DD752FAD57})::Offsets·0/float({EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D})::top·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -1867,12 +1910,6 @@
 													<Class name="float" field="m_data" value="-255.0050049" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 												</Class>
 											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225703251056972424·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#16339829923336444153·3/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsExpandedInEditor·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="bool" field="m_data" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-												</Class>
-											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::MetadataEntities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#1854007354520·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/EditorDisabledCompositionComponent({E77AE6AC-897D-4035-8353-637449B6DCFB})#15370301212040888674·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
@@ -1961,37 +1998,6 @@
 													</Class>
 												</Class>
 											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225703251056972424·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTextInputComponent({2CB3872B-D2B4-4DDB-B39A-97492310AE11})#18295482324565764378·8/UiInteractableComponent({A42EB486-1C89-434C-AD22-A3FC6CEEC46F})::BaseClass1·2/AZStd::vector&lt;UiInteractableStateAction*, allocator&gt;({BE13CF75-3B94-5569-AEAD-F31E0067762B})::HoverStateActions·0/UiInteractableStateAlpha({ABCD5D45-CC47-4C17-8D21-9471032618F6})#0·2/EntityId({6383F1D3-BB27-4E6B-A49A-6409B2059EAA})::TargetEntity·1/AZ::u64({D6597933-47CD-4FC8-B911-63F3E2B0993A})::id·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="AZ::u64" field="m_data" value="2806412999311" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-												</Class>
-											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225707533139366536·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiTransform2dComponent({2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6})#12566577726618989226·3/Offsets({F681BA9D-245C-4630-B20E-05DD752FAD57})::Offsets·0/float({EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D})::left·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="float" field="m_data" value="14.7500000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-												</Class>
-											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::MetadataEntities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#1849712387224·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/EditorEntitySortComponent({6EA1E03D-68B2-466D-97F7-83998C8C27F0})#9875838147789556271·2/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="EditorEntitySortComponent" field="m_data" version="2" type="{6EA1E03D-68B2-466D-97F7-83998C8C27F0}">
-														<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
-															<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-																<Class name="AZ::u64" field="Id" value="9875838147789556271" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-															</Class>
-														</Class>
-														<Class name="AZStd::vector&lt;EntityOrderEntry, allocator&gt;" field="ChildEntityOrderEntryArray" type="{BE163120-C1ED-5F69-A650-DC2528A8FF94}"/>
-													</Class>
-												</Class>
-											</Class>
-											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
-												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::MetadataEntities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#1854007354520·2/bool({A0CA880C-AFE4-43CB-926C-59AC48496112})::IsDependencyReady·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
-												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}">
-													<Class name="bool" field="m_data" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-												</Class>
-											</Class>
 											<Class name="AZStd::pair&lt;AddressType, AZStd::any&gt;" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
 												<Class name="AddressType" field="value1" value="AZStd::vector&lt;AZ::Entity*, allocator&gt;({21786AF0-2606-5B9A-86EB-0892E2820E6C})::Entities·0/AZ::Entity({75651658-8663-478D-9090-2432DFCAFA44})#17225703251056972424·2/AZStd::vector&lt;AZ::Component*, allocator&gt;({13D58FF9-1088-5C69-9A1F-C2A144B57B78})::Components·0/UiElementComponent({4A97D63E-CE7A-45B6-AAE4-102DB4334688})#16339829923336444153·3/AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;({0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62})::ChildEntityIdOrder·0/ChildEntityIdOrderEntry({D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2})#17225703238172070536·1/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
 												<Class name="AZStd::any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>

+ 2 - 2
UICanvases/Scoreboard/QuitButton.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:52055f14bb22309ec55c71a389027c498015ac6ae4c122792f175e78301fbe9d
-size 115844
+oid sha256:32fd4b86cbb3d0e94f30dc9b7581657d0654b7808c288e55f5e8229e9a889b96
+size 78073

+ 3 - 0
UICanvases/Scoreboard/QuitButtonDown.png

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:229750df82f1f8c6748a8e7d52ad3ff6688643287fc9c3385acc7886852912ee
+size 80048

+ 2 - 2
UICanvases/Scoreboard/QuitButtonHover.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:71d25fec5da059b2163ea7000f6501329077751e8e9ca0f834bf58611dbed878
-size 121208
+oid sha256:3bc30c61221e6fe40669474b54b8a85dca3be234e9ce0f74f9d966ab9af986a5
+size 85039

+ 57 - 35
UICanvases/Settings.uicanvas

@@ -86,6 +86,28 @@
 							<Class name="AZ::u64" field="id" value="16687506677739" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 						</Class>
 					</Class>
+					<Class name="UiToggle" field="Fullscreen" type="{60AD7DDE-1730-41D8-BB82-630FF8008370}">
+						<Class name="EntityId" field="Label" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+							<Class name="AZ::u64" field="id" value="16730456350699" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+						</Class>
+						<Class name="EntityId" field="LeftButton" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+							<Class name="AZ::u64" field="id" value="16739046285291" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+						</Class>
+						<Class name="EntityId" field="RightButton" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+							<Class name="AZ::u64" field="id" value="16743341252587" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+						</Class>
+					</Class>
+					<Class name="UiToggle" field="Resolution" type="{60AD7DDE-1730-41D8-BB82-630FF8008370}">
+						<Class name="EntityId" field="Label" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+							<Class name="AZ::u64" field="id" value="16786290925547" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+						</Class>
+						<Class name="EntityId" field="LeftButton" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+							<Class name="AZ::u64" field="id" value="16794880860139" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+						</Class>
+						<Class name="EntityId" field="RightButton" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+							<Class name="AZ::u64" field="id" value="16799175827435" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+						</Class>
+					</Class>
 				</Class>
 			</Class>
 			<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
@@ -1095,7 +1117,7 @@
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -1241,9 +1263,9 @@
 									</Class>
 									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
 										<Class name="float" field="left" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-										<Class name="float" field="top" value="-71.8750000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 										<Class name="float" field="right" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-										<Class name="float" field="bottom" value="28.1250038" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									</Class>
 									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -1266,16 +1288,16 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="4000596796298634214" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Low" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="DirectX 12" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="0.0000000 0.0000000 0.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
-									<Class name="float" field="FontSize" value="80.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="unsigned int" field="EffectIndex" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 									<Class name="int" field="TextHAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
 									<Class name="int" field="TextVAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
@@ -1514,7 +1536,7 @@
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -1660,9 +1682,9 @@
 									</Class>
 									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
 										<Class name="float" field="left" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-										<Class name="float" field="top" value="-71.8750000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 										<Class name="float" field="right" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-										<Class name="float" field="bottom" value="28.1250038" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									</Class>
 									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -1685,16 +1707,16 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="4000596796298634214" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Low" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="Medium (1K)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="0.0000000 0.0000000 0.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
-									<Class name="float" field="FontSize" value="80.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="unsigned int" field="EffectIndex" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 									<Class name="int" field="TextHAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
 									<Class name="int" field="TextVAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
@@ -1933,7 +1955,7 @@
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -2079,9 +2101,9 @@
 									</Class>
 									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
 										<Class name="float" field="left" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-										<Class name="float" field="top" value="-71.8750000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 										<Class name="float" field="right" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
-										<Class name="float" field="bottom" value="28.1250038" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									</Class>
 									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -2104,16 +2126,16 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="4000596796298634214" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Low" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="40" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="0.0000000 0.0000000 0.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
-									<Class name="float" field="FontSize" value="80.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="unsigned int" field="EffectIndex" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 									<Class name="int" field="TextHAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
 									<Class name="int" field="TextVAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
@@ -3835,11 +3857,11 @@
 										<Class name="AZ::u64" field="Id" value="10674354919225820364" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
 									<Class name="unsigned int" field="Id" value="176" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-									<Class name="bool" field="IsEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="IsVisibleInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="IsExpandedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}">
 										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
 											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
@@ -3936,13 +3958,13 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="3068610810953516373" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Setting 4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="Fullscreen" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -4113,13 +4135,13 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="4000596796298634214" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Low" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="Windowed" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="0.0000000 0.0000000 0.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="80.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -4177,8 +4199,8 @@
 										<Class name="AZ::u64" field="Id" value="7398167135878938608" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
 									<Class name="unsigned int" field="Id" value="180" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
@@ -4258,7 +4280,7 @@
 									<Class name="bool" field="IsVisibleInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="IsExpandedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}">
 										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
 											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
@@ -4355,13 +4377,13 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="3068610810953516373" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Setting 5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="Resolution" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -4532,13 +4554,13 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="4000596796298634214" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="Low" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="1280 x 720" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="0.0000000 0.0000000 0.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="fonts/vera-bold.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/anton/anton-regular.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
 									<Class name="float" field="FontSize" value="80.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
@@ -4596,8 +4618,8 @@
 										<Class name="AZ::u64" field="Id" value="7398167135878938608" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
 									<Class name="unsigned int" field="Id" value="187" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
@@ -4677,7 +4699,7 @@
 									<Class name="bool" field="IsVisibleInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-									<Class name="bool" field="IsExpandedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}">
 										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
 											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 312 - 272
UICanvases/StartMenu.uicanvas


+ 2 - 2
UICanvases/StartMenu/HostGameButton.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:cf2034a10dee84b6026372b8b492cb79929e970f481b2659a5d72429b7934495
-size 55112
+oid sha256:0d381f6912332344ba8a8f942d628a9e93b92f672d64006cdcd6e314a3b9fd75
+size 55366

+ 2 - 2
UICanvases/StartMenu/HostGameButtonDown.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f1345ebe83362361416c4cb2952244f6f049d0be770ad436802b5778aae276e0
-size 64758
+oid sha256:5481290fa0eb7cd6d336c67bc339302a75ed4e07211eaf8d28a9b21d7a158add
+size 70987

+ 2 - 2
UICanvases/StartMenu/HostGameButtonHover.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:385aa460876d55de27fccf2250d8a8577348a26fa66f188fe67ecc98b55274ef
-size 65481
+oid sha256:8c65c8033682183537cd8234cb8d79bcae39aaba71b41c021627a1dcb4fbf9a3
+size 55491

+ 2 - 2
UICanvases/StartMenu/IPWindow.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2b4775d11512d1d7eb39dbac7487b0bd636d04dda9369bbbc650d70eb47b40dc
-size 7376
+oid sha256:6a6ceb4861bc8cd3de251a83a39ddfc2b4d1e4119c0ad1e60f9a1bb67403ac32
+size 18913

+ 2 - 2
UICanvases/StartMenu/JoinGameButton.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:14f8f0a4c8a37d1b7a8623f71ae35ab26aab2b1879284106471b6ac9952ac5eb
-size 63250
+oid sha256:13ac89e808b368c94a55185b9d78ab200cb8fc0d8b54f56632e5752c0712fe71
+size 54950

+ 2 - 2
UICanvases/StartMenu/JoinGameButtonDown.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5b3978b732612faa1b9d8cdfcbfea0c8af7f181d0ff2d81c3757705ee263375a
-size 61847
+oid sha256:e3207a39a6887c69d3e03f16b3c250bb423f2d2965ca01b18125c73098bbdc2f
+size 54818

+ 2 - 2
UICanvases/StartMenu/JoinGameButtonHover.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:622286af70fcba84ebca66dc0979560c18b3ea3600f489aec412b0b8e1dd7d24
-size 66243
+oid sha256:6c4726dda6f27c198db2fbb1bd3c110cd59704e94e4a3ffa99cd3d6d2c47791d
+size 55725

+ 2 - 2
UICanvases/StartMenu/QuitButton.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3b4fe44deccce80cbc52135c1ae2d54c3bc440152dd397a86ca46b5f89a9948a
-size 94616
+oid sha256:32fd4b86cbb3d0e94f30dc9b7581657d0654b7808c288e55f5e8229e9a889b96
+size 78073

+ 2 - 2
UICanvases/StartMenu/QuitButtonDown.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c05bf1c014c7dea29ca188f0f57ff8a4b8b9a40cb23d125744be35c1e4d459ab
-size 93711
+oid sha256:229750df82f1f8c6748a8e7d52ad3ff6688643287fc9c3385acc7886852912ee
+size 80048

+ 2 - 2
UICanvases/StartMenu/QuitButtonHover.png

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9908ca5c6047589f704508d3dce04cf315504cd82b425df12925d27326d36277
-size 91710
+oid sha256:3bc30c61221e6fe40669474b54b8a85dca3be234e9ce0f74f9d966ab9af986a5
+size 85039

+ 40 - 0
credits.md

@@ -0,0 +1,40 @@
+# O3DE 2305 - Initial Release Contributors
+
+* Galib Arrieta (lumbermixalot) - Programming
+* Mike Balfour - Programming
+* Karl Berg - Programming
+* Ben Black - Art, Tools
+* Alex Damarjian - Art, Animation
+* Jonny Galloway (HogJonny) - Technical Art Direction, Lighting, Documentation
+* Brendan Jackson - Programming
+* Ahmad Kareem - Programming
+* Olex Lozitskiy - Programming
+* Doug McDiarmid - Programming
+* @lumberyard-employee-dm - Programming
+* Darrin McPherson - Design Leadership, Game & Level Design, Production
+* Sidharth Moudgil - Programming
+* Sergey Pereslavtsev - Programming
+* Alex Peterson - Programming
+* lmbr-pip - Programming Leadership, Production
+* Ken Pruiksma - Programming
+* Rajiv Puuvada - Programming
+* Qing Tao - Programming
+* Joshua Rainbolt - UI Direction, UI Design
+* Chris Santora - Programming
+* Starr Shaw - Art, UI
+* Allie Stanko (Allisaurus) - Programming
+* Joe Stankowicz - Programming
+* Gene Walters - Programming
+
+## Special Thanks
+
+* Adobe for contributing the Y-Bot character model and its animations.
+* KitBash3D for contributing the High Tech Streets set.
+* Hexany Audio & Owen Cooper for creating the game’s audio.
+* PopcornFX for creating the game’s VFX.
+
+## Music
+* "Rocket", "Beauty Flow", "Future Gladiator" Kevin MacLeod (incompetech.com)
+Licensed under Creative Commons: By Attribution 4.0 License
+http://creativecommons.org/licenses/by/4.0/
+

+ 9 - 0
libs/gameaudio/wwise/multiplayersample_controls.xml

@@ -30,6 +30,15 @@
 		<ATLTrigger atl_name="Play_Sound_Gun_Firing" path="z_placeholders">
 			<WwiseEvent wwise_name="Play_Sound_Gun_Firing"/>
 		</ATLTrigger>
+		<ATLTrigger atl_name="rocket" path="Events/MUS">
+			<WwiseEvent wwise_name="rocket"/>
+		</ATLTrigger>
+		<ATLTrigger atl_name="future_gladiator" path="Events/MUS">
+			<WwiseEvent wwise_name="future_gladiator"/>
+		</ATLTrigger>
+		<ATLTrigger atl_name="beauty_flow" path="Events/MUS">
+			<WwiseEvent wwise_name="beauty_flow"/>
+		</ATLTrigger>
 		<ATLTrigger atl_name="set_state_game_none" path="Events/_Globals/States/Game">
 			<WwiseEvent wwise_name="set_state_game_none"/>
 		</ATLTrigger>

+ 239 - 63
scriptcanvas/ClientDisconnect.scriptcanvas

@@ -5,7 +5,7 @@
     "ClassData": {
         "m_scriptCanvas": {
             "Id": {
-                "id": 63723511289631
+                "id": 41296274672356
             },
             "Name": "Script Canvas Graph",
             "Components": {
@@ -16,7 +16,7 @@
                         "m_nodes": [
                             {
                                 "Id": {
-                                    "id": 63744986126111
+                                    "id": 41317749508836
                                 },
                                 "Name": "SC-Node(ExecuteConsoleCommand)",
                                 "Components": {
@@ -100,7 +100,7 @@
                             },
                             {
                                 "Id": {
-                                    "id": 63740691158815
+                                    "id": 41313454541540
                                 },
                                 "Name": "EBusEventHandler",
                                 "Components": {
@@ -341,7 +341,88 @@
                             },
                             {
                                 "Id": {
-                                    "id": 63736396191519
+                                    "id": 47163199998692
+                                },
+                                "Name": "SC-Node(ExecuteConsoleCommand)",
+                                "Components": {
+                                    "Component_[17382034980001092472]": {
+                                        "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method",
+                                        "Id": 17382034980001092472,
+                                        "Slots": [
+                                            {
+                                                "id": {
+                                                    "m_id": "{365E1DAE-26DC-42E8-9DC2-E4AE1A04B08F}"
+                                                },
+                                                "contracts": [
+                                                    {
+                                                        "$type": "SlotTypeContract"
+                                                    }
+                                                ],
+                                                "slotName": "String",
+                                                "Descriptor": {
+                                                    "ConnectionType": 1,
+                                                    "SlotType": 2
+                                                },
+                                                "DataType": 1
+                                            },
+                                            {
+                                                "id": {
+                                                    "m_id": "{E061744B-A882-4069-B606-F3F0036C2941}"
+                                                },
+                                                "contracts": [
+                                                    {
+                                                        "$type": "SlotTypeContract"
+                                                    }
+                                                ],
+                                                "slotName": "In",
+                                                "Descriptor": {
+                                                    "ConnectionType": 1,
+                                                    "SlotType": 1
+                                                }
+                                            },
+                                            {
+                                                "id": {
+                                                    "m_id": "{C7F2B1D8-93A2-4B0B-98B2-BFDE5E7E34B1}"
+                                                },
+                                                "contracts": [
+                                                    {
+                                                        "$type": "SlotTypeContract"
+                                                    }
+                                                ],
+                                                "slotName": "Out",
+                                                "Descriptor": {
+                                                    "ConnectionType": 2,
+                                                    "SlotType": 1
+                                                }
+                                            }
+                                        ],
+                                        "Datums": [
+                                            {
+                                                "isOverloadedStorage": false,
+                                                "scriptCanvasType": {
+                                                    "m_type": 5
+                                                },
+                                                "isNullPointer": false,
+                                                "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string",
+                                                "value": "disconnect",
+                                                "label": "Command"
+                                            }
+                                        ],
+                                        "methodType": 0,
+                                        "methodName": "ExecuteConsoleCommand",
+                                        "className": "ConsoleRequestBus",
+                                        "inputSlots": [
+                                            {
+                                                "m_id": "{365E1DAE-26DC-42E8-9DC2-E4AE1A04B08F}"
+                                            }
+                                        ],
+                                        "prettyClassName": "ConsoleRequestBus"
+                                    }
+                                }
+                            },
+                            {
+                                "Id": {
+                                    "id": 41309159574244
                                 },
                                 "Name": "SC-Node(EqualTo)",
                                 "Components": {
@@ -490,7 +571,7 @@
                             },
                             {
                                 "Id": {
-                                    "id": 63732101224223
+                                    "id": 41304864606948
                                 },
                                 "Name": "SC-Node(TimeDelayNodeableNode)",
                                 "Components": {
@@ -631,7 +712,7 @@
                             },
                             {
                                 "Id": {
-                                    "id": 63727806256927
+                                    "id": 41300569639652
                                 },
                                 "Name": "ReceiveScriptEvent",
                                 "Components": {
@@ -929,35 +1010,7 @@
                         "m_connections": [
                             {
                                 "Id": {
-                                    "id": 63749281093407
-                                },
-                                "Name": "srcEndpoint=(TimeDelay: Done), destEndpoint=(ExecuteConsoleCommand: In)",
-                                "Components": {
-                                    "Component_[18339910822672896418]": {
-                                        "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
-                                        "Id": 18339910822672896418,
-                                        "sourceEndpoint": {
-                                            "nodeId": {
-                                                "id": 63732101224223
-                                            },
-                                            "slotId": {
-                                                "m_id": "{5BB44F12-9009-4193-961B-8E2F6CC538FB}"
-                                            }
-                                        },
-                                        "targetEndpoint": {
-                                            "nodeId": {
-                                                "id": 63744986126111
-                                            },
-                                            "slotId": {
-                                                "m_id": "{8C46EFC2-676D-4B14-A5F0-B58404C64CD0}"
-                                            }
-                                        }
-                                    }
-                                }
-                            },
-                            {
-                                "Id": {
-                                    "id": 63753576060703
+                                    "id": 41326339443428
                                 },
                                 "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(Receive Script Event: Connect)",
                                 "Components": {
@@ -966,7 +1019,7 @@
                                         "Id": 9151944094509384703,
                                         "sourceEndpoint": {
                                             "nodeId": {
-                                                "id": 63740691158815
+                                                "id": 41313454541540
                                             },
                                             "slotId": {
                                                 "m_id": "{ECD88DEB-EE0D-4ECC-8583-48E97A5113B2}"
@@ -974,7 +1027,7 @@
                                         },
                                         "targetEndpoint": {
                                             "nodeId": {
-                                                "id": 63727806256927
+                                                "id": 41300569639652
                                             },
                                             "slotId": {
                                                 "m_id": "{739ED44A-BACE-4B23-9F76-DED2F3A7457C}"
@@ -985,7 +1038,7 @@
                             },
                             {
                                 "Id": {
-                                    "id": 63757871027999
+                                    "id": 41330634410724
                                 },
                                 "Name": "srcEndpoint=(Receive Script Event: ScreenToShow), destEndpoint=(Equal To (==): Value A)",
                                 "Components": {
@@ -994,7 +1047,7 @@
                                         "Id": 17600078873613684267,
                                         "sourceEndpoint": {
                                             "nodeId": {
-                                                "id": 63727806256927
+                                                "id": 41300569639652
                                             },
                                             "slotId": {
                                                 "m_id": "{25FC9880-C3C6-4432-AA4F-1C894497F22D}"
@@ -1002,7 +1055,7 @@
                                         },
                                         "targetEndpoint": {
                                             "nodeId": {
-                                                "id": 63736396191519
+                                                "id": 41309159574244
                                             },
                                             "slotId": {
                                                 "m_id": "{DBE1F264-1D99-4604-8070-B4ADFC8A2A1C}"
@@ -1013,7 +1066,7 @@
                             },
                             {
                                 "Id": {
-                                    "id": 63762165995295
+                                    "id": 41334929378020
                                 },
                                 "Name": "srcEndpoint=(Equal To (==): True), destEndpoint=(TimeDelay: Start)",
                                 "Components": {
@@ -1022,7 +1075,7 @@
                                         "Id": 10150836379398510596,
                                         "sourceEndpoint": {
                                             "nodeId": {
-                                                "id": 63736396191519
+                                                "id": 41309159574244
                                             },
                                             "slotId": {
                                                 "m_id": "{4C285E52-9795-47E5-90A5-70936454D2AF}"
@@ -1030,7 +1083,7 @@
                                         },
                                         "targetEndpoint": {
                                             "nodeId": {
-                                                "id": 63732101224223
+                                                "id": 41304864606948
                                             },
                                             "slotId": {
                                                 "m_id": "{89844691-7E99-4E4B-A2CC-7920469B3351}"
@@ -1041,7 +1094,7 @@
                             },
                             {
                                 "Id": {
-                                    "id": 71514581964575
+                                    "id": 41339224345316
                                 },
                                 "Name": "srcEndpoint=(Receive Script Event: ExecutionSlot:SetActiveScreen), destEndpoint=(Equal To (==): In)",
                                 "Components": {
@@ -1050,7 +1103,7 @@
                                         "Id": 5974153072275692349,
                                         "sourceEndpoint": {
                                             "nodeId": {
-                                                "id": 63727806256927
+                                                "id": 41300569639652
                                             },
                                             "slotId": {
                                                 "m_id": "{5C46F887-23F6-4A14-9ADD-03B5E0543328}"
@@ -1058,7 +1111,7 @@
                                         },
                                         "targetEndpoint": {
                                             "nodeId": {
-                                                "id": 63736396191519
+                                                "id": 41309159574244
                                             },
                                             "slotId": {
                                                 "m_id": "{DC73B288-02D4-4667-A0E5-3ED395DF8DC2}"
@@ -1066,12 +1119,68 @@
                                         }
                                     }
                                 }
+                            },
+                            {
+                                "Id": {
+                                    "id": 52205491604196
+                                },
+                                "Name": "srcEndpoint=(TimeDelay: Done), destEndpoint=(ExecuteConsoleCommand: In)",
+                                "Components": {
+                                    "Component_[15414995311809178445]": {
+                                        "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+                                        "Id": 15414995311809178445,
+                                        "sourceEndpoint": {
+                                            "nodeId": {
+                                                "id": 41304864606948
+                                            },
+                                            "slotId": {
+                                                "m_id": "{5BB44F12-9009-4193-961B-8E2F6CC538FB}"
+                                            }
+                                        },
+                                        "targetEndpoint": {
+                                            "nodeId": {
+                                                "id": 47163199998692
+                                            },
+                                            "slotId": {
+                                                "m_id": "{E061744B-A882-4069-B606-F3F0036C2941}"
+                                            }
+                                        }
+                                    }
+                                }
+                            },
+                            {
+                                "Id": {
+                                    "id": 53103139769060
+                                },
+                                "Name": "srcEndpoint=(ExecuteConsoleCommand: Out), destEndpoint=(ExecuteConsoleCommand: In)",
+                                "Components": {
+                                    "Component_[13185958598790311973]": {
+                                        "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+                                        "Id": 13185958598790311973,
+                                        "sourceEndpoint": {
+                                            "nodeId": {
+                                                "id": 47163199998692
+                                            },
+                                            "slotId": {
+                                                "m_id": "{C7F2B1D8-93A2-4B0B-98B2-BFDE5E7E34B1}"
+                                            }
+                                        },
+                                        "targetEndpoint": {
+                                            "nodeId": {
+                                                "id": 41317749508836
+                                            },
+                                            "slotId": {
+                                                "m_id": "{8C46EFC2-676D-4B14-A5F0-B58404C64CD0}"
+                                            }
+                                        }
+                                    }
+                                }
                             }
                         ],
                         "m_scriptEventAssets": [
                             [
                                 {
-                                    "id": 63727806256927
+                                    "id": 41300569639652
                                 },
                                 {}
                             ]
@@ -1086,13 +1195,49 @@
                     "GraphCanvasData": [
                         {
                             "Key": {
-                                "id": 63723511289631
+                                "id": 41296274672356
                             },
                             "Value": {
                                 "ComponentData": {
                                     "{5F84B500-8C45-40D1-8EFC-A5306B241444}": {
                                         "$type": "SceneComponentSaveData",
                                         "Constructs": [
+                                            {
+                                                "Type": 1,
+                                                "DataContainer": {
+                                                    "ComponentData": {
+                                                        "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+                                                            "$type": "NodeSaveData"
+                                                        },
+                                                        "{524D8380-AC09-444E-870E-9CEF2535B4A2}": {
+                                                            "$type": "CommentNodeTextSaveData",
+                                                            "Comment": "The \"disconnect\" is required here because once a client has connected to a server for the first time, it won't be able to initiate a level load without calling a client-side disconnect to reset the state.",
+                                                            "BackgroundColor": [
+                                                                0.9800000190734863,
+                                                                0.9700000286102295,
+                                                                0.6499999761581421
+                                                            ],
+                                                            "FontSettings": {
+                                                                "PixelSize": 16
+                                                            }
+                                                        },
+                                                        "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+                                                            "$type": "GeometrySaveData",
+                                                            "Position": [
+                                                                960.0,
+                                                                220.0
+                                                            ]
+                                                        },
+                                                        "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+                                                            "$type": "StylingComponentSaveData"
+                                                        },
+                                                        "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+                                                            "$type": "PersistentIdComponentSaveData",
+                                                            "PersistentId": "{587F771B-FC38-4C05-8A31-6002D71FF144}"
+                                                        }
+                                                    }
+                                                }
+                                            },
                                             {
                                                 "Type": 3,
                                                 "DataContainer": {
@@ -1114,23 +1259,23 @@
                                                         },
                                                         "{6F4811ED-BD83-4A2A-8831-58EEA4020D57}": {
                                                             "$type": "NodeGroupFrameComponentSaveData",
-                                                            "DisplayHeight": 520.0,
-                                                            "DisplayWidth": 2260.0,
+                                                            "DisplayHeight": 547.0,
+                                                            "DisplayWidth": 2400.0,
                                                             "PersistentGroupedId": [
-                                                                "{6FDF698F-ACB9-4747-AA27-E23A3DA8FEC3}",
-                                                                "{1E80C9AA-C1A2-4313-9310-1EE8E5127DC8}",
-                                                                "{4B7B33DD-6E65-4A51-A4B7-F2E91BA9DAB4}",
+                                                                "{89868DAB-1712-4C78-AE33-0014BDC142EA}",
                                                                 "{282BB238-27B1-482D-A39E-A42B99C55EA9}",
-                                                                "{E008D29B-1194-4DD3-83CD-71A9BD9442C5}",
+                                                                "{4B7B33DD-6E65-4A51-A4B7-F2E91BA9DAB4}",
+                                                                "{C21F9316-8419-4C35-BAFE-536829F5C78A}",
+                                                                "{1E80C9AA-C1A2-4313-9310-1EE8E5127DC8}",
                                                                 "{496A1DBA-E33D-4AA7-AA49-C533AFA7E519}",
-                                                                "{C21F9316-8419-4C35-BAFE-536829F5C78A}"
+                                                                "{587F771B-FC38-4C05-8A31-6002D71FF144}"
                                                             ]
                                                         },
                                                         "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
                                                             "$type": "GeometrySaveData",
                                                             "Position": [
                                                                 -800.0,
-                                                                180.0
+                                                                160.0
                                                             ]
                                                         },
                                                         "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
@@ -1155,7 +1300,7 @@
                         },
                         {
                             "Key": {
-                                "id": 63727806256927
+                                "id": 41300569639652
                             },
                             "Value": {
                                 "ComponentData": {
@@ -1198,7 +1343,7 @@
                         },
                         {
                             "Key": {
-                                "id": 63732101224223
+                                "id": 41304864606948
                             },
                             "Value": {
                                 "ComponentData": {
@@ -1228,7 +1373,7 @@
                         },
                         {
                             "Key": {
-                                "id": 63736396191519
+                                "id": 41309159574244
                             },
                             "Value": {
                                 "ComponentData": {
@@ -1258,7 +1403,7 @@
                         },
                         {
                             "Key": {
-                                "id": 63740691158815
+                                "id": 41313454541540
                             },
                             "Value": {
                                 "ComponentData": {
@@ -1292,7 +1437,7 @@
                         },
                         {
                             "Key": {
-                                "id": 63744986126111
+                                "id": 41317749508836
                             },
                             "Value": {
                                 "ComponentData": {
@@ -1306,7 +1451,7 @@
                                     "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
                                         "$type": "GeometrySaveData",
                                         "Position": [
-                                            1000.0,
+                                            1300.0,
                                             360.0
                                         ]
                                     },
@@ -1320,6 +1465,37 @@
                                     }
                                 }
                             }
+                        },
+                        {
+                            "Key": {
+                                "id": 47163199998692
+                            },
+                            "Value": {
+                                "ComponentData": {
+                                    "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+                                        "$type": "NodeSaveData"
+                                    },
+                                    "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+                                        "$type": "GeneralNodeTitleComponentSaveData",
+                                        "PaletteOverride": "MethodNodeTitlePalette"
+                                    },
+                                    "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+                                        "$type": "GeometrySaveData",
+                                        "Position": [
+                                            960.0,
+                                            360.0
+                                        ]
+                                    },
+                                    "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+                                        "$type": "StylingComponentSaveData",
+                                        "SubStyle": ".method"
+                                    },
+                                    "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+                                        "$type": "PersistentIdComponentSaveData",
+                                        "PersistentId": "{89868DAB-1712-4C78-AE33-0014BDC142EA}"
+                                    }
+                                }
+                            }
                         }
                     ],
                     "StatisticsHelper": {
@@ -1342,7 +1518,7 @@
                             },
                             {
                                 "Key": 13774516393157610292,
-                                "Value": 1
+                                "Value": 2
                             }
                         ]
                     }

Vissa filer visades inte eftersom för många filer har ändrats