Add multi-level capture mode for games with streamed Blueprint classes. #495

Open
Evasion3356 wants to merge 3 commits from Evasion3356/feature/load-all-classes into main
Evasion3356 commented 2026-03-17 04:05:49 +01:00 (Migrated from github.com)
image

What this change will do, is if the user opts into it, 2 new functional keypresses will now be available. Pressing F4 marks all current UObjects in the array as EInternalObjectFlags::RootSet, which the garbage collector will skip over when it goes to run. This allows the user to load into a level with streamed Blueprint classes, leave, and then load another level, so that when the SDK is generated, it will be complete at least for each level required. I tried initially implementing a way to invoke GetAllAsssets then invoking LoadObject, but this was wildly unstable and unpredictable, as the level-specific BP code expected pointers to be passed into it during its load call that had to resolve to the type it was expected, or else it would crash.

Tested against Ready or Not engine build 5.3.2.

image image image image

`#pragma once

/*

// Package: BP_Tower_Interact_Keycard

#include "Basic.hpp"

#include "Engine_structs.hpp"
#include "Engine_classes.hpp"

namespace SDK
{

// BlueprintGeneratedClass BP_Tower_Interact_Keycard.BP_Tower_Interact_Keycard_C
// 0x0058 (0x02F8 - 0x02A0)
class ABP_Tower_Interact_Keycard_C final : public AActor
{
public:
struct FPointerToUberGraphFrame UberGraphFrame; // 0x02A0(0x0008)(ZeroConstructor, Transient, DuplicateTransient)
class UStaticMeshComponent* SM_WallSwitch_02_a; // 0x02A8(0x0008)(BlueprintVisible, ZeroConstructor, InstancedReference, NonTransactional, NoDestructor, HasGetValueTypeHash)
class UInteractableComponent* Interactable; // 0x02B0(0x0008)(BlueprintVisible, ZeroConstructor, InstancedReference, NonTransactional, NoDestructor, HasGetValueTypeHash)
bool bIsOn; // 0x02B8(0x0001)(Edit, BlueprintVisible, Net, ZeroConstructor, DisableEditOnInstance, IsPlainOldData, NoDestructor, HasGetValueTypeHash)
bool TriggerOnceOnly_; // 0x02B9(0x0001)(Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)
uint8 Pad_2BA[0x6]; // 0x02BA(0x0006)(Fixing Size After Last Property [ Dumper-7 ])
class FText PressedTextOn; // 0x02C0(0x0018)(Edit, BlueprintVisible)
class FText PressedTextOff; // 0x02D8(0x0018)(Edit, BlueprintVisible)
class FName DoorTag; // 0x02F0(0x0008)(Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash)

public:
void Server_Interact(class AReadyOrNotCharacter* InteractInstigator1, class UInteractableComponent* InteractableComponent1);
void ReceiveBeginPlay();
void OnFocusLost(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);
void OnFocusGain(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);
void NewFunction();
void Multicast_Interacted();
void MeleeInteract(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);
void Interact(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);
void Fire(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);
void ExecuteUbergraph_BP_Tower_Interact_Keycard(int32 EntryPoint);
void EndInteract(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);
void EndFire(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);
void DoubleTapInteract(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent);

class UInteractableComponent* GetInteractableComponent() const;
float DetermineInteractionDistance() const;
EInputEvent DetermineInputEvent() const;
float DetermineCurrentProgress() const;
class FName DetermineAnimatedIcon() const;
class FText DetermineActionText() const;
bool CanInteractThroughHitActors(const struct FHitResult& Hit) const;
bool CanInteract() const;

public:
static class UClass* StaticClass()
{
BP_STATIC_CLASS_IMPL("BP_Tower_Interact_Keycard_C")
}
static const class FName& StaticName()
{
STATIC_NAME_IMPL(L"BP_Tower_Interact_Keycard_C")
}
static class ABP_Tower_Interact_Keycard_C* GetDefaultObj()
{
return GetDefaultObjImpl<ABP_Tower_Interact_Keycard_C>();
}
};
DUMPER7_ASSERTS_ABP_Tower_Interact_Keycard_C;

}`

