Skip to content

Commit

Permalink
SDK: Various improvements to parameter instantiation
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Oct 27, 2023
1 parent 43393ac commit 2ed20da
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 39 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ list(APPEND sdk_SOURCES
"shared/sdk/Globals.cpp"
"shared/sdk/ScriptMatrix.cpp"
"shared/sdk/ScriptRotator.cpp"
"shared/sdk/ScriptTransform.cpp"
"shared/sdk/ScriptVector.cpp"
"shared/sdk/Slate.cpp"
"shared/sdk/StereoStuff.cpp"
Expand Down Expand Up @@ -372,6 +373,7 @@ list(APPEND sdk_SOURCES
"shared/sdk/RHICommandList.hpp"
"shared/sdk/ScriptMatrix.hpp"
"shared/sdk/ScriptRotator.hpp"
"shared/sdk/ScriptTransform.hpp"
"shared/sdk/ScriptVector.hpp"
"shared/sdk/Slate.hpp"
"shared/sdk/StereoStuff.hpp"
Expand Down
5 changes: 4 additions & 1 deletion shared/sdk/AActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,14 +299,17 @@ void AActor::finish_add_component_ex(sdk::UObject* new_comp) {
}

// For older UE.
if (new_comp->get_class()->is_a(sdk::USceneComponent::static_class())) {
const auto is_sc = new_comp->get_class()->is_a(sdk::USceneComponent::static_class());
if (is_sc) {
auto sc = (sdk::USceneComponent*)new_comp;

if (get_root_component() == nullptr) {
set_root_component(sc);
} else {
sc->attach_to(get_root_component());
}

sc->set_local_transform({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f}, false, false);
}

((sdk::UActorComponent*)new_comp)->register_component_with_world(this->get_world());
Expand Down
38 changes: 38 additions & 0 deletions shared/sdk/ScriptTransform.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "UObjectArray.hpp"
#include "FProperty.hpp"

#include "ScriptVector.hpp"
#include "ScriptTransform.hpp"

namespace sdk {
sdk::UScriptStruct* ScriptTransform::static_struct() {
static auto modern_class = sdk::find_uobject<UScriptStruct>(L"ScriptStruct /Script/CoreUObject.Transform");
static auto old_class = modern_class == nullptr ? sdk::find_uobject<UScriptStruct>(L"ScriptStruct /Script/CoreUObject.Object.Transform") : nullptr;

return modern_class != nullptr ? modern_class : old_class;
}

std::vector<uint8_t> ScriptTransform::create_dynamic_struct(const glm::vec3& location, const glm::vec4& rotation, const glm::vec3& scale) {
static const bool is_ue5 = ScriptVector::static_struct()->get_struct_size() == sizeof(glm::vec<3, double>);

std::vector<uint8_t> out{};
out.insert(out.end(), static_struct()->get_struct_size(), 0);

// quaternion, vec3, vec3
static const auto quat_offset = static_struct()->find_property(L"Rotation")->get_offset();
static const auto loc_offset = static_struct()->find_property(L"Translation")->get_offset();
static const auto scale_offset = static_struct()->find_property(L"Scale3D")->get_offset();

if (is_ue5) {
*(glm::vec<4, double>*)(out.data() + quat_offset) = rotation;
*(glm::vec<3, double>*)(out.data() + loc_offset) = location;
*(glm::vec<3, double>*)(out.data() + scale_offset) = scale;
} else {
*(glm::vec4*)(out.data() + quat_offset) = rotation;
*(glm::vec3*)(out.data() + loc_offset) = location;
*(glm::vec3*)(out.data() + scale_offset) = scale;
}

return out;
}
}
17 changes: 17 additions & 0 deletions shared/sdk/ScriptTransform.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <vector>

#include "Math.hpp"
#include "UClass.hpp"

namespace sdk {
class ScriptTransform : public UObject {
public:
static UScriptStruct* static_struct();

static std::vector<uint8_t> create_dynamic_struct(const glm::vec3& location, const glm::vec4& rotation, const glm::vec3& scale);

protected:
};
}
84 changes: 51 additions & 33 deletions shared/sdk/UGameplayStatics.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "UObjectArray.hpp"

#include "ScriptVector.hpp"
#include "ScriptTransform.hpp"
#include "UFunction.hpp"
#include "FProperty.hpp"
#include "UGameplayStatics.hpp"

namespace sdk {
Expand Down Expand Up @@ -38,7 +41,7 @@ AActor* UGameplayStatics::begin_deferred_actor_spawn_from_class(UObject* world_c
const auto fvector = sdk::ScriptVector::static_struct();
const auto is_ue5 = fvector->get_struct_size() == sizeof(glm::vec<3, double>);

struct {
/*struct {
UObject* world_context{};
UClass* actor_class{};
struct {
Expand Down Expand Up @@ -84,7 +87,36 @@ AActor* UGameplayStatics::begin_deferred_actor_spawn_from_class(UObject* world_c
}
this->process_event(func, &params_ue4);
return params_ue4.result;
return params_ue4.result;*/

std::vector<uint8_t> params{};
params.insert(params.end(), (uint8_t*)&world_context, (uint8_t*)&world_context + sizeof(void*));
params.insert(params.end(), (uint8_t*)&actor_class, (uint8_t*)&actor_class + sizeof(void*));

static const auto spawn_transform_offset = func->find_property(L"SpawnTransform")->get_offset();

// Pad until we reach the spawn transform
if (params.size() < spawn_transform_offset) {
params.insert(params.end(), spawn_transform_offset - params.size(), 0);
}

const auto transform = sdk::ScriptTransform::create_dynamic_struct(location, glm::vec4{0.0f, 0.0f, 0.0f, 1.0f}, glm::vec3{1.0f, 1.0f, 1.0f});
params.insert(params.end(), transform.begin(), transform.end());
params.insert(params.end(), (uint8_t*)&collision_method, (uint8_t*)&collision_method + sizeof(uint32_t));

// Align up to 8 bytes if necessary
if (params.size() % sizeof(void*) != 0) {
params.insert(params.end(), sizeof(void*) - (params.size() % sizeof(void*)), 0);
}

params.insert(params.end(), (uint8_t*)&owner, (uint8_t*)&owner + sizeof(void*));

const auto result_offset = params.size();
params.insert(params.end(), sizeof(void*), 0);

this->process_event(func, params.data());

return *(AActor**)(params.data() + result_offset);
}

AActor* UGameplayStatics::finish_spawning_actor(AActor* actor, const glm::vec3& location) {
Expand All @@ -97,43 +129,29 @@ AActor* UGameplayStatics::finish_spawning_actor(AActor* actor, const glm::vec3&
const auto fvector = sdk::ScriptVector::static_struct();
const auto is_ue5 = fvector->get_struct_size() == sizeof(glm::vec<3, double>);

struct {
AActor* actor{};
char pad[0x8];
struct {
double rotation[4]{0.0, 0.0, 0.0, 1.0};
glm::vec<4, double> translation{};
glm::vec<4, double> scale{1.0, 1.0, 1.0, 1.0};
} transform;
AActor* result{};
} params_ue5{};
std::vector<uint8_t> params{};
params.insert(params.end(), (uint8_t*)&actor, (uint8_t*)&actor + sizeof(void*));

struct {
AActor* actor{};
char pad[0x8];
struct {
float rotation[4]{0.0f, 0.0f, 0.0f, 1.0f};
glm::vec4 translation{};
glm::vec4 scale{1.0f, 1.0f, 1.0f, 1.0f};
} transform;
AActor* result{};
} params_ue4{};
static const auto spawn_transform_offset = func->find_property(L"SpawnTransform")->get_offset();

if (is_ue5) {
params_ue5.actor = actor;
params_ue5.transform.translation = glm::vec<4, double>{location, 1.0};
} else {
params_ue4.actor = actor;
params_ue4.transform.translation = glm::vec4{location, 1.0};
// Pad until we reach the spawn transform
if (params.size() < spawn_transform_offset) {
params.insert(params.end(), spawn_transform_offset - params.size(), 0);
}

if (is_ue5) {
this->process_event(func, &params_ue5);
return params_ue5.result;
const auto transform = sdk::ScriptTransform::create_dynamic_struct(location, glm::vec4{0.0f, 0.0f, 0.0f, 1.0f}, glm::vec3{1.0f, 1.0f, 1.0f});
params.insert(params.end(), transform.begin(), transform.end());

// Align up to 8 bytes if necessary
if (params.size() % sizeof(void*) != 0) {
params.insert(params.end(), sizeof(void*) - (params.size() % sizeof(void*)), 0);
}

const auto result_offset = params.size();
params.insert(params.end(), sizeof(void*), 0);

this->process_event(func, &params_ue4);
return params_ue4.result;
this->process_event(func, params.data());
return *(AActor**)(params.data() + result_offset);
}

UObject* UGameplayStatics::spawn_object(UClass* uclass, UObject* outer) {
Expand Down
65 changes: 61 additions & 4 deletions shared/sdk/USceneComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "ScriptVector.hpp"
#include "ScriptRotator.hpp"
#include "FProperty.hpp"
#include "ScriptTransform.hpp"
#include "UFunction.hpp"

#include "USceneComponent.hpp"

Expand Down Expand Up @@ -183,6 +185,41 @@ void USceneComponent::add_local_rotation(const glm::vec3& rotation, bool sweep,
this->process_event(fn, params.data());
}

void USceneComponent::set_local_transform(const glm::vec3& location, const glm::vec4& rotation, const glm::vec3& scale, bool sweep, bool teleport) {
static auto fn = static_class()->find_function(L"K2_SetRelativeTransform");
static const auto fhitresult = sdk::find_uobject<UScriptStruct>(L"ScriptStruct /Script/Engine.HitResult");

if (fn == nullptr) {
return;
}

static const auto fvector = sdk::ScriptVector::static_struct();
static const auto is_ue5 = fvector->get_struct_size() == sizeof(glm::vec<3, double>);

// Need to dynamically allocate the params because of unknown FVector size
std::vector<uint8_t> params{};

const auto transform_struct = sdk::ScriptTransform::create_dynamic_struct(location, rotation, scale);
params.insert(params.end(), transform_struct.begin(), transform_struct.end());

// add a bool
params.insert(params.end(), (uint8_t*)&sweep, (uint8_t*)&sweep + sizeof(bool));

// Pad until the offset of SweepHitResult
static const auto sweep_hit_result_offset = fn->find_property(L"SweepHitResult")->get_offset();
if (params.size() != sweep_hit_result_offset) {
params.insert(params.end(), sweep_hit_result_offset - params.size(), 0);
}

// add a FHitResult
params.insert(params.end(), fhitresult->get_struct_size(), 0);

// add a bool
params.insert(params.end(), (uint8_t*)&teleport, (uint8_t*)&teleport + sizeof(bool));

this->process_event(fn, params.data());
}

glm::vec3 USceneComponent::get_world_location() {
static const auto func = static_class()->find_function(L"K2_GetComponentLocation");
const auto fvector = sdk::ScriptVector::static_struct();
Expand Down Expand Up @@ -238,7 +275,7 @@ bool USceneComponent::attach_to(USceneComponent* parent, const std::wstring& soc
return false;
}

struct {
/*struct {
USceneComponent* parent{};
FName socket_name{L"None"};
uint8_t attach_type{};
Expand All @@ -249,11 +286,31 @@ bool USceneComponent::attach_to(USceneComponent* parent, const std::wstring& soc
params.parent = parent;
params.socket_name = FName{socket_name};
params.attach_type = attach_type;
params.weld = weld;
params.weld = weld;*/

this->process_event(func, &params);
// Dynamically create params
std::vector<uint8_t> params{};
static const auto struct_size = func->find_property(L"bWeldSimulatedBodies")->get_offset() + (sizeof(bool) * 2);
params.insert(params.end(), struct_size, 0);

static const auto parent_offset = func->find_property(L"InParent")->get_offset();
*(USceneComponent**)(params.data() + parent_offset) = parent;

static const auto socket_name_offset = func->find_property(L"InSocketName")->get_offset();
*(FName*)(params.data() + socket_name_offset) = FName{socket_name};

static const auto attach_type_offset = func->find_property(L"AttachType")->get_offset();
*(uint8_t*)(params.data() + attach_type_offset) = attach_type;

static const auto weld_offset = func->find_property(L"bWeldSimulatedBodies")->get_offset();
*(bool*)(params.data() + weld_offset) = weld;

// add a bool
params.insert(params.end(), sizeof(bool), 0);

this->process_event(func, params.data());

return params.result;
return (bool)params.back();
}

void USceneComponent::set_hidden_in_game(bool hidden, bool propagate) {
Expand Down
3 changes: 2 additions & 1 deletion shared/sdk/USceneComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ class USceneComponent : public UActorComponent {
void set_world_location(const glm::vec3& location, bool sweep = false, bool teleport = false);
void add_world_offset(const glm::vec3& offset, bool sweep = false, bool teleport = false);
void add_local_rotation(const glm::vec3& rotation, bool sweep = false, bool teleport = false);
void set_local_transform(const glm::vec3& location, const glm::vec4& rotation, const glm::vec3& scale, bool sweep = false, bool teleport = false);

glm::vec3 get_world_location();
glm::vec3 get_world_rotation();

bool attach_to(USceneComponent* parent, const std::wstring& socket_name = L"None", uint8_t attach_type = 0, bool weld = false);
bool attach_to(USceneComponent* parent, const std::wstring& socket_name = L"None", uint8_t attach_type = 0, bool weld = true);
void set_hidden_in_game(bool hidden, bool propagate_to_children = true);
};
}

0 comments on commit 2ed20da

Please sign in to comment.