Beef
Beef
SMSatisfactory Modding
Created by Beef on 12/10/2024 in #modding-resources
ModProfile Profiling Lib
Simple header-only lib to allow simple profiling of C++ methods within your mod I wasn't really happy with Unreal Insights or Jetbrains profiling tools as they tend to take more time to get the information I need in a modding context. This is much simpler and straightforwards. This library simply outputs the method name and the execution time into your log:
UResourceRouletteManager::InitMeshesToDestroy executed in 0.01 ms
Persistent callback for tagging new actors has been registered.
UResourceCollectionManager::CollectWorldResources executed in 6.06 ms
UResourcePurityManager::CollectOriginalPurities executed in 0.01 ms
Cached new Original Resource node data.
Resource Scan from Save.
UResourceRouletteManager::ScanWorldResourceNodes executed in 13.04 ms
UResourceRouletteManager::RandomizeWorldResourceNodes executed in 0.01 ms
Number of nodes to spawn: 621
UResourceNodeSpawner::SpawnWorldResources executed in 54.50 ms
UResourceRouletteUtility::AssociateExtractorsWithNodes executed in 0.01 ms
Resources Spawning completed successfully.
UResourceRouletteManager::InitMeshesToDestroy executed in 0.01 ms
Persistent callback for tagging new actors has been registered.
UResourceCollectionManager::CollectWorldResources executed in 6.06 ms
UResourcePurityManager::CollectOriginalPurities executed in 0.01 ms
Cached new Original Resource node data.
Resource Scan from Save.
UResourceRouletteManager::ScanWorldResourceNodes executed in 13.04 ms
UResourceRouletteManager::RandomizeWorldResourceNodes executed in 0.01 ms
Number of nodes to spawn: 621
UResourceNodeSpawner::SpawnWorldResources executed in 54.50 ms
UResourceRouletteUtility::AssociateExtractorsWithNodes executed in 0.01 ms
Resources Spawning completed successfully.
https://github.com/TheRealBeef/Satisfactory-ModProfile-Lib
1 replies
SMSatisfactory Modding
Created by Beef on 11/30/2024 in #help-using-mods
Splitter and merger meshes disappeared
No description
65 replies
SMSatisfactory Modding
Created by Beef on 11/26/2024 in #modding-resources
Helpful UE5 Plugins
If you have any that you use, please post them here as well! Graph Formatter (to automatically format Blueprint Nodes) - Thanks to SirDigby for finding this https://www.fab.com/listings/45218c70-1d87-4d34-ae71-4f575395af64 if you want to support that dev, but it's also open-source and hosted on github at https://github.com/howaajin/graphformatter
1 replies
SMSatisfactory Modding
Created by Beef on 11/20/2024 in #help-developing-mods
Buildable Nodes Redux + Resource Roulette
So RR conflicts with BRN because my scanning/destroying/spawning nodes and their meshes relies primarily on AFGResouceNode classnames for identification of the vanilla nodes to remove them (and they are always trying to come back!). After skimming through the BRN mod, one simple solution that comes to mind is to request Robb to put a tag on actors/mesh components spawned by BRN as I didn't see that they're assigned (or if it exists and I missed it, I guess that's the simple solution already) I'm not sure if there's another more clever way to filter out nodes so that way I can head off potential conflicts with nodes spawned by other mods as well, as there are likely to be many more resource node mods in the future and something smarter than that simple solution would mean I don't have to update this tag filtering logic routinely. I just don't know if there's anything.
16 replies
SMSatisfactory Modding
Created by Beef on 11/20/2024 in #help-using-mods
Resource Roulette - Buildable Resource Nodes conflict
Uninstalling and reinstalling resource roulette got me the correct version in-game - but broke some ore nodes that were placed with Robb's Buildable Resource Nodes mod.
@sunyudai when you say "broke them" can you be a bit more specific (e.g. they're there but don't work, or they're not there, etc)
16 replies
SMSatisfactory Modding
Created by Beef on 11/18/2024 in #modding-resources
TObjectIterators the speedy-er way
So as best I understand, in general using
for (TObjectIterator<UStaticMeshComponent> It; It; ++It)
for (TObjectIterator<UStaticMeshComponent> It; It; ++It)
is bad - it's not a good idea to iterate all the UStaticMeshComponents (in a fresh save there's about 10k of them) or whatever other component you want to iterate over, but sometimes it seems somewhat unavoidable for whatever reason. I just wanted to share the results of my profiling in case it helps This simple approach takes between 5-7ms to run on my PC.
for (TObjectIterator<UStaticMeshComponent> It; It; ++It)
{
UStaticMeshComponent* StaticMeshComponent = *It;
if (StaticMeshComponent && StaticMeshComponent->GetWorld() == World && !StaticMeshComponent->ComponentTags.
Contains(ResourceRouletteTag))
{
if (const UStaticMesh* StaticMesh = StaticMeshComponent->GetStaticMesh())
{
FName MeshPath = FName(*StaticMesh->GetPathName());
if (MeshesToDestroy.Contains(MeshPath))
{
StaticMeshComponent->SetActive(false);
StaticMeshComponent->SetVisibility(false);
StaticMeshComponent->DestroyComponent();
}
}
}
}
for (TObjectIterator<UStaticMeshComponent> It; It; ++It)
{
UStaticMeshComponent* StaticMeshComponent = *It;
if (StaticMeshComponent && StaticMeshComponent->GetWorld() == World && !StaticMeshComponent->ComponentTags.
Contains(ResourceRouletteTag))
{
if (const UStaticMesh* StaticMesh = StaticMeshComponent->GetStaticMesh())
{
FName MeshPath = FName(*StaticMesh->GetPathName());
if (MeshesToDestroy.Contains(MeshPath))
{
StaticMeshComponent->SetActive(false);
StaticMeshComponent->SetVisibility(false);
StaticMeshComponent->DestroyComponent();
}
}
}
}
4 replies
SMSatisfactory Modding
Created by Beef on 11/15/2024 in #help-developing-mods
Moving Meshes at Runtime
Moving this here as it's still a blocker for me and I guess it's more complicated as the more general UE modding server suggested coming back here to ask again - Do you have to change anything else meshes to update? E.g. setting visibility off and on again, or disabling/re-enabling collision? When updating node location, such as using
ResourceNode->SetActorLocation(NodeData.Location);
ResourceNode->SetActorRotation(NodeData.Rotation);
MeshComponent->SetWorldLocation(NodeData.Location);
MeshComponent->SetWorldRotation(NodeData.Rotation);
ResourceNode->SetActorLocation(NodeData.Location);
ResourceNode->SetActorRotation(NodeData.Rotation);
MeshComponent->SetWorldLocation(NodeData.Location);
MeshComponent->SetWorldRotation(NodeData.Rotation);
I notice that setting this location/rotation for both works if its during their spawn, but it doesn't appear to update their location once they've already been spawned. I'm also not entirely sure if I have to update the MeshComponent separately from the Actor or not, since the mesh is attached to the actor when I spawn them using
ResourceNode->SetRootComponent(MeshComponent);
MeshComponent->RegisterComponent();
ResourceNode->SetRootComponent(MeshComponent);
MeshComponent->RegisterComponent();
tried again with
ResourceNode->SetActorLocation(NodeData.Location, false, nullptr, ETeleportType::TeleportPhysics);
ResourceNode->SetActorRotation(NodeData.Rotation, ETeleportType::TeleportPhysics);
MeshComponent->SetWorldLocation(NodeData.Location, false, nullptr, ETeleportType::TeleportPhysics);
MeshComponent->SetWorldRotation(NodeData.Rotation, false, nullptr, ETeleportType::TeleportPhysics);
ResourceNode->SetActorLocation(NodeData.Location, false, nullptr, ETeleportType::TeleportPhysics);
ResourceNode->SetActorRotation(NodeData.Rotation, ETeleportType::TeleportPhysics);
MeshComponent->SetWorldLocation(NodeData.Location, false, nullptr, ETeleportType::TeleportPhysics);
MeshComponent->SetWorldRotation(NodeData.Rotation, false, nullptr, ETeleportType::TeleportPhysics);
the method is being called and is updating these appropriately, and the mesh is moveable (also as an aside, weird how AActor::SetActorRotation is missing the fields the other methods have ... (https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/GameFramework/AActor/SetActorRotation/1) I can't find anything in UE documentation or forum/reddit/etc that seems to deal with this
25 replies
SMSatisfactory Modding
Created by Beef on 11/14/2024 in #help-developing-mods
Randomization Logic
I'm trying to lay down good logic for randomization that makes sense, and wonder if I've made some oversights in my planning. I know there are efficiency optimizations that can be done, but wrapping my head around this one by itself has already bent my brains into a pretzel so that will come later. Variables:
NotProcessedResourceNodes (sorted by class and then by purity from pure->impure)
NotProcessedPossibleLocations (this is already in pseudorandom order based on seed)

NotProcessedSingleResourceNodes
NotProcessedSinglePossibleLocations
NotProcessedResourceNodes (sorted by class and then by purity from pure->impure)
NotProcessedPossibleLocations (this is already in pseudorandom order based on seed)

NotProcessedSingleResourceNodes
NotProcessedSinglePossibleLocations
Processing Logic
- While there are still nodes in NotProcessedResourceNodes (starting with the last one and working towards first one)
- Check to ensure we still have NotProcessedResourceNodes and we still have NotProcessedPossibleLocations available, otherwise break out of the loop
- If it's one of the non-groupable classes, add it to NotProcessedSingleResourceNodes and remove from NotProcessedResourceNodes.
- Otherwise, grab the last index of NotProcessedPossibleLocations
- Feed this possible location and the current list of all Possible locations into LocationGrouper, and recursively check what other NotProcessedPossibleLocations are within GroupingRadius. We use recursion to ensure we will get multiple resources that are all in a row or otherwise very close but are not all within the radius of the starting NotProcessedPossibleLocations.
- Return the list (and the list of their corresponding indexes in NotProcessedPossibleLocations) for each location within the group.
- If we have only 1 location in the group, then we use a Counter % 4 != 0 that's initialized at the start to give it a deterministic 25% chance of being used. If it fails (75% chance), then we insert the location to the NotProcessedSinglePossibleLocations and remove it from NotProcessedPossibleLocations.
- While there are still nodes in NotProcessedResourceNodes (starting with the last one and working towards first one)
- Check to ensure we still have NotProcessedResourceNodes and we still have NotProcessedPossibleLocations available, otherwise break out of the loop
- If it's one of the non-groupable classes, add it to NotProcessedSingleResourceNodes and remove from NotProcessedResourceNodes.
- Otherwise, grab the last index of NotProcessedPossibleLocations
- Feed this possible location and the current list of all Possible locations into LocationGrouper, and recursively check what other NotProcessedPossibleLocations are within GroupingRadius. We use recursion to ensure we will get multiple resources that are all in a row or otherwise very close but are not all within the radius of the starting NotProcessedPossibleLocations.
- Return the list (and the list of their corresponding indexes in NotProcessedPossibleLocations) for each location within the group.
- If we have only 1 location in the group, then we use a Counter % 4 != 0 that's initialized at the start to give it a deterministic 25% chance of being used. If it fails (75% chance), then we insert the location to the NotProcessedSinglePossibleLocations and remove it from NotProcessedPossibleLocations.
15 replies
SMSatisfactory Modding
Created by Beef on 11/13/2024 in #help-developing-mods
Struct not serializing to savefile
No description
8 replies
SMSatisfactory Modding
Created by Beef on 11/8/2024 in #modding-resources
StreamDeck Actions for Devs
No description
21 replies
SMSatisfactory Modding
Created by Beef on 11/8/2024 in #modding-resources
ModLog Logging Library
I put together a somewhat dirty logging library that allows you to write clean logs to external files. It's got both blueprint and C++ callable methods. https://github.com/TheRealBeef/Satisfactory-ModLog-Lib It could certainly use some improvements but may be handy
1 replies
SMSatisfactory Modding
Created by Beef on 11/5/2024 in #modding-resources
Resource Node Related Knowledge (Vanilla and Modded)
AFGResourceNode Classnames Could be handy for making custom spawners/despawners or randomizing node locations etc Vanilla Resource types:
Gas - EResourceForm::RF_GAS:
Desc_NitrogenGas_C

Heat - EResourceForm::RF_HEAT:
Desc_Geyser_C

Liquid - EResourceForm::RF_LIQUID:
Desc_LiquidOil_C
Desc_Water_C

Solid - EResourceForm::RF_SOLID:
Desc_SAM_C
Desc_Stone_C
Desc_OreIron_C
Desc_OreCopper_C
Desc_OreGold_C
Desc_Coal_C
Desc_RawQuartz_C
Desc_Sulfur_C
Desc_OreBauxite_C
Desc_OreUranium_C
Gas - EResourceForm::RF_GAS:
Desc_NitrogenGas_C

Heat - EResourceForm::RF_HEAT:
Desc_Geyser_C

Liquid - EResourceForm::RF_LIQUID:
Desc_LiquidOil_C
Desc_Water_C

Solid - EResourceForm::RF_SOLID:
Desc_SAM_C
Desc_Stone_C
Desc_OreIron_C
Desc_OreCopper_C
Desc_OreGold_C
Desc_Coal_C
Desc_RawQuartz_C
Desc_Sulfur_C
Desc_OreBauxite_C
Desc_OreUranium_C
Modded (Currently only FF and RP - please let me know of other ones and I'll add to list. OFC these are subject to change more frequently than vanilla))
-- Ficsit Farming --
Solid - EResourceForm::RF_SOLID:
Desc_FF_Dirt_Fertilized_C
Desc_FF_Dirt_C
Desc_FF_Dirt_Wet_C

-- Refined Power --
Liquid - EResourceForm::RF_LIQUID:
Desc_RP_Deanium_C

Solid - EResourceForm::RF_SOLID:
Desc_RP_WaterDamNode_C
Desc_WaterTurbineNode_C
Desc_RP_Thorium_C
-- Ficsit Farming --
Solid - EResourceForm::RF_SOLID:
Desc_FF_Dirt_Fertilized_C
Desc_FF_Dirt_C
Desc_FF_Dirt_Wet_C

-- Refined Power --
Liquid - EResourceForm::RF_LIQUID:
Desc_RP_Deanium_C

Solid - EResourceForm::RF_SOLID:
Desc_RP_WaterDamNode_C
Desc_WaterTurbineNode_C
Desc_RP_Thorium_C
27 replies
SMSatisfactory Modding
Created by Beef on 11/4/2024 in #help-using-mods
Resource Node Randomizer conflicts with Ficsit Farming
Portable miners and miners disappear on (Ficsit Farming) dirt nodes. I believe this is a mod conflict with Resource Node Randomizer. @Marshall I believe I have a fix and will submit a PR to your Github if it works...
6 replies
SMSatisfactory Modding
Created by Beef on 11/3/2024 in #help-using-mods
Heavy Fluid Overhaul - RP/FF compatibility
Any interest in adding compatibility with Refined Power/Ficsit Farming? It may be outside your scope of work, but it appears that Heavy Fluid Overhaul has no effect on these mods (to not much surprise). Since RP/FF are closed source it's perhaps not feasible either.
8 replies
SMSatisfactory Modding
Created by Beef on 10/23/2024 in #help-developing-mods
Access Violations
I started using SUBSCRIBE_UOBJECT_METHOD() as per Mircea/Rex advice, but I still get an access violation. Starting a test world with nothing in it / no other mods besides SML, everything works OK until I place a sign. The build animation plays and then there's about 1 frame where the sign tries to display something and then the game crashes.
#include "MoreLightingOptionsModule.h"
#include "Buildables/FGBuildableWidgetSign.h"
#include "Patching/NativeHookManager.h"

class HFGBuildableWidgetSign
{
public:
static void Hook_GetAdjustedEmissiveValue(TCallScope<float(__cdecl*)(const AFGBuildableWidgetSign*, int32)>& scope, const AFGBuildableWidgetSign* self, int32 Level)
{
if (!self) {
return;
}

float BaseEmissiveValue = scope(self, Level);
float NewEmissiveValue = BaseEmissiveValue * 10.0f;
if (NewEmissiveValue >= 0.0f) {
scope.Override(NewEmissiveValue);
}
}

static void RegisterHooks()
{
SUBSCRIBE_UOBJECT_METHOD(AFGBuildableWidgetSign, GetAdjustedEmissiveValue, &HFGBuildableWidgetSign::Hook_GetAdjustedEmissiveValue);
}
};

// Startup Module for MoreLightingOptions
void FMoreLightingOptionsModule::StartupModule()
{
if (!WITH_EDITOR)
{
HFGBuildableWidgetSign::RegisterHooks();
}
}

void FMoreLightingOptionsModule::ShutdownModule()
{
}

IMPLEMENT_GAME_MODULE(FMoreLightingOptionsModule, MoreLightingOptions);
#include "MoreLightingOptionsModule.h"
#include "Buildables/FGBuildableWidgetSign.h"
#include "Patching/NativeHookManager.h"

class HFGBuildableWidgetSign
{
public:
static void Hook_GetAdjustedEmissiveValue(TCallScope<float(__cdecl*)(const AFGBuildableWidgetSign*, int32)>& scope, const AFGBuildableWidgetSign* self, int32 Level)
{
if (!self) {
return;
}

float BaseEmissiveValue = scope(self, Level);
float NewEmissiveValue = BaseEmissiveValue * 10.0f;
if (NewEmissiveValue >= 0.0f) {
scope.Override(NewEmissiveValue);
}
}

static void RegisterHooks()
{
SUBSCRIBE_UOBJECT_METHOD(AFGBuildableWidgetSign, GetAdjustedEmissiveValue, &HFGBuildableWidgetSign::Hook_GetAdjustedEmissiveValue);
}
};

// Startup Module for MoreLightingOptions
void FMoreLightingOptionsModule::StartupModule()
{
if (!WITH_EDITOR)
{
HFGBuildableWidgetSign::RegisterHooks();
}
}

void FMoreLightingOptionsModule::ShutdownModule()
{
}

IMPLEMENT_GAME_MODULE(FMoreLightingOptionsModule, MoreLightingOptions);
38 replies
SMSatisfactory Modding
Created by Beef on 10/20/2024 in #help-using-mods
SifVerT - Difficulty Tuner
There's an option to enable "Machine Parts" if you disable the crafting table, which is kind, but it also adds several milestones to research to unlock the assembler/manufacturer/etc that can be built with machine parts. However, with machine parts disabled, the milestones to unlock these machines still appear. I'm not sure if this is intended behavior or not.
7 replies
SMSatisfactory Modding
Created by Beef on 10/14/2024 in #help-using-mods
Harder Phases 10x Multiplication Bug
No description
15 replies