<img width="1200" height="675" alt="image" src="https://github.com/user-attachments/assets/5ee1c52c-3983-44a6-a164-20d446f6248a" /> What this change will do, is if the user opts into it, 2 new functional keypresses will now be available. Pressing F4 marks all current UObjects in the array as EInternalObjectFlags::RootSet, which the garbage collector will skip over when it goes to run. This allows the user to load into a level with streamed Blueprint classes, leave, and then load another level, so that when the SDK is generated, it will be complete at least for each level required. I tried initially implementing a way to invoke GetAllAsssets then invoking LoadObject, but this was wildly unstable and unpredictable, as the level-specific BP code expected pointers to be passed into it during its load call that had to resolve to the type it was expected, or else it would crash. Tested against Ready or Not engine build 5.3.2. <img width="979" height="512" alt="image" src="https://github.com/user-attachments/assets/ab1fde3c-8276-4b4d-98e0-715d4521e026" /> <img width="674" height="63" alt="image" src="https://github.com/user-attachments/assets/7bb938bb-d314-40e6-a7ad-619476eb6dfb" /> <img width="521" height="41" alt="image" src="https://github.com/user-attachments/assets/1582793a-0e24-491b-b276-d4bf708f85d2" /> <img width="961" height="24" alt="image" src="https://github.com/user-attachments/assets/0013ebda-49ca-458a-a1f7-54272513bfa8" /> `#pragma once /* * SDK generated by Dumper-7 * * https://github.com/Encryqed/Dumper-7 */ // Package: BP_Tower_Interact_Keycard #include "Basic.hpp" #include "Engine_structs.hpp" #include "Engine_classes.hpp" namespace SDK { // BlueprintGeneratedClass BP_Tower_Interact_Keycard.BP_Tower_Interact_Keycard_C // 0x0058 (0x02F8 - 0x02A0) class ABP_Tower_Interact_Keycard_C final : public AActor { public: struct FPointerToUberGraphFrame UberGraphFrame; // 0x02A0(0x0008)(ZeroConstructor, Transient, DuplicateTransient) class UStaticMeshComponent* SM_WallSwitch_02_a; // 0x02A8(0x0008)(BlueprintVisible, ZeroConstructor, InstancedReference, NonTransactional, NoDestructor, HasGetValueTypeHash) class UInteractableComponent* Interactable; // 0x02B0(0x0008)(BlueprintVisible, ZeroConstructor, InstancedReference, NonTransactional, NoDestructor, HasGetValueTypeHash) bool bIsOn; // 0x02B8(0x0001)(Edit, BlueprintVisible, Net, ZeroConstructor, DisableEditOnInstance, IsPlainOldData, NoDestructor, HasGetValueTypeHash) bool TriggerOnceOnly_; // 0x02B9(0x0001)(Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash) uint8 Pad_2BA[0x6]; // 0x02BA(0x0006)(Fixing Size After Last Property [ Dumper-7 ]) class FText PressedTextOn; // 0x02C0(0x0018)(Edit, BlueprintVisible) class FText PressedTextOff; // 0x02D8(0x0018)(Edit, BlueprintVisible) class FName DoorTag; // 0x02F0(0x0008)(Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash) public: void Server_Interact(class AReadyOrNotCharacter* InteractInstigator1, class UInteractableComponent* InteractableComponent1); void ReceiveBeginPlay(); void OnFocusLost(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); void OnFocusGain(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); void NewFunction(); void Multicast_Interacted(); void MeleeInteract(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); void Interact(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); void Fire(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); void ExecuteUbergraph_BP_Tower_Interact_Keycard(int32 EntryPoint); void EndInteract(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); void EndFire(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); void DoubleTapInteract(class AReadyOrNotCharacter* InteractInstigator, class UInteractableComponent* InInteractableComponent); class UInteractableComponent* GetInteractableComponent() const; float DetermineInteractionDistance() const; EInputEvent DetermineInputEvent() const; float DetermineCurrentProgress() const; class FName DetermineAnimatedIcon() const; class FText DetermineActionText() const; bool CanInteractThroughHitActors(const struct FHitResult& Hit) const; bool CanInteract() const; public: static class UClass* StaticClass() { BP_STATIC_CLASS_IMPL("BP_Tower_Interact_Keycard_C") } static const class FName& StaticName() { STATIC_NAME_IMPL(L"BP_Tower_Interact_Keycard_C") } static class ABP_Tower_Interact_Keycard_C* GetDefaultObj() { return GetDefaultObjImpl<ABP_Tower_Interact_Keycard_C>(); } }; DUMPER7_ASSERTS_ABP_Tower_Interact_Keycard_C; }`
This pull request has changes conflicting with the target branch.
  • Dumper/Settings.cpp
  • Dumper/main.cpp
  • README.md
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin Evasion3356/feature/load-all-classes:Evasion3356/feature/load-all-classes
git switch Evasion3356/feature/load-all-classes

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff Evasion3356/feature/load-all-classes
git switch Evasion3356/feature/load-all-classes
git rebase main
git switch main
git merge --ff-only Evasion3356/feature/load-all-classes
git switch Evasion3356/feature/load-all-classes
git rebase main
git switch main
git merge --no-ff Evasion3356/feature/load-all-classes
git switch main
git merge --squash Evasion3356/feature/load-all-classes
git switch main
git merge --ff-only Evasion3356/feature/load-all-classes
git switch main
git merge Evasion3356/feature/load-all-classes
git push origin main
Sign in to join this conversation.
No description provided.