diff --git a/README.md b/README.md index fe9257b1..199be653 100644 --- a/README.md +++ b/README.md @@ -58,17 +58,15 @@ The container will automatically serve the built content upon opening for previe as well as a file watcher to automatically rebuild the preview upon detecting changes. You will still have to manually refresh your browser, though... -If you are switching between container and local dev you may have to delete the `node_modules` and/or `.pnpm_store` folder. +If you are switching between container and local dev +you may have to delete the `node_modules` and/or `.pnpm_store` folder. ### Manual If you don't want to use the preconfigured devcontainer (or Codespaces), follow the directions below. -Although you can edit the `.adoc` files with just about any editor out there, -we suggest either Visual Studio Code (with the -[Asciidoc](https://marketplace.visualstudio.com/items?itemName=asciidoctor.asciidoctor-vscode) -and [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) plugins) -or IntelliJ. +We suggest either Visual Studio Code (and the [suggested extensions](./.vscode/extensions.json)) +or IntelliJ as your editor. In order to see what the pages will look like on the live site before being deployed, follow the below directions. @@ -86,13 +84,16 @@ follow the below directions. pnpm install ``` -4. If you have VSCode, open the folder as a workspace - and use the Command Palette to run the Task: `Launch hot reloading development server`. - Otherwise, follow the building and previewing directions below. +4. If you have VSCode, open the folder as a workspace to connect with our existing functionality. #### Building -To set up a development watch server that will automatically rebuild the SML docs when you make changes: +If you have VSCode, use the Command Palette to run the Task: `Launch hot reloading development server`. +This automatically rebuilds the docs when you make changes and opens your web browser to preview it. +You will still have to refresh the page manually to see the rebuilt changes. +Otherwise, follow the directions below. + +To open up a development watch server that will automatically rebuild the SML docs when you make changes: ```bash pnpm run watch:dev @@ -114,15 +115,26 @@ The output HTML files for both commands can be found in `\build\site`. #### Previewing -To preview the content, you can open the output HTML files in your browser, ex. `build/site/satisfactory-modding/latest/index.html` +If you have VSCode, use the Command Palette to run the Task: `Launch hot reloading development server`. +This automatically rebuilds the docs when you make changes and opens your web browser to preview it. +You will still have to refresh the page manually to see the rebuilt changes. +Otherwise, follow the directions below. + +To preview the content, you can open the output HTML files in your browser, +ex. `build/site/satisfactory-modding/latest/index.html` You can also run `pnpm run serve` which will start a local webserver. Your terminal will print usable addresses for the webserver. #### Link Checker -The CI will also run the [lychee link checker](https://github.com/lycheeverse/lychee/tree/master) to check for broken links. -Its reports can be found in the the [Actions tab](https://github.com/satisfactorymodding/Documentation/actions) of the repo. +The CI will also run the +[lychee link checker](https://github.com/lycheeverse/lychee/tree/master) +to check for broken links. +Its reports can be found in the the +[Actions tab](https://github.com/satisfactorymodding/Documentation/actions) +of the repo. + You can optionally install the tool yourself if you want to run it locally by following the lychee documentation. ## Adding Docs for Another Mod @@ -142,7 +154,9 @@ Contact us for more details if you'd like to set this up. The general steps are Sub-mod documentation sites are currently still subject to the Lychee link checker run by our CI, so if you have broken links in your docs, the build will fail and your site will not be updated. -You can check the [Actions](https://github.com/satisfactorymodding/Documentation/actions) for this repo to see if/why they failed. Mod docs updates are started by the SatisfactoryModdingBot github user under the action name `mod-docs-update`. +You can check the [Actions](https://github.com/satisfactorymodding/Documentation/actions) +for this repo to see if/why they failed. +Mod docs updates are started by the SatisfactoryModdingBot github user under the action name `mod-docs-update`. ## Adding new version branches diff --git a/cspell.json b/cspell.json index cbe717cb..853abd6f 100644 --- a/cspell.json +++ b/cspell.json @@ -39,6 +39,7 @@ "doggos", "DOREPCONDITIONAL", "DOREPLIFETIME", + "ESIT", "FACTORYGAME", "favorited", "Feyko", @@ -53,6 +54,7 @@ "furtue", "Headlift", "HKEY", + "Holo", "hoverpack", "hypertube", "hypertubes", @@ -101,6 +103,7 @@ "slomo", "SMEI", "smod", + "Spatialization", "struct", "structs", "subfolder", @@ -131,10 +134,12 @@ "USTRUCT", "utoc", "utocs", + "vgmstream", "VRAM", "Vulkan", "webp", "winget", + "wproj", "Wwise", "wwiser", "xeno", diff --git a/modules/ROOT/attachments/BeginnersGuide/dependencies/SML.vsconfig b/modules/ROOT/attachments/BeginnersGuide/dependencies/SML.vsconfig index 518fd1f4..5fc2cf48 100644 --- a/modules/ROOT/attachments/BeginnersGuide/dependencies/SML.vsconfig +++ b/modules/ROOT/attachments/BeginnersGuide/dependencies/SML.vsconfig @@ -41,7 +41,6 @@ "Microsoft.ComponentGroup.Blend", "Microsoft.VisualStudio.Workload.ManagedDesktop", "Microsoft.VisualStudio.Component.VC.ATL", - "Microsoft.VisualStudio.Component.SecurityIssueAnalysis", "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake", diff --git a/modules/ROOT/images/Satisfactory/IconLibrary/CreateDataAsset.png b/modules/ROOT/images/Satisfactory/IconLibrary/CreateDataAsset.png new file mode 100644 index 00000000..56ce7a16 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/IconLibrary/CreateDataAsset.png differ diff --git a/modules/ROOT/images/Satisfactory/IconLibrary/FreshIconDataArrayElement.png b/modules/ROOT/images/Satisfactory/IconLibrary/FreshIconDataArrayElement.png new file mode 100644 index 00000000..a911a003 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/IconLibrary/FreshIconDataArrayElement.png differ diff --git a/modules/ROOT/images/Satisfactory/IconLibrary/IconTextureSettings.png b/modules/ROOT/images/Satisfactory/IconLibrary/IconTextureSettings.png new file mode 100644 index 00000000..50aa2835 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/IconLibrary/IconTextureSettings.png differ diff --git a/modules/ROOT/images/Satisfactory/IconLibrary/ImportAsset.png b/modules/ROOT/images/Satisfactory/IconLibrary/ImportAsset.png new file mode 100644 index 00000000..279ae79b Binary files /dev/null and b/modules/ROOT/images/Satisfactory/IconLibrary/ImportAsset.png differ diff --git a/modules/ROOT/images/Satisfactory/IconLibrary/SelectDataAssetClass_FGIconLibrary.png b/modules/ROOT/images/Satisfactory/IconLibrary/SelectDataAssetClass_FGIconLibrary.png new file mode 100644 index 00000000..e0cde653 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/IconLibrary/SelectDataAssetClass_FGIconLibrary.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_AkEvent_Create.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_AkEvent_Create.png new file mode 100644 index 00000000..9a42c18b Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_AkEvent_Create.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_AkEvent_Info.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_AkEvent_Info.png new file mode 100644 index 00000000..cd6061ea Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_AkEvent_Info.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Audio_Settings.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Audio_Settings.png new file mode 100644 index 00000000..e0d31912 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Audio_Settings.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Create.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Create.png new file mode 100644 index 00000000..10cd6902 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Create.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Info.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Info.png new file mode 100644 index 00000000..5436a0dc Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Info.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_ProjectExplorer.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_ProjectExplorer.png new file mode 100644 index 00000000..d6a4b468 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_ProjectExplorer.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Spread_Graph.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Spread_Graph.png new file mode 100644 index 00000000..e3429b6a Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Attenuation_Spread_Graph.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_ImportWindow.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_ImportWindow.png new file mode 100644 index 00000000..269faac7 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_ImportWindow.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_ProjectExplorer.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_ProjectExplorer.png new file mode 100644 index 00000000..cbccf0a4 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_ProjectExplorer.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_VirtualFolderCreate.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_VirtualFolderCreate.png new file mode 100644 index 00000000..0a45f7bb Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Import_VirtualFolderCreate.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_IsSignificant.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_IsSignificant.png new file mode 100644 index 00000000..5d93b9f1 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_IsSignificant.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_PlaybackLimit.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_PlaybackLimit.png new file mode 100644 index 00000000..9bcc1d29 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_PlaybackLimit.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Configure.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Configure.png new file mode 100644 index 00000000..d0e9c392 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Configure.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Create.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Create.png new file mode 100644 index 00000000..d1f3699c Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Create.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Overview.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Overview.png new file mode 100644 index 00000000..97ce7feb Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Overview.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Range.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Range.png new file mode 100644 index 00000000..726f2442 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_RTPC_Range.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Significance.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Significance.png new file mode 100644 index 00000000..2de05ed0 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Significance.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Create.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Create.png new file mode 100644 index 00000000..0f816024 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Create.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_EditTab.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_EditTab.png new file mode 100644 index 00000000..b331debd Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_EditTab.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Generate.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Generate.png new file mode 100644 index 00000000..dbb9738c Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Generate.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_ProjectExplorer.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_ProjectExplorer.png new file mode 100644 index 00000000..1ccf1d47 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_ProjectExplorer.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Window.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Window.png new file mode 100644 index 00000000..c39a75e0 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_Soundbank_Window.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_Create.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_Create.png new file mode 100644 index 00000000..e2aa0c1e Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_Create.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_EndPlay.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_EndPlay.png new file mode 100644 index 00000000..1bbbeec5 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_EndPlay.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_FireAndForget.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_FireAndForget.png new file mode 100644 index 00000000..8f094282 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_FireAndForget.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_Verify.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_Verify.png new file mode 100644 index 00000000..0c2461f6 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UEAkEvent_Verify.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_UE_RTPC_Create.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UE_RTPC_Create.png new file mode 100644 index 00000000..5165295f Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UE_RTPC_Create.png differ diff --git a/modules/ROOT/images/Satisfactory/Wwise/Wwise_UE_RTPC_Usage.png b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UE_RTPC_Usage.png new file mode 100644 index 00000000..56efb6c3 Binary files /dev/null and b/modules/ROOT/images/Satisfactory/Wwise/Wwise_UE_RTPC_Usage.png differ diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 1ee8cad3..411d3ca5 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -13,6 +13,7 @@ * xref:Development/index.adoc[Development] ** xref:Development/UpdatingFromSml38.adoc[Updating from SML 3.8.0] +// ** xref:Development/UpdatingFromSml39.adoc[Updating from SML 3.9.0] // TODO SML3.10.0 ** xref:Development/UpdatingToNewVersions.adoc[_Updating your Mod_] ** xref:Development/BeginnersGuide/index.adoc[Getting Started] *** Installing Dependencies @@ -82,6 +83,7 @@ **** xref:Development/Satisfactory/AbstractInstance.adoc[Abstract Instances] **** xref:Development/Satisfactory/ConditionalPropertyReplication.adoc[Conditional Property Replication] **** xref:Development/Satisfactory/Savegame.adoc[SaveGame] +// **** xref:Development/Satisfactory/IconLibrary.adoc[Icon Libraries] // TODO SML3.10.0 AccessTransformer EditAnywhere edits still on dev **** xref:Development/Satisfactory/DedicatedServerAPIDocs.adoc[Vanilla Dedicated Server API] *** xref:Development/Satisfactory/ModsWithoutSML.adoc[Modding Without SML] *** Legacy @@ -128,7 +130,7 @@ ** xref:CommunityResources/incredibuild.adoc[Incredibuild] ** xref:CommunityResources/TrainSignalGuide.adoc[Train Signaling Guide] -// TODO unhide once translating section is ready +// TODO un-hide once translating section is ready // * Translating Mods // ** xref:Translation/GetStartedTranslating.adoc[Get Started Translating] // ** xref:Translation/UsingTolgee.adoc[Using Tolgee] diff --git a/modules/ROOT/pages/Development/BeginnersGuide/ReleaseMod.adoc b/modules/ROOT/pages/Development/BeginnersGuide/ReleaseMod.adoc index fbb17b35..3737c981 100644 --- a/modules/ROOT/pages/Development/BeginnersGuide/ReleaseMod.adoc +++ b/modules/ROOT/pages/Development/BeginnersGuide/ReleaseMod.adoc @@ -125,7 +125,7 @@ Below is a description of all extra fields SML and SMR require: |SemVersion | Version number for the mod. Should always increase with new releases, and should follow the https://semver.org/[semver] format. -To summarize, the format is `Major.Minor.Patch` +To summarize, the format is `Major.Minor.Patch`. {blank} + {blank} + As a rule of thumb, version `1.0.0` should be used for the first public release of your mod. @@ -141,6 +141,13 @@ so you should try to avoid this. or break how other mods interact with your mod, you should increase the Major version, for example `2.0.0`. +If you wish to release a pre-release version of your mod, +use the extended `Major.Minor.Patch-PrereleaseString` format, +where `PrereleaseString` is an +https://semver.org/#spec-item-9[alphanumeric-and-dot] string of your choice, such as `pre.1` or `beta.12`. +The Mod Manager does not automatically download any versions with a prerelease suffix - +the user must manually select that version from the version picker. + {blank} + Note that `1.10.0` is a valid semver version, `2.0.0` does not necessarily have to come after `1.9.0`. @@ -371,24 +378,6 @@ Remember, you can totally avoid formatting concerns by using the Alpakit widget Consider asking on the Discord if you get stuck on this step. -[id="ArchivedPluginsDirectory"] -== How Mod File Exporting Works - -Up until this point, you have likely been using the Alpakit Dev 'copy to mods directory' feature -to stage your mods files in game's folders for testing. - -Behind the scenes, using the 'Alpakit Selected (Development)' or the 'Alpakit!' (just this mod) buttons -generates a zip archive for you located at -`/Saved/ArchivedPlugins/YourModReference/YourModReference-TargetPlatformName.zip`. - -Note that this folder is in the **starter project's Saved folder**, -not the Saved folder of any of your mods. - -Consider checking the zip's contents to see if they're what you expect. -If for some reason you need extra files to be packaged into the mod, follow the directions -xref:Development/BeginnersGuide/Adding_Ingame_Mod_Icon.adoc#_setup[here] -to tell Alpakit to include them when building. - [id="PackageForUpload"] == Package for Release @@ -406,9 +395,12 @@ is relatively well known. However, there are also are also different builds of the game for different platforms (targets). There are Stable and EXP variants of each of these: -- `Windows` - Client version of Satisfactory, the one you launch to play the game. People playing the game on Linux still use this version, they run it through a compatibility/emulation layer. -- `Windows Server` - Windows Dedicated Server version of Satisfactory. It doesn't have a visual interface and is used to run servers from Windows, which is somewhat uncommon. -- `Linux Server` - Linux Dedicated Server version of Satisfactory. This is what most dedicated servers will be running, especially those hosted by third party services. +- `Windows` - Client version of Satisfactory, the one you launch to play the game. + People playing the game on Linux still use this version, they run it through a compatibility/emulation layer. +- `Windows Server` - Windows Dedicated Server version of Satisfactory. + It doesn't have a visual interface and is used to run servers from Windows, which is somewhat uncommon. +- `Linux Server` - Linux Dedicated Server version of Satisfactory. + This is what most dedicated servers will be running, especially those hosted by third party services. There are also slightly different versions of the Windows client for Steam and Epic. Your mod must be compiled in a slightly different way to be usable on each of these platforms, @@ -433,21 +425,46 @@ If you leave out one of these targets, the mod will not work on that platform! [IMPORTANT] ==== In most cases, especially for mods with no custom {cpp} code, *_you should check all 3 Release Target checkboxes_*. -This means your mod will run on game clients and dedicated servers. +This means your mod can be installed on game clients and dedicated servers. ==== +[id="ArchivedPluginsDirectory"] +=== How Mod File Exporting Works + +Up until this point, you have likely been using the Alpakit Dev 'copy to mods directory' feature +to stage your mods files in game's folders for testing. + +Behind the scenes, Alpakit uses the Unreal Build Tool and Unreal Automation Tool to generate zip files in the mod's **ArchivedPlugins** folder located at +`/Saved/ArchivedPlugins/YourModReference/YourModReference-TargetPlatformName.zip`. +Note that this folder is in the **starter project's Saved folder**, +not the Saved folder of any of your mods. + === Alpakit Release The 'Alpakit Selected (Release)' and release 'Alpakit!' (just this mod) buttons -will compile and package mods for all targets into one multi-target zip file. +compile and package mods for all their enabled targets, combining the output into one multi-target zip file. In the example image below, clicking `Alpakit!` for ExampleMod builds it for all 3 targets. image:BeginnersGuide/AlpakitReleaseDemo.png[Alpakit Release with Example Mod and SML selected] -Once complete, find the completed package in the same link:#ArchivedPluginsDirectory[ArchivedPlugins folder mentioned earlier] -called `YourModReference.zip`. +Click the 'Alpakit!' (just this mod) button for your mod and wait for the process to complete. +Packaging for release can take a significant amount of time +as the project's {cpp} code is compiled for targets that were previously skipped, +although subsequent runs are faster. + +After packaging a mod using Alpakit Release once, a new folder button appears in its row. +Clicking the button takes you to the link:#ArchivedPluginsDirectory[ArchivedPlugins folder mentioned earlier] +containing the zip files for that mod for easy inspection and uploading. + +The release process creates a zip file called `YourModReference.zip` +that contains all of the built targets. This is the file you'll upload to the Mod Repository later. +Consider checking the zip's contents to see if they're what you expect. +If for some reason you need extra files to be packaged into the mod, follow the directions +xref:Development/BeginnersGuide/Adding_Ingame_Mod_Icon.adoc#_setup[here] +to tell Alpakit to include them when building. + == Last Chance to Change Your Mod Reference As mentioned on the diff --git a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/item.adoc b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/item.adoc index f81fbb71..34d8fb52 100644 --- a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/item.adoc +++ b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/item.adoc @@ -231,7 +231,7 @@ We chose to not import any textures with the model because we want to leverage t https://docs.unrealengine.com/en-US/Engine/Rendering/Materials/MaterialInstances/index.html[material instances] system to improve game performance. -Right click in the Content Browser to create an advanced asset: `Materials and Textures > Material Instance` +Right click in the Content Browser to create an advanced asset: `Material > Material Instance` and name it `MI_DocItem` to follow Coffee Stain's naming scheme. MI stands for Material Instance, whereas MM stands for Master Material. @@ -264,7 +264,9 @@ That's because they store special information in each of the 4 (Red, Green, Blue How this works is outside of the scope of this tutorial, but you can find some more info in the xref:Development/Modeling/index.adoc[Modeling] section of the docs. -Open the imported `Tex_Doc-Item_MREO` texture, and in the Textures category of the Details pane, uncheck `sRGB`. +Open the imported `Tex_Doc-Item_MREO` texture, and in the Textures category of the Details pane, +uncheck `sRGB` +and set the Compression Settings to `Masks (no sRGB)` We have to do this because the of the special data in each color channel - we don't want Unreal to treat it like a normal image. The xref:Development/Modeling/MainMaterials.adoc#_factory_baked_mm_factorybaked[Main Materials] page has more details about what's going on. @@ -284,7 +286,7 @@ and check all three of these checkboxes to allow us to override their values: - For the Normal field, select `Tex_Doc-Item_N`. - For the Reflection Map field, select `Tex_Doc-Item_MREO`. -Next, find the Ambient Occlusion section, and check the `UseAO` box. +Next, find the AO section, and check the `UseAO` box. In the Emissive section, check the `UseEmissive` box. diff --git a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SimpleMachine.adoc b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SimpleMachine.adoc index cce66508..22ee790d 100644 --- a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SimpleMachine.adoc +++ b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SimpleMachine.adoc @@ -95,7 +95,7 @@ If the input grab boolean is false, we just return nothing and the output boolea Overall the logic becomes: checks if we have power. If we do, try and get a item from the input. If there's no item, we do nothing. But if we get a item, we count it and then return it to the output. -We also add a `Log Display` node near the end for debugging purposes. Details on getting a Live view of the game log can be found xref:Development/TestingResources.adoc#logging[here]. +We also add a `Log Display` node near the end for debugging purposes. Details on getting a live view of the game log can be found xref:Development/TestingResources.adoc#_sml_logging[here]. .Open this image full size to get a better look image::BeginnersGuide/simpleMod/machines/SimpleMachine_Grab.png[image] diff --git a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SolarPanel.adoc b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SolarPanel.adoc index 035cc063..f266aaad 100644 --- a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SolarPanel.adoc +++ b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/machines/SolarPanel.adoc @@ -66,7 +66,9 @@ We need to assess the time of day on multiple occasions - once when the actor sp For that, we can subscribe to the `OnDayStateChanged` event dispatcher of the time subsystem to be notified when this happens and switch our generator accordingly. Drag from the Return Value pin of a `Get Time Subsystem` node to create a `Bind Event to OnDayStateChanged` node. -Next, the event (let's name it `On Day State Changed`) is created by using the `Add Custom Event...` action or by dragging from `Event` pin of `Bind Event to OnDayStateChanged` node. +Next, the event (let's name it `On Day State Changed`) is created by using +the `Add Custom Event...` action when right-clicking in the blueprint graph, +or by dragging from `Event` pin of `Bind Event to OnDayStateChanged` node. Hook up the execution pin of the Bind Event node to our Begin Play line since we only need to bind once. diff --git a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/recipe.adoc b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/recipe.adoc index ecff2b9a..79569c14 100644 --- a/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/recipe.adoc +++ b/modules/ROOT/pages/Development/BeginnersGuide/SimpleMod/recipe.adoc @@ -299,7 +299,7 @@ xref:Development/BeginnersGuide/SimpleMod/gameworldmodule.adoc#_compile_and_save == Register the Schematic To register the schematic, open up the -xref:Development/BeginnersGuide/SimpleMod/gameworldmodule.adoc#_create_the_class[RootGameWorld_YourModReferenceHere] +xref:Development/BeginnersGuide/SimpleMod/gameworldmodule.adoc#_create_game_world_module[RootGameWorld_YourModReferenceHere] asset we created earlier and add the schematics to the `M Schematics` array. And we're set! Our recipe and schematic are registered and should show up in the game now. diff --git a/modules/ROOT/pages/Development/BeginnersGuide/StarterProjectStructure.adoc b/modules/ROOT/pages/Development/BeginnersGuide/StarterProjectStructure.adoc index 6d1663e2..ef233285 100644 --- a/modules/ROOT/pages/Development/BeginnersGuide/StarterProjectStructure.adoc +++ b/modules/ROOT/pages/Development/BeginnersGuide/StarterProjectStructure.adoc @@ -38,7 +38,7 @@ For example, you can use Iron Rods as an ingredient in your own recipes because there is an Iron Rod placeholder asset present in the Starter Project. The placeholder generator makes a best effort to fill in fields with the correct values, - but it's not always possible to do so, +but it's not always possible to do so, or the content is purposefully excluded. For example, recipe ingredients and quantities will be present, but models and textures are intentionally replaced with blanks. @@ -56,6 +56,8 @@ image::BeginnersGuide/StarterProjectStructure/IronRodPlaceholder.png[Iron Rod pl Only placeholders for the more common assets types are included in the Starter Project. You may need to manually create placeholders for less common assets like particle systems, animations, and such if you wish to reference them. + +The process for creating your own placeholders so is covered xref:Development/ReuseGameFiles.adoc[here]. ==== Although it is _possible_ to edit these files, diff --git a/modules/ROOT/pages/Development/BeginnersGuide/dependencies.adoc b/modules/ROOT/pages/Development/BeginnersGuide/dependencies.adoc index 450d6469..5bf41cda 100644 --- a/modules/ROOT/pages/Development/BeginnersGuide/dependencies.adoc +++ b/modules/ROOT/pages/Development/BeginnersGuide/dependencies.adoc @@ -77,7 +77,7 @@ You might have to scroll a bit to find them. Next, from the "Individual Components" tab, search for and select: -- `MSVC v143 - VS2022 C++ x64/x86 build tools (v14.34-17.4)` +- `MSVC v143 - VS 2022 C++ x64/x86 build tools (v14.34-17.4)` - `.NET 6.0 Runtime (Long Term Support)` - `.NET Framework 4.8.1 SDK` diff --git a/modules/ROOT/pages/Development/Cpp/hooking.adoc b/modules/ROOT/pages/Development/Cpp/hooking.adoc index c1ff7feb..5994cdcc 100644 --- a/modules/ROOT/pages/Development/Cpp/hooking.adoc +++ b/modules/ROOT/pages/Development/Cpp/hooking.adoc @@ -1,10 +1,33 @@ = Hooking -Hooking is a {cpp} exclusive feature of SML that allows you to attach a custom function body to a existing function. +Hooking is a {cpp} exclusive feature of SML that allows you to attach a custom function body to an existing function. All C/{cpp} functioning hooking stuff can be found in `#include "Patching/NativeHookManager.h"`. All Blueprint function hook stuff can be found in `#include "Patching/BlueprintHookManager.h"`. +== Background Information + +The hooking system SML is using is just C / {cpp} function hooking, as Unreal Engine is {cpp}. +This system can theoretically be used on any executable, +but you need to know the location of functions in memory, which is difficult. +For general {cpp} executables, and most UE games, you only have a .exe, +which provides no information about where functions are located, +so to figure that out you need very good reverse engineering skills, +and it needs to be done on an exe-by-exe basis, so if the game updates, everything breaks. + +What's different about Satisfactory is that it provides PDBs, +which normally are used to determine the call stack when a crash happens, +but they can also be used in the other direction: to find a function address based on the name. + +Finding a function address based on the name is the technique that SML v1 used to implement hooking. +The trouble there is that many functions may be stripped, or inlined, which makes {cpp} modding in general harder, +but also complicates hooking, as methods might suddenly disappear and be embedded into the place they are called from. + +At our request, Coffee Stain enabled Modular Build in +https://satisfactory.wiki.gg/wiki/Patch_0.4.1.0#Modular_builds[Update 4], which means each Unreal Engine module is a dll on its own. +This means that all functions are exported, so their address can be natively found by the linker, and also that no function can be inlined. +Modular builds also enable the native Unreal Engine mod support (i.e., loading mod plugins from the Mods folder). + [id="CppFunctionHooks"] == {cpp} Function Hooks @@ -15,8 +38,8 @@ SML's hooking interface provides distinct 3 ways of hooking functions, each of w If multiple hooks are attached to the same function, these hooks will then get called in the order they were registered. -There is a normal hook which gets called before the actual function gets called. -Through this hook you are able to prevent the final function call and you are also able to overwrite the return value. +There is a normal hook that gets called before the actual function gets called. +Through this hook, you are able to prevent the final function call and you are also able to overwrite the return value. If you cancel the execution of the final function, you can prevent the following hooks from being called. Keep in mind that this means that another hook can prevent your hooks from being called by Satisfactory. The normal hook's signature is `void(TCallScope&, hookFuncParams)`. @@ -57,12 +80,12 @@ void hook(TCallScope& Scope, class* exampleClass, int exampleArg) { ---- Since you still want to make sure your hook gets called, -no care about if the final function got called or not we introduce the "after" hooks. +no care about whether the final function got called or not we introduce the "after" hooks. These hooks get all called after the normal hook calls and only allow you to read the parameters as well as the resulting return value. That means you can't influence the final function call. Also, don't use the TCallScope object, instead the first parameter of your hooks signature -is the return value following by the function call parameters. +is the return value followed by the function call parameters. [source,cpp] ---- @@ -76,7 +99,7 @@ void hook(int returnValue, int exampleArg) { By 'hook types' we mean the different ways of attaching a hook to a function. Each attachment method works differently under the hood, and it's important to pay attention to the key differences between the different types of hooks. -Be aware that type of return values and parameters etc has nothing to do with each other or if it is a member function, you can use them in any way. +Be aware that the type of return values and parameters etc has nothing to do with each other or if it is a member function, you can use them in any way. Note that the Hook function is a std::function, which means that it can be any type a std::function can accept, such as function pointers, function pointers with bound placeholders, or even lambdas. [IMPORTANT] @@ -94,7 +117,7 @@ if (!WITH_EDITOR) { } ---- -Using `#if !WITH_EDITOR` and `#endif` directives is also an option, but it is not recommended: it hides errors until building shipping and confuses IDEs, making development and debugging slightly more annoying with no benefit. +Using `#if !WITH_EDITOR` and `#endif` directives are also an option, but it is not recommended: they hide errors until building shipping and confuse IDEs, making development and debugging slightly more annoying with no benefit. ==== === Type: SUBSCRIBE_METHOD @@ -105,7 +128,7 @@ such that the code you pass will be called before the function executes. If multiple mods have subscribed to the same function, the hooks will be called in the order they were registered. -Usage goes as following: +Usage goes as follows: [source,cpp] ---- @@ -131,7 +154,7 @@ void registerHooks() { [WARNING] ==== Hooking an overloaded function might not work as intended since the compiler has no clue what exact symbol you now want to hook. -For that you should have an look at the `SUBSCRIBE_METHOD_MANUAL`-Macro which allows you +For that, you should have a look at the `SUBSCRIBE_METHOD_MANUAL`-Macro which allows you to explicitly set the symbol you want to hook. ==== @@ -145,7 +168,7 @@ but the hook will still run if the hooked function is called by the overriding i If the overriding implementation of a subclass does not "call super", you have to hook said subclass separately. Because pure virtual functions do not have a proper function body, they cannot possibly be hooked. -Usage goes as following: +Usage goes as follows: [source,cpp] ---- @@ -162,7 +185,7 @@ public: #include "Patching/NativeHookManager.h" void registerHooks() { - SomeClass* SampleObject = new SomeClass(); // For UObject derived classes, use SUBSCRIBE_UOBJECT_METHOD instead + SomeClass* SampleObject = GetMutableDefault(); // For UObject derived classes, use SUBSCRIBE_UOBJECT_METHOD instead SUBSCRIBE_METHOD_VIRTUAL(SomeClass::MemberFunction, SampleObject, [](auto& scope, SomeClass* self, int arg1) { // do some nice stuff there }); @@ -182,18 +205,49 @@ Depending on the type of function you are attempting to hook and what you want t ==== Const Functions When hooking a `const` function you will need to prefix the "self" pointer with `const`. -[horizontal] -*Non-Const Function*:: `(auto& scope, SomeClass* self)` -*Const Function*:: `(auto& scope, *const* SomeClass* self)` + +[cols="1,4a"] +|=== +| Is Const? | Format + +| Non-Const +| `(auto& scope, SomeClass* self)` + +| Const +| `(auto& scope, *const* SomeClass* self)` + +|=== ==== Hooking AFTER For "after" hooks, add the `_AFTER` postfix to the macro names. -Be aware that the hook function signature changes accordingly and will no longer need the "scope": -[horizontal] -*Non-Virtual*:: `SUBSCRIBE_METHOD_AFTER(SomeClass::MemberFunction, [](SomeClass* self))` -*Virtual*:: `SUBSCRIBE_METHOD_VIRTUAL_AFTER(SomeClass::MemberFunction, [](SomeClass* self))` +Be aware that the hook function signature changes accordingly and no longer needs the "scope". + +The below examples are for non-virtual functions. +For virtual functions, use `SUBSCRIBE_METHOD_VIRTUAL_AFTER` instead of `SUBSCRIBE_METHOD_AFTER`. + +[cols="1,1,4a"] +|=== +| Return? | Parameters? | Format + +| ❌ +| ❌ +| `SUBSCRIBE_METHOD_AFTER(SomeClass::MemberFunction, [](SomeClass* self))` + +| ✔️ +| ❌ +| `SUBSCRIBE_METHOD_AFTER(SomeClass::MemberFunction, [](auto returnValue, SomeClass* self))` + +| ❌ +| ✔️ +| `SUBSCRIBE_METHOD_AFTER(SomeClass::MemberFunction, [](SomeClass* self, int arg1, int arg2))` + +| ✔️ +| ✔️ +| `SUBSCRIBE_METHOD_AFTER(SomeClass::MemberFunction, [](auto returnValue, SomeClass* self, int arg1, int arg2))` + +|=== ==== FORCEINLINE Functions diff --git a/modules/ROOT/pages/Development/Cpp/thirdparty.adoc b/modules/ROOT/pages/Development/Cpp/thirdparty.adoc index 238783d6..cf7c644d 100644 --- a/modules/ROOT/pages/Development/Cpp/thirdparty.adoc +++ b/modules/ROOT/pages/Development/Cpp/thirdparty.adoc @@ -143,3 +143,11 @@ you should consider creating a dependency mod to hold the library. Although there shouldn't be any issues at runtime if each mod contains the library as a module (untested), at development time, Unreal will complain about it when building if both mods are in the project at the same time and the third party module name is the same in both. + +== Existing Plugins + +If the library you wish to use is already a complete uplugin, +try bringing it into your project folder and packaging it via Alpakit. +If that works, the library can then be released as a separate mod +and requirements handled via the normal mod dependency system. +Ensure you have permission from the library creator to redistribute it before publishing. diff --git a/modules/ROOT/pages/Development/ExtractGameFiles.adoc b/modules/ROOT/pages/Development/ExtractGameFiles.adoc index 3b8181cf..6e60f495 100644 --- a/modules/ROOT/pages/Development/ExtractGameFiles.adoc +++ b/modules/ROOT/pages/Development/ExtractGameFiles.adoc @@ -274,20 +274,21 @@ prompting a system dialog to select a save location. [WARNING] ==== -Some users have reported issues with FModel's audio player, causing it to display sounds as `.wem.wem` files and not play them. -We haven't found a cause for this issue. -See https://discord.com/channels/555424930502541343/1036634533077979146/1286942067125260320[this Discord conversation] for more information (required mod developer discord role to view). - -If you are affected by this issue, try using the Bulk Audio Renamer approach below. +Some users have reported issues with FModel's audio player, +causing it to display sounds as `.wem.wem` files and not play them. +If this is affecting you, check your FModel install directory's `/Output/.data/` folder. +It should contain `vgmstream-win.zip` and multiple extracted files. +If it doesn't, get a copy of `vgmstream-win.zip` from +https://github.com/vgmstream/vgmstream/releases/tag/r1951[its github releases page] +and extract the zip directly into that folder, then relaunch FModel. + +See https://discord.com/channels/555424930502541343/1036634533077979146/1318603952375468125[this Discord conversation] and +https://discord.com/channels/555424930502541343/1036634533077979146/1286942067125260320[this Discord conversation] +if that didn't work (mod developer discord role required to view). ==== === Bulk Audio Renamer -// TODO unclear why MrCheese said that FModel can't play sound files since release. -// Resolve before merge because it might change the above directions further. -// https://github.com/orgs/satisfactorymodding/projects/15/views/1?pane=issue&itemId=80439924 -// https://discord.com/channels/555424930502541343/1036634533077979146/1286942067125260320 - Community member MrCheese has created a python script that enables mass renaming of exported wem files to their associated named bnk files. If you decide to extract a large number of sounds, this script can save you a lot of time. diff --git a/modules/ROOT/pages/Development/ModLoader/AccessTransformers.adoc b/modules/ROOT/pages/Development/ModLoader/AccessTransformers.adoc index 5e05acee..7e136eb6 100644 --- a/modules/ROOT/pages/Development/ModLoader/AccessTransformers.adoc +++ b/modules/ROOT/pages/Development/ModLoader/AccessTransformers.adoc @@ -85,6 +85,17 @@ so that no changes to the game headers are required. Adds `BlueprintCallable` to the specified UFUNCTION, allowing you to call that function from blueprints. It cannot be added to a non-`UFUNCTION` function. +// TODO SML3.10.0 + +// === EditAnywhere + +// Adds `EditAnywhere` to the specified UPROPERTY, +// allowing you the property to be modified in the Details panel of blueprint assets and instances. + +// === BlueprintType + +// Adds `BlueprintType` to the specified USTRUCT, allowing that struct to be made or split using blueprint nodes. + == Loading As of SML3.5.0, BlueprintReadWrite and BlueprintCallable Access Transformers are now applied at runtime, @@ -145,6 +156,10 @@ BlueprintReadWrite=(Class="/Script/FactoryGame.FGSchematicManager", Property="mP BlueprintCallable=(Class="/Script/FactoryGame.FGDismantleInterface", Function="Dismantle") ---- +// TODO SML3.10.0 +// EditAnywhere=(Class="/Script/FactoryGame.IconData", Property="ID") +// BlueprintType=(Struct="/Script/FactoryGame.WorldScannableData") + === Blueprint Asset Property Tracing Example As an example, if you wanted the `mMaxZoopAmount` property of the blueprint asset `Holo_Foundation` to be Blueprint Read-Writeable, diff --git a/modules/ROOT/pages/Development/ModLoader/Logging.adoc b/modules/ROOT/pages/Development/ModLoader/Logging.adoc index be7cc50d..5543b179 100644 --- a/modules/ROOT/pages/Development/ModLoader/Logging.adoc +++ b/modules/ROOT/pages/Development/ModLoader/Logging.adoc @@ -13,11 +13,13 @@ a suffix will be appended to the file name to differentiate them (ex. `FactoryGa == Viewing Logs -By default, the game's logs will be stored in +By default, the game client's logs are be stored in `\AppData\Local\FactoryGame\Saved\Logs\FactoryGame.log`. +For information on log file locations for other platforms, see the xref:faq.adoc#Files_Logs[FAQ]. You can also view the logs live in a terminal as the game is running. To view the terminal, add `-log` to the game's launch arguments. +You can also use the enhanced Unreal Console via `-log -NewConsole` as described xref:Development/TestingResources.adoc#_unreal_console[here]. Learn how to configure launch arguments on the xref:faq.adoc#_how_do_i_start_the_game_with_launch_arguments[FAQ page]. diff --git a/modules/ROOT/pages/Development/OpenSourceExamples.adoc b/modules/ROOT/pages/Development/OpenSourceExamples.adoc index 76305847..72eec21c 100644 --- a/modules/ROOT/pages/Development/OpenSourceExamples.adoc +++ b/modules/ROOT/pages/Development/OpenSourceExamples.adoc @@ -35,8 +35,6 @@ _Notable Techniques Used:_ * Widget Injection ** Modify the base game's interface to hide, change, and add new elements -* Runtime asset generation -** Used to generate the fake recipe entries for display in the xref:Development/Satisfactory/ShoppingList.adoc[Shopping List] * In-game tutorial ** An icon with a tooltip that encourages the player to see how to use the mod after installing it, then dismisses itself for later @@ -44,7 +42,7 @@ _Notable Techniques Used:_ _Notable Satisfactory Features Used:_ * xref:Development/Satisfactory/ShoppingList.adoc[To-Do/Shopping List] -** Automatically adds items to the player's Shopping List list +** Adds schematics to the player's Shopping List list _Notable Mod Loader Features Used:_ @@ -95,6 +93,8 @@ _Notable Mod Loader Features Used:_ ** Tracking if the user has modified the config from the defaults to know if future mod updates should automatically overwrite them with updated default data ** Programatically modifying config values and saving the changes +* xref:Development/ModLoader/ContentTagRegistry.adoc[Content Tags] +** Tags can be used to specify items/recipes/schematics to skip from sample consideration without mod source dependencies. == Screw It @@ -279,3 +279,25 @@ _Notable Mod Loader Features Used:_ ** Scans all recipes and all schematics for a specific tag and modifies them when present ** Enables easy extending the mod to affect other mods' blueprint designers. Any recipe with the relevant tag is made free and any schematic with the relevant tag is given for free. + +[id="ThisSignUp"] +== This Sign Up + +Adds arrows to indicate which way is up when building a sign. + +_Source Code_: Linked on the https://ficsit.app/mod/ThisSignUp[Mod Page] + +_Mod Type_: Pure Blueprint + +_Notable Techniques Used:_ + +* None + +_Notable Satisfactory Features Used:_ + +* None + +_Notable Mod Loader Features Used:_ + +* Simple Construction Script (SCS) Hooks +** Used to spawn an additional actor component on sign placement holograms (the upwards facing arrow) diff --git a/modules/ROOT/pages/Development/ReuseGameFiles.adoc b/modules/ROOT/pages/Development/ReuseGameFiles.adoc index 63576926..47fcfdf7 100644 --- a/modules/ROOT/pages/Development/ReuseGameFiles.adoc +++ b/modules/ROOT/pages/Development/ReuseGameFiles.adoc @@ -26,7 +26,7 @@ xref:Development/ExtractGameFiles.adoc[Extracting Game Files page] instead for m As described on the xref:Development/BeginnersGuide/StarterProjectStructure.adoc[Starter Project Structure] page, all of the supposed base-game assets in the Starter Project are actually placeholders. If the starter project doesn't already have a placeholder for the base-game asset you wish to reference, -you'll have to create it yourself +you'll have to create it yourself. == Example Static Mesh and Icon Reuse @@ -37,15 +37,12 @@ component mentioned earlier. The first step is to track down the location of the asset in the base game. This is done by figuring out the Blueprint Path of the asset via the https://satisfactory.wiki.gg/[Satisfactory Wiki], -finding the content on a -https://github.com/Goz3rr/SatisfactorySaveEditor/tree/master/Reference%20Materials[reference list], or via searching around for it in -xref:Development/ExtractGameFiles.adoc#FModel[FModel] -(the case for most GUI elements). +searching around for it in xref:Development/ExtractGameFiles.adoc#FModel[FModel] +(the case for most GUI elements), +or using a mod like https://ficsit.app/mod/ContentInspector[Content Inspector]. -image:ReuseContent/WikiHubPartsBox.png[HUB Parts on the Satisfactory Wiki] - - -_HUB Parts on the Satisfactory Wiki_ +.HUB Parts on the Satisfactory Wiki +image::ReuseContent/WikiHubPartsBox.png[HUB Parts on the Satisfactory Wiki] Next, you can go to that blueprint path in FModel to find out what the paths of the relevant static mesh and icon objects are. @@ -56,10 +53,8 @@ so we should go to `\FactoryGame\Resource\Parts\HUBParts` in FModel to find the relevant files. -image:ReuseContent/FModelFoundPath.png[HUB Parts inside of FModel] - - -_HUB Parts inside of the FModel Folders browser_ +.HUB Parts inside of the FModel Folders browser +image::ReuseContent/FModelFoundPath.png[HUB Parts inside of FModel] Upon switching to the Packages tab we can see the `FGItemDescriptor` (`Desc_HUBParts.uasset`) @@ -71,9 +66,8 @@ For this example, make sure you have `HUBParts` selected in the Folders tab, then open `SM_HUBparts_01` from the Packages tab to bring up the 3D viewer. Use the Commands button in the top left of the viewer to see navigation keybinds. -image:ReuseContent/FModelHubParts.png[HUB Parts in the FModel 3D Viewer] - -_HUB Parts in the FModel 3D Viewer_ +.HUB Parts in the FModel 3D Viewer +image::ReuseContent/FModelHubParts.png[HUB Parts in the FModel 3D Viewer] Now that you've found the location of the asset in the base game, you're ready to set up the placeholder for it. Within your editor, @@ -93,6 +87,14 @@ creating a placeholder for _does not matter at all_ - just that it has the correct name, path, and asset type as the content you want to reference. ==== +[TIP] +==== +If you aren't sure what asset type the placeholder should be, +look at the `Type`, `Class`, and `SuperStruct` properties in FModel. +Note that some classes do not have valid {cpp} stub implementations and can crash the editor. +In that case, try using a parent class of the crashing class as the placeholder instead. +==== + For the mesh, we can reuse the link:{attachmentsdir}/BeginnersGuide/simpleMod/Mesh_DocBuild.fbx[Plantpot of Knowledge] from the @@ -129,4 +131,4 @@ This version of the project would include models, textures, and other resources instead of their placeholder versions, allowing you to view them in-editor. You can read more about this in its section on the -xref:Development/BeginnersGuide/StarterProject/ObtainStarterProject.adoc[Extracting Game Files page]. +xref:Development/ExtractGameFiles.adoc#_generating_a_complete_starter_project[Extracting Game Files page]. diff --git a/modules/ROOT/pages/Development/Satisfactory/Audio.adoc b/modules/ROOT/pages/Development/Satisfactory/Audio.adoc index 39a5e47a..9d8d3b39 100644 --- a/modules/ROOT/pages/Development/Satisfactory/Audio.adoc +++ b/modules/ROOT/pages/Development/Satisfactory/Audio.adoc @@ -5,20 +5,367 @@ This page is a work in progress. ==== +Adding sound effects and music via mods can really help bring them to life. +Coffee Stain uses the Wwise audio system to play sounds in Satisfactory. +Depending on what your mod is trying to do, you may want to use the built in Unreal system or the Wwise system. + +== Audio for ADA Messages + +See the xref:Development/Satisfactory/AdaMessages.adoc[dedicated page on ADA Messages] for more information. + +== Unreal Audio System + +If you're playing sound for the purpose of user interfaces (UI) or client-side only effects, +it may be easier to use Unreal's built in sound system +at the cost of losing integration with some of the game's systems (ex. ADA) and the advanced features of Wwise. + +The "Play Sound 2D" and "Play Sound at Location" blueprint nodes are useful for this purpose. + == Wwise -TODO +Interfacing with the Wwise sound system will require setting up and integrating a Wwise project and integrating it with the modding project. -Coffee Stain uses the Wwise audio system to play sounds in Satisfactory. +Note that using large numbers of Wwise sounds may require getting a +https://www.audiokinetic.com/en/blog/free-wwise-indie-license/[Wwise indie license] +for your project. -At the time of writing it is very difficult for modders to interface with Wwise systems, -so you should use Unreal's built in sound system instead. +=== Setting Up Audio Buses -The SML team is working on enabling modders to interface with Wwise. +By default when using Wwise audio only the `Master` volume slider will work. -== ADA +You will need to manually create the different Audio Buses that link to the other sliders. + +TODO: Waiting for CSS to provide the correct audio bus names. + +=== Setting Up Attenuation + +If you plan to use Wwise audio for buildings or equipment, you must set up **attenuation**. +By default, the audio will play at full volume even if you are on the other side of the map from its origin. +Attenuation causes the sound to become quieter at a distance or not play at all. + +[NOTE] +==== +Attenuation is not required if you plan to use Audio for UI or ADA messages, and this step can be skipped. +==== + +On Wwise's Project Explorer, go to the `ShareSets` tab. Share Sets are useful for providing the same configuration to multiple Wwise objects. + +You will see the section `Attenuations -> Default Work Unit` + +image:Satisfactory/Wwise/Wwise_Attenuation_ProjectExplorer.png[Wwise_Attenuation_ProjectExplorer, 350] + +Create a new Attenuation object by right-clicking the `Default Work Unit` then `New Child -> Attenuation` + +image:Satisfactory/Wwise/Wwise_Attenuation_Create.png[Wwise_Attenuation_Create, 100%] + +You can name this whatever you want; just be mindful that you can't use the same name twice. + +Open the new Attenuation ShareSet by double clicking the new attenuation shareset. + +In the main section, you will be presented with the following: + +image:Satisfactory/Wwise/Wwise_Attenuation_Info.png[Wwise_Attenuation_Info, 100%] + +==== Distance + +Click on the First setting, Volume (by default, will automatically be selected). This is marked in Yellow on the screenshot. + +You will then need to set the `Max Distance` setting. + +[TIP] +==== +This number is in Unreal Units (uu); the conversion is 100uu = 1 meter. +==== + +The Max Distance will be the distance away from the building that the player can still hear the sound. + +Based on the vanilla buildings, smaller buildings have a maximum distance of 4,000 to 6,000, and larger vanilla buildings are around 6,000 to 10,000. + +==== Spread + +By default, the spread will be set to 0. This means that the sound comes from a specific point when rotating the player. + +This can become very confusing to players when they are standing right next to the building. + +On the screenshot above, change the dropdown marked in Red to `Custom`. This will then show the spread graph in the bottom section. + +You can add a new point to the graph by double-clicking the line. Then, set the `X` value to roughly the size of your building and the `Y` value to 100. + +Add another point to the graph slightly further on, set the `X` value to the size of the building plus a bit more, and set the `Y` value to 0. + +image:Satisfactory/Wwise/Wwise_Attenuation_Spread_Graph.png[Wwise_Attenuation_Spread_Graph, 100%] + +=== Importing Media Files to Wwise + +Open the Wwise project file, typically in `SMLProject/SMLProject_WwiseProject/SMLProject_WwiseProject.wproj`. Double-clicking this file will open Wwise. + +To make sure you are in the correct layout at the top, go to `Layout -> Designer` + +On the left-hand side, you will see the project explorer; select the Audio Tab. + +image:Satisfactory/Wwise/Wwise_Import_ProjectExplorer.png[Wwise_Import_ProjectExplorer, 350] + +Under `Actor-Mixer Hierarchy`, there will be `Default Work Unit` + +To keep everything organized, create a new Virtual Folder to house your Wwise files and name it the same as your +xref:Development/BeginnersGuide/SimpleMod/gameworldmodule.adoc#ModReference[mod reference]. + +image:Satisfactory/Wwise/Wwise_Import_VirtualFolderCreate.png[Wwise_Import_VirtualFolderCreate, 600] + +Now, to import audio files! + +Drag your `.wav` files into this newly created Virtual Folder. The `Audio File Importer` window will show. + +image:Satisfactory/Wwise/Wwise_Import_ImportWindow.png[Wwise_Import_ImportWindow, 600] + +Ensure that you have `Create New Objects` selected under import mode. Verify it is going to the correct folder and then click `Import` + +Your audio files are now imported to Wwise and ready to be referenced by Unreal systems. + +=== Adding Attenuation To Audio + +If you plan on using attenuation on audio, you must first follow the attenuation section of the documentation. xref:Development/Satisfactory/Audio.adoc#_setting_up_attenuation[Setting Up Attenuation]. + +To set up attenuation on the audio, double-click the audio file in the Wwise Project Explorer `Audio` tab. + +Then, once the audio opens in the main section, go to the `Positioning` tab. + +Change the `3D Spatialization` setting to `Position + Orientation` (Marked in blue in the screenshot). + +Click the `>>` button, then select the Attenuation ShareSet from the list (Marked in red in the screenshot). + +image:Satisfactory/Wwise/Wwise_Attenuation_Audio_Settings.png[Wwise_Attenuation_Audio_Settings, 500] + +=== Creating Audiokinetic Events + +**Audiokinetic Events** (typically shortened to `AKEvents`) allow your mod code to tell the Wwise sound system to do something. +Example AKEvent types include Play, Pause, and Stop. +Each sound you want to use typically needs multiple events associated with it. + +To play the audio in your mod, you will need to create an event in Wwise. First, make sure that you have followed the above steps to import your `.wav` files to Wwise. + +In Wwise's Project Explorer, go to the `Audio` tab and locate the audio for which you want to create an event. + +Right-click the audio and select `New Event -> Play`. This will create a new Play event. + +image:Satisfactory/Wwise/Wwise_AkEvent_Create.png[Wwise_AkEvent_Create, 600] + +Verify the event was created successfully by going to the Project Explorer's `Events` tab. +You should see the event `Play_`. +Double-clicking the event will show the Event's details in the main center section. + +There are a few things to take note of and verify: + +* Take a note of the Event ID. You will need to compare it with values in the Unreal Editor later. (Red in the screenshot) +* Make sure that `Inclusion` is checked (Green in the screenshot) +* Verify that the target is for the correct audio (Blue in the screenshot) + +image:Satisfactory/Wwise/Wwise_AkEvent_Info.png[Wwise_AkEvent_Info, 600] + +Repeat the process for all other audio you want to play in your mod. + +[TIP] +==== +Consider creating one or more Virtual Folders within your mod's folder to store your AKEvents for ease of organization. +==== + +=== Creating Audiokinetic Soundbanks + +You will need to create a new Soundbank for all your Events to be stored. + +In Wwise, change the layout to Soundbanks. This can be found at the top under `Layouts -> Soundbanks`. + +Select the `Soundbanks` tab in the Project Explorer on the left. + + +By default, you will have the following tree structure: + +image:Satisfactory/Wwise/Wwise_Soundbank_ProjectExplorer.png[Wwise_Soundbank_ProjectExplorer, 600] + +Create a new Soundbank by Right-clicking the `Default Work Unit` then `New Child -> Soundbank` + +image:Satisfactory/Wwise/Wwise_Soundbank_Create.png[Wwise_Soundbank_Create, 600] + +Name the Soundbank `YourModReference_Soundbank`. +Soundbank names do not need to be in this format, but including the mod reference helps with organization. + +Double-click the newly created Soundbank, which will open in a new window. + +In the main Wwise window, navigate to the Events tab in the Project Explorer. + +With the Soundbank window still open, drag the `Default Work Unit` to the Soundbank window. If you created a specific Virtual Folder for your event, drag that folder instead. + +image:Satisfactory/Wwise/Wwise_Soundbank_Window.png[Wwise_Soundbank_Window, 700] + +Go to the `Edit` tab to verify that all the events are included in the Soundbank. + +image:Satisfactory/Wwise/Wwise_Soundbank_EditTab.png[Wwise_Soundbank_EditTab, 600] + +Now, it's finally time to generate the Soundbank for Unreal Engine. + +In the Wwise Project Explorer, on the `Soundbanks` tab, right-click on the soundbank and click `Generate Soundbank(s) for all platforms`. + +image:Satisfactory/Wwise/Wwise_Soundbank_Generate.png[Wwise_Soundbank_Generate, 500] + +=== Unreal Project Configuration + +Open the Unreal Engine project settings and Navigate to the Wwise integration settings. + +Change the `Root Output Path` setting to `/GeneratedSoundBanks`. +Then change the `Unreal Audio Routing` setting to `Both Wwise and Unreal audio`. +You may need to restart the Unreal Editor after making these changes. + +=== Creating AKEvents In Unreal Engine + +Now that you've defined your audio, events, and soundbanks in Wwise, it's time to utilize them in the Unreal Engine. +The first step in doing this is to create Unreal assets that reference your Wwise assets. +Although it is possible to use the Wwise Browser to create these, this is not recommended, +as it places them in the wrong project folders. +As such, follow the steps below to create them via the Unreal Editor. + +Create a new Audiokinetic Event by right-clicking on an empty area in the Content Browser. + +Go To `Audiokinetic -> Audiokinetic Event` + +image:Satisfactory/Wwise/Wwise_UEAkEvent_Create.png[Wwise_UEAkEvent_Create, 500] + +Name the new asset **exactly** the same name as the event you created earlier in Wwise. This enables Unreal to automatically populate the correct event information in the asset's fields. + +Open the asset and verify that its settings match those configured in Wwise: + +* Verify that the `Wwise Short ID` matches the event ID in Wwise. +* Verify the `Wwise Name` matches the event name. + +image:Satisfactory/Wwise/Wwise_UEAkEvent_Verify.png[Wwise_UEAkEvent_Verify, 500] + +If everything has worked correctly, you can now test the event by right-clicking the event in Unreal and clicking `Play Event`. +This will trigger the event in the editor, for example, playing the sound if the event is a Play-type event. + +=== Triggering AKEvents in Code + +Triggering AKEvents is typically done in Blueprint code. +Although it is possible to trigger them from {cpp}, this is not recommended, as it would require passing lots of asset references to the {cpp} side. If you want to trigger events from {cpp}, define a `BlueprintImplementableEvent` UFUNCTION for your {cpp} code to call, allowing you to define the implementation in Blueprint. + +==== Fire & Forget Events + +If you would like to play a one-off AK event, such as a spark sound, you will need to use the following method in your blueprint. + +image:Satisfactory/Wwise/Wwise_UEAkEvent_FireAndForget.png[Wwise_UEAkEvent_FireAndForget, 100%] + +This will create a new temporary `AK Component` and then play the AK Event specified. + +Once the AK event has ended, the temporary `AK Component` will be automatically cleaned up. + +==== Looping Events + +If you would like to play a sound effect that might loop, for example, a humming/buzzing sound for a building, you should use the same AK Component for ease of reference and to avoid the creation/destruction overhead. Add an `AK Component` to your actor blueprint and set the `AK Audio Event` variable on the component. + +Make sure to stop the audio when the actor is destroyed, +otherwise it will continue to play with no way to stop it. + +image:Satisfactory/Wwise/Wwise_UEAkEvent_EndPlay.png[Wwise_UEAkEvent_EndPlay, 100%] + +=== Updating Wwise Values From Your Mod + +Wwise uses a feature called Real-Time Parameter Control (RTPC) that allows game engines like Unreal or Unity to change values on Wwise assets in real-time. +This enables special behaviors like a manufacturing building's sound volume to fluctuate based on recipe progress. + +After setting up RTPC in Wwise and Unreal, blueprint code can update audio parameter values. + +To set these up, in your Wwise project, go to Project Explorer and the `Game Syncs` tab. + +Under `Game Parameters -> Default Work Unit` create a new game parameter by right-clicking the `Default Work Unit` and then `New Child -> Game Parameter` + +image:Satisfactory/Wwise/Wwise_RTPC_Create.png[Wwise_RTPC_Create, 100%] + +Name this whatever you want. + +Open the newly created Game Parameter, and you should see the following in the main section: + +image:Satisfactory/Wwise/Wwise_RTPC_Range.png[Wwise_RTPC_Range, 100%] + +The parameter must have a range defined. +A useful range is `0.0` to `1.0` since many existing game and engine systems already use that range as a start-finish, minimum-maximum, or off-on scale. + +Now, assign the RTPC Game Parameter to your audio. + +Open your Audio in Wwise and go to the `RTPC` tab. +Click the `>>` in the main section to set what you want to update. +This example case shows updating the `Voice Volume`. + +Then click the `>>` to the right of the first one and select your game parameter. + +image:Satisfactory/Wwise/Wwise_RTPC_Configure.png[Wwise_RTPC_Configure, 500] + +Once that is done, you should see something similar to the following: + +image:Satisfactory/Wwise/Wwise_RTPC_Overview.png[Wwise_RTPC_Overview, 100%] + +Now, to create the link between Unreal Engine and Wwise you will need to create the Game Parameter in Unreal Engine: + +image:Satisfactory/Wwise/Wwise_UE_RTPC_Create.png[Wwise_UE_RTPC_Create, 600] + +Name it the same as you have in Wwise. + +You can now update the RTPC Game Parameter value using blueprints: + +image:Satisfactory/Wwise/Wwise_UE_RTPC_Usage.png[Wwise_UE_RTPC_Usage, 700] + +=== Playback Limits + +Wwise limits the amount of audio that can be played at once. +Trying to play more than this limit will result in lower-priority audio like footsteps, music, or animals to stop playing. + +To resolve this, you will need to set playback limits for each of your audio files. This can be done in the audio's advanced settings tab. + +image:Satisfactory/Wwise/Wwise_PlaybackLimit.png[Wwise_PlaybackLimit, 700] + +You will need to set the `Limit sound instance to` amount; this is the number of instances that can play this audio on the AK Component in Unreal. +Also, set the dropdown next to this limit to `Per Game Object`. In Unreal, this means per `AK Component`. + +Next, you will need to change the `When limit is reached` to `Kill voice` and set the drop-down menu under that to `Discard oldest instances`. +This means that when the limit for this audio is reached, it will kill any oldest instances and discard them. + +Finally, you will need to set up playback priority. The playback priority requires that you set up Attenuation. + +Set the priority of your audio to something like `10`, then set the `Offset priority by` setting to `-10`. + +This setting will set the audio priority to 10, and then when you are outside the attenuation distance, it will set the priority to 0, allowing for more important audio, like the game sounds, to be played. + +Even with Attenuation and playback limits set, the audio will still play and count towards the Wwise Playback Limit. + +* Attenuation will only lower the volume of the audio and not stop the audio. +* Playback limits only limit the number of audio instances playing on a game object. + +So, to prevent audio from playing when you are outside of the attenuation range, you will need to use the Significance Manager. + +For playing background building sounds, use the `Gained Significance` and `Lost Significance` events: + +image:Satisfactory/Wwise/Wwise_Significance.png[Wwise_Significance, 700] + +For fire and forget AK events, use the `Get Is Significant` function before posting the event: + +image:Satisfactory/Wwise/Wwise_IsSignificant.png[Wwise_IsSignificant, 700] + +== Wwise and Source Control + +[NOTE] +==== +This heading is a work in progress. +The SML team plans to ship a Wwise project that includes stubs for base game Wwise events in the future. +The suggested approach in this heading may change once that process is complete. +==== + +Wwise project files require extra consideration to store in +xref:Development/BeginnersGuide/LearnGit.adoc[source control]. +Distributing the raw audio assets is sometimes prohibited by audio licenses. + +One approach is to create a separate (private) repository to store the Wwise project and to enable Git LFS for raw audio files. +However, this interferes with the typical one-repo-per-mod structure by tying multiple mod's files together in one repository. + +Wwise offers advice on connecting to source control +https://www.audiokinetic.com/en/library/edge/?source=Help&id=using_wwise_with_source_control_system[in their documentation]. -See the xref:Development/Satisfactory/AdaMessages.adoc[dedicated page on ADA Messages] for more information. == Volume Options @@ -50,3 +397,20 @@ RTPC.Menu_Volume_Weapons These values are on a scale of `0.0` (off) to `1.0` (full volume). If multiple categories apply, multiply them together to reach the final volume value. For example, the Chainsaw's volume is probably Master multiplied with Equipment multiplied with the chainsaw's specific category. + +You may also wish to implement your own volume slider to factor into the mix. +The suggested approach is to create a +xref:Development/ModLoader/Configuration.adoc[mod float config option] +combobox ranging from 0.0 to 1.0 and multiplying it with the other relevant volume categories to use as the final volume. + +=== Volume with the Unreal Audio System + +Unreal's play sound nodes take volume as a float parameter. +Follow the steps in the main Volume Options section to combine the relevant volume slider values to obtain the final input volume. + +=== Volume with Wwise + +The game's master volume slider is automatically applied to any sounds played through Wwise. +Following other base game volume sliders requires using the respective audio busses on the event. + +The RTPC system can be used to factor in arbitrary volume options from other sources. diff --git a/modules/ROOT/pages/Development/Satisfactory/IconLibrary.adoc b/modules/ROOT/pages/Development/Satisfactory/IconLibrary.adoc new file mode 100644 index 00000000..ab6b762f --- /dev/null +++ b/modules/ROOT/pages/Development/Satisfactory/IconLibrary.adoc @@ -0,0 +1,172 @@ += Icon Libraries + +Extending the set of icons available for use in the game's sign, map stamps, and map icon system requires creating an Icon Library data asset. +Adding new icons is a relatively straightforward process but there are some considerations to be made. + +This page walks through creating an Icon Library, adding icons to it, +and editing it as your mod evolves. + +[IMPORTANT] +==== +The game's icon library system is originally designed to be used with an editor tool that is not available to modders. +As such, many of the warnings and mentioned in the headers (and field hover tooltips) are not relevant to modders. + +Disregard the tooltips' warnings, but be sure to read the warnings and notes posted on this page. +==== + +== Setup + +Before getting started you will need to add some +xref:Development/ModLoader/AccessTransformers.adoc[Access Transformers]. +The game's icon library system has a couple safeguards to avoid icon ID conflicts, +but we must turn off these safeguards to add modded icons in our own libraries. + + +// TODO SML3.10.0 AccessTransformer EditAnywhere edits still on dev +> EditAnywhere AccessTransformers currently on the SML dev branch, but since they are editor-time, they can still be used to package mods for SML 3.9.1 + +Add the following to your mod's `AccessTransformers.ini`: + +[source,ini] +---- +[AccessTransformers] + +; Custom FGIconLibrary +EditAnywhere=(Class="/Script/FactoryGame.IconData", Property="ID") +EditAnywhere=(Class="/Script/FactoryGame.IconData", Property="IconType") +EditAnywhere=(Class="/Script/FactoryGame.IconData", Property="ItemDescriptor") +EditAnywhere=(Class="/Script/FactoryGame.IconData", Property="DisplayNameOverride") +---- + +== Create the Icon Library Data Asset + +A data asset needs to be created to hold all the information about the icons you are adding. +Create a data asset using the Content Browser by right-clicking on empty space in your mod's Content folder, hovering over `Miscellaneous` and selecting `Data Asset`. + +image:Satisfactory/IconLibrary/CreateDataAsset.png[Screenshot of creating a new Data Asset in the editor] + +Then select `FGIconLibrary` as the Data Asset Class + +image:Satisfactory/IconLibrary/SelectDataAssetClass_FGIconLibrary.png[Screenshot of selecting Data Asset class] + +Place the asset wherever you'd like in your mod's files. +The game's Icon Database Subsystem will automatically detect and load it. + +== Importing Icon Images + +You will need to import images to be used as icons if they aren't already part of your mod. +To do this simply right-click on an empty space again and this time select `Import to /[YourModReference]`, then use the file browser to select your image(s). + +image:Satisfactory/IconLibrary/ImportAsset.png[Screenshot of import asset context menu] + +Some Texture settings can be set to match Vanilla icons. + +In the `Level Of Detail` section: + +* Mip Gen Settings = `FromTextureGroup`` +* Texture Group = `UI Streamable` + +In the `Compression` section: + +* Compression Settings = `Default (DX11/...)` + +image:Satisfactory/IconLibrary/IconTextureSettings.png[Screenshot of icon Texture asset settings] + +Everything else can be left as the default from when it was imported. + +=== Image Considerations + +There are a couple things to keep in mind for your images: + +1. Images should be square. Signs will stretch images into a square so if you want it to show correctly make sure you crop it to a square before importing. +2. PNGs with alpha backgrounds work best. Vanilla icons have alpha backgrounds, so to best match the vanilla style yours should have that as well. + +== Filling out the Data Asset + +Upon opening the data asset you will see several different arrays you can add icons to. No matter what type of icon you are adding you will want to use `M Icon Data`. If you add your icon in one of the other arrays it will not show in-game. + +Add a new element to `M Icon Data`, it should look like this: + +image:Satisfactory/IconLibrary/FreshIconDataArrayElement.png[Screenshot of newly created Icon Data array element] + +[cols="1,4a"] +|=== +| Field | Description of Function + +| ID +| Each of your icons requires a unique, non-negative ID. For ease of editing, start at 0 and use the same number as the array index. + +[NOTE] +==== +Icon IDs must be unique within the Data Asset, but not across Icon Libraries. +If you have multiple Icon Library Data Assets it's safe to reuse IDs as long as it isn't within the same Library asset. +==== + +| Texture +| Required. The texture (or material instance) to use for the icon. + +| Item Descriptor +| Optional. If you want to duplicate the name of an item or building, select its descriptor here. + +| Display Name Override +| When checked, the `Item Descriptor` field will be ignored and `Icon Name` will be used instead. + +| Icon Name +| The user-facing icon name to use for the icon. Required, unless an `Item Descriptor` is provided. + + +* When no `Item Descriptor` is provided, the field is used as the icon name. +* When an `Item Descriptor` is provided, this field is only used as the icon name when `Display Name Override` is true, otherwise the value is ignored. + +| Icon Type +| Required. Controls the category the icon is sorted into in-game, +and if it's treated as a map stamp icon. +Set this to something other than `ESIT None`. + +| Hidden +| When checked, the icon will not be available for selection in-game. +Use this if you want to remove an icon from the library instead of deleting its array entry. + +| Search Only +| When checked, this icon will only appear when searched for directly. + +| Animated +| see link:#AnimatedBackgrounds[Animated Backgrounds] for more information. + +|=== + +== Adding and Removing Icons + +To add new icons, simply add new array elements and ensure they have unique IDs. + +[IMPORTANT] +==== +When removing icons from your library, use the Hidden field instead of removing them! + +Although it's possible to remove array entries, this is highly discouraged as it could result in you accidentally re-using an ID later. +Re-using an ID will cause users' signs to unexpectedly change from the old icon to the new icon. +Instead, it is recommended to simply leave the array entry in place and enable the `Hidden` boolean property. +Clear the texture reference if necessary. +==== + +== Finishing Up + +To test your icon library, package the mod and build a sign to see if your icons are showing up. +Check out Example Mod's `ExampleModIcons` if you're having trouble getting your icon library settings to work. + +== Special Icon Types + +This section provides some additional notes about specific Icon Type values. + +[id="AnimatedBackgrounds"] +=== Animated Backgrounds + +It is possible to add new animated backgrounds. +Look at `FactoryGame/Interface/UI/InGame/Signs/SignBackgrounds` for some examples of settings for animated backgrounds. + +NOTE: Animated icons will only animate when used as a background, and all backgrounds are automatically made grayscale when selected in-game. + +=== Map Stamps + +Using Icon Type `ESIT_Map_Stamp` will result in the icon automatically appearing as a stamp option in the game's map UI. + diff --git a/modules/ROOT/pages/Development/Satisfactory/Inventory.adoc b/modules/ROOT/pages/Development/Satisfactory/Inventory.adoc index 296a6330..8a15ac24 100644 --- a/modules/ROOT/pages/Development/Satisfactory/Inventory.adoc +++ b/modules/ROOT/pages/Development/Satisfactory/Inventory.adoc @@ -1,7 +1,10 @@ = Inventories and Items -This page doesn't just describe the inventory itself, -but also everything else that is used by it. +[NOTE] +==== +This page is not comprehensive. +Check out the comments in `FGInventoryComponent.h` and `FGInventoryLibrary.h` for additional context and helper functions. +==== == Item Descriptor [.title-ref]#(`UFGItemDescriptor`)# @@ -12,23 +15,30 @@ and UFGFactoryCustomizationDescriptor (Customizer patterns), which are not 'items' in the usual sense, and do not make use of all available UFGItemDescriptor properties. -== Item [.title-ref]#(`FInventoryItem`)# +== Inventory Item [.title-ref]#(`FInventoryItem`)# -This structure contains information about a item (class pointer to a item descriptor) and its connected item state (any kind of actor). +Represents a single "instance" of an item descriptor and its associated item state (any kind of actor). +Usually used when referring to items outside of inventories, for example, on belts. -== ItemAmount [.title-ref]#(`FItemAmount`)# +Most items do not have state, and the game's recipe system ignores item state. +Equipment items use item state to store ammo/fuel levels, user settings, and other persistent data. -This struct connects just a item descriptor and a count of items without a state. -That means, this structure is not used to hold information the representation of a item ingame. -Instead this is f.e. use in a recipe to define how many items of what type of item you need to bring up to get some different type of item with a different amount of them. +== Item Amount [.title-ref]#(`FItemAmount`)# -== ItemStack [.title-ref]#(`FItemStack`)# +Associates an item descriptor class with a count of items, notably without an item state. +Useful for representing quantities of items without regard to how they are being stored. +Primarily used to define ingredients/products in recipes and costs of schematics. -This is the brother of ItemAmount but this time it holds a Item and a count. -That means, this time, it is actually used to hold information about item and its count ingame. -F.e. how many items of what kind are in one player inventory slot? +Be careful converting these to/from Inventory Stacks to avoid losing item state data. -== FGInventoryComponent [.title-ref]#(`UFGInventoryComponent`)# +== Inventory Stack [.title-ref]#(`FInventoryStack`)# -This is a `USceneComponent` used to attach a inventory, able to hold multiple Item Stacks at the same time, to a actor. This is not only used for the player, its nearly always used were you know there are items inside. -That means you can think of them like a container full of items. \ No newline at end of file +Represents an Inventory Item as a stack of potentially multiple items. +Unlike Item Amount, this maintains state data. + +Be careful converting these to/from Item Amounts to avoid losing item state data. + +== Inventory Component [.title-ref]#(`UFGInventoryComponent`)# + +A `USceneComponent` used to attach a inventory, able to hold multiple Inventory Stacks at the same time, to a actor. This is not only used for the player, it's nearly always used where you know there are items inside. +That means you can think of them like a container full of items. diff --git a/modules/ROOT/pages/Development/Satisfactory/Savegame.adoc b/modules/ROOT/pages/Development/Satisfactory/Savegame.adoc index 7da4fee2..b37f80e9 100644 --- a/modules/ROOT/pages/Development/Satisfactory/Savegame.adoc +++ b/modules/ROOT/pages/Development/Satisfactory/Savegame.adoc @@ -120,3 +120,11 @@ Generally, content created by mods appears under `Game//` tag. Here is a screenshot from https://github.com/Goz3rr/SatisfactorySaveEditor/[SatisfactorySaveEditor] displaying data from a mod with the reference NogsOres. image:https://i.imgur.com/0sdahyB.png[image] + +== Save File Structure + +You can learn more about the save file format via the following resources: + +- https://github.com/moritz-h/satisfactory-3d-map/blob/master/docs/SATISFACTORY_SAVE.md[Morizt-h's documentation on the save file format] +- https://satisfactory.wiki.gg/wiki/Save_files#Save_file_format[Satisfactory Wiki: Save files] +- Looking at open source https://ficsit.app/tools[tools] to learn how they implemented their features. diff --git a/modules/ROOT/pages/Development/Satisfactory/ShoppingList.adoc b/modules/ROOT/pages/Development/Satisfactory/ShoppingList.adoc index 732ce916..9941a2ef 100644 --- a/modules/ROOT/pages/Development/Satisfactory/ShoppingList.adoc +++ b/modules/ROOT/pages/Development/Satisfactory/ShoppingList.adoc @@ -12,7 +12,7 @@ The shopping list portion of the to-do list is a list of items that the player w Players can manually add items to it from the codex, crafting bench, and buildgun. The shopping list can hold arbitrary data, -but the base game seems to have only implemented visualization of Recipes and Blueprints. +but the base game seems to have only implemented visualization of Schematics, Recipes, and Blueprints. Obtain a reference to the player's shopping list via the Get Shopping List Component static function of FGShoppingListComponent. diff --git a/modules/ROOT/pages/Development/UpdatingFromSml38.adoc b/modules/ROOT/pages/Development/UpdatingFromSml38.adoc index 51e29fb4..ede0da15 100644 --- a/modules/ROOT/pages/Development/UpdatingFromSml38.adoc +++ b/modules/ROOT/pages/Development/UpdatingFromSml38.adoc @@ -25,6 +25,11 @@ Clients will refuse to join servers that are missing mods present on the client The existing `RequiredOnRemote` and `RemoteVersionRange` uplugin fields control this behavior. Read more about them in the xref:Development/BeginnersGuide/ReleaseMod.adoc#_special_fields[uplugin Special Fields section]. +=== Wwise Support + +SML 3.9.1 enables mods to make use of some of the game's Wwise sound system. +See the xref:Development/Satisfactory/Audio.adoc[Audio] page for more information. + === Quick Launch Script Supports Multiplayer The xref:Development/TestingResources.adoc#LaunchScript[Quick Launch Script] @@ -112,6 +117,11 @@ Another example - this argument can be used to raise the multiplayer max player == Notable Fixes +=== Reliable Buffer Overflow + +Mircea has created a standalone mod to address one of the causes of the Reliable Buffer Overflow issue. +See https://ficsit.app/mod/FixReliableBufferOverflow[its mod page] for more information. + === Content Registry Issue with Mod Schematics Depending on Vanilla Schematics Mods can now alter vanilla content to unlock-depend on modded content without breaking its registration. @@ -142,8 +152,9 @@ This is a https://github.com/satisfactorymodding/SatisfactoryModLoader/issues/15 and will be fixed in a future SML release. The next best way is to use sublevel spawning. Here is an example from Kyrium of how to do that: -* https://github.com/Satisfactory-KMods/KBFL/blob/d21381de3621d25f063ecfbf24b5d35533da4357/Source/KBFL/Private/Subsystems/ResourceNodes/KBFLSubLevelSpawning.cpp#L41 -* https://github.com/Satisfactory-KMods/KBFL/blob/d21381de3621d25f063ecfbf24b5d35533da4357/Source/KBFL/Private/Subsystems/KBFLResourceNodeSubsystem.cpp#L67 + +* https://github.com/Satisfactory-KMods/KBFL/blob/d21381de3621d25f063ecfbf24b5d35533da4357/Source/KBFL/Private/Subsystems/ResourceNodes/KBFLSubLevelSpawning.cpp#L41[KBFLSubLevelSpawning] +* https://github.com/Satisfactory-KMods/KBFL/blob/d21381de3621d25f063ecfbf24b5d35533da4357/Source/KBFL/Private/Subsystems/KBFLResourceNodeSubsystem.cpp#L67[KBFLResourceNodeSubsystem] == Required Changes diff --git a/modules/ROOT/pages/Development/UpdatingFromSml39.adoc b/modules/ROOT/pages/Development/UpdatingFromSml39.adoc new file mode 100644 index 00000000..a1b70a90 --- /dev/null +++ b/modules/ROOT/pages/Development/UpdatingFromSml39.adoc @@ -0,0 +1,77 @@ += Upgrading from SML 3.9.x to 3.10.x + +[NOTE] +==== +You have found a hidden docs page! + +This page is still a work in progress. + +If you have any feedback, please let us know in the Discord. +==== + +TODO + +Look for // TODO SML3.10.0 docs comments before merging + +Please _read this entire page before you begin updating your mod_. +It will save you time later to have an idea going in of what to expect while updating. +After you have finished reading this page, +follow the directions on the +xref:Development/UpdatingToNewVersions.adoc[Updating your Mod] +guide to install the updated engine, starter project, and update your mod. + +== New Features + +This section talks about the new features that SML 3.10 brings to the table. + +TODO + +- BlueprintType access transformer +- EditAnywhere access transformer + +== Notable Fixes + +TODO + +== Not Done Yet + +The following features are not quite ready to use yet. + +=== Advanced Game Settings values not saved + +The xref:Development/ModLoader/SessionSettings.adoc[Session Settings] page +explains how you can create your own Advanced Game Settings. +However, their values are not currently saved with the save file. +Session Settings still function correctly - their values are saved. + +=== Content Bundle Cooking + +The optimal way to add modded content to the game world (like ore nodes, deposits, etc.) +is to use the Content Bundle system, +but Unreal currently refuses to cook content bundles unless the world is also cooked. +This is a https://github.com/satisfactorymodding/SatisfactoryModLoader/issues/155[known bug] +and will be fixed in a future SML release. + +The next best way is to use sublevel spawning. Here is an example from Kyrium of how to do that: + +* https://github.com/Satisfactory-KMods/KBFL/blob/d21381de3621d25f063ecfbf24b5d35533da4357/Source/KBFL/Private/Subsystems/ResourceNodes/KBFLSubLevelSpawning.cpp#L41[KBFLSubLevelSpawning] +* https://github.com/Satisfactory-KMods/KBFL/blob/d21381de3621d25f063ecfbf24b5d35533da4357/Source/KBFL/Private/Subsystems/KBFLResourceNodeSubsystem.cpp#L67[KBFLResourceNodeSubsystem] + +== Required Changes + +In addition to any specific-to-your-mod issues you may encounter, +the changes described below _must_ be made in order for your mod to be updated. + +TODO + +- There are no required changes for this SML update! + +== Additional Changes + +You might not be affected by these changes, +but we'd like to draw extra attention to them. + +TODO + +- cpp Chat command usage FString -> FText +- Cpp Mod config desc FString -> FText \ No newline at end of file diff --git a/modules/ROOT/pages/ForUsers/SatisfactoryModManager.adoc b/modules/ROOT/pages/ForUsers/SatisfactoryModManager.adoc index 100fdb82..3e462645 100644 --- a/modules/ROOT/pages/ForUsers/SatisfactoryModManager.adoc +++ b/modules/ROOT/pages/ForUsers/SatisfactoryModManager.adoc @@ -193,7 +193,7 @@ This can be useful if you want to temporarily turn a mod off for troubleshooting If you're trying to remove a specific mod from your mod manager profile and it's not working, try creating a new profile. You could also try -link:#_how_do_i_share_my_mods_with_my_friends_for_multiplayer[exporting your profile], +xref:faq.adoc#_how_do_i_share_my_mods_with_my_friends_for_multiplayer[exporting your profile], editing the file to delete the mod listing, then importing it again. == Turning Off All Mods diff --git a/modules/ROOT/pages/SMLChatCommands.adoc b/modules/ROOT/pages/SMLChatCommands.adoc index ddff7021..d1f18ab8 100644 --- a/modules/ROOT/pages/SMLChatCommands.adoc +++ b/modules/ROOT/pages/SMLChatCommands.adoc @@ -101,7 +101,7 @@ xref:Development/BeginnersGuide/dependencies.adoc#CustomEngine[here]. |Cheats | Open the Coffee Stain Studios cheats user interface. -| Mod developers can add cheats here by following xref:Development/Satisfactory/CheatBoard.adoc[these directions]. +Mod developers can add cheats here by following xref:Development/Satisfactory/CheatBoard.adoc[these directions]. | (Unspecified) // From UE CheatManager diff --git a/modules/ROOT/pages/faq.adoc b/modules/ROOT/pages/faq.adoc index b00efa5b..376c4031 100644 --- a/modules/ROOT/pages/faq.adoc +++ b/modules/ROOT/pages/faq.adoc @@ -34,9 +34,6 @@ To turn off mods entirely, flip the "Mods" switch in the top left corner of the image:FAQ/TurnOffMods.png[Satisfactory Mod Manager Off Switch] -If this fails for some reason, go to `%appdata%\SatisfactoryModManager\profiles` and delete the vanilla folder, -then restart SMM and turn mods on and back off. - If for some reason this still doesn't work, delete the "Mods" folder from your link:#_where_are_my_game_files_located[game's install directory]. @@ -662,7 +659,7 @@ Expect it to take up about 30 gigabytes. One way to do this is to right click on it and select create shortcut. 4. Open the shortcut's properties from the right click menu. -Under the "Shortcut" settings tab, modify the "Target" line to end in ` -NoSteamClient -EpicPortal`. +Under the "Shortcut" settings tab, modify the "Target" line to end in `-NoSteamClient -EpicPortal`. Make sure you have a space between the file path and this launch argument. 5. You now have a standalone version of the game that will not update or talk to Steam.