diff --git a/cheat-library/cheat-library.vcxproj b/cheat-library/cheat-library.vcxproj index bf885e9..ab88e3d 100644 --- a/cheat-library/cheat-library.vcxproj +++ b/cheat-library/cheat-library.vcxproj @@ -15,6 +15,7 @@ + false @@ -116,6 +117,7 @@ + false diff --git a/cheat-library/cheat-library.vcxproj.filters b/cheat-library/cheat-library.vcxproj.filters index fb22fb8..5f3f132 100644 --- a/cheat-library/cheat-library.vcxproj.filters +++ b/cheat-library/cheat-library.vcxproj.filters @@ -234,6 +234,9 @@ Header Files + + Header Files + @@ -426,6 +429,9 @@ Source Files + + Source Files + diff --git a/cheat-library/src/appdata/il2cpp-functions.h b/cheat-library/src/appdata/il2cpp-functions.h index 93995be..a69ab18 100644 --- a/cheat-library/src/appdata/il2cpp-functions.h +++ b/cheat-library/src/appdata/il2cpp-functions.h @@ -178,6 +178,11 @@ DO_APP_FUNC(0x065508C0, void, Object_1_DestroyImmediate_1, (Object_1* obj, Metho DO_APP_FUNC(0x06550C00, Object_1*, Object_1_Instantiate_2, (Object_1* original, MethodInfo* method)); DO_APP_FUNC(0x041B0BB0, Object*, Object_1_Instantiate_5, (Object* original, MethodInfo* method)); DO_APP_FUNC(0x041B0BB0, GameObject*, Object_1_Instantiate_11, (GameObject* original, MethodInfo* method)); +DO_APP_FUNC(0x06555870, int32_t, Transform_get_childCount, (Transform* __this, MethodInfo* method)); +DO_APP_FUNC(0x0652EBC0, GameObject*, Component_1_get_gameObject, (Component_1* __this, MethodInfo* method)); +DO_APP_FUNC(0x06551030, String*, Object_1_get_name, (Object_1* __this, MethodInfo* method)); +DO_APP_FUNC(0x0665DA90, Material__Array*, Renderer_GetMaterialArray, (Renderer* __this, MethodInfo* method)); +DO_APP_FUNC(0x0652FB40, void, Material_set_mainTexture, (Material* __this, Texture* value, MethodInfo* method)); // Music game event diff --git a/cheat-library/src/appdata/il2cpp-types.h b/cheat-library/src/appdata/il2cpp-types.h index 3060455..0239083 100644 --- a/cheat-library/src/appdata/il2cpp-types.h +++ b/cheat-library/src/appdata/il2cpp-types.h @@ -11414,6 +11414,12 @@ namespace app { struct Object_1__Fields _; }; + struct Texture { + struct Texture__Class* klass; + MonitorData* monitor; + struct Texture__Fields fields; + }; + struct Texture2D__Fields { struct Texture__Fields _; }; @@ -11424,9 +11430,6 @@ namespace app { struct Texture2D__Fields fields; }; - - - struct Image_1__Fields { struct MaskableGraphic__Fields _; struct Sprite* m_CachedSprite; @@ -11914,6 +11917,24 @@ namespace app { MonitorData* monitor; }; + struct Renderer__Fields { + struct Component_1__Fields _; + }; + + struct Renderer { + struct Renderer__Class* klass; + MonitorData* monitor; + struct Renderer__Fields fields; + }; + + struct Material__Array { + struct Material__Array__Class* klass; + MonitorData* monitor; + Il2CppArrayBounds* bounds; + il2cpp_array_size_t max_length; + struct Material* vector[32]; + }; + #if !defined(_GHIDRA_) && !defined(_IDA_) } #endif diff --git a/cheat-library/src/user/cheat/cheat.cpp b/cheat-library/src/user/cheat/cheat.cpp index 3aaa9f8..e08d1f1 100644 --- a/cheat-library/src/user/cheat/cheat.cpp +++ b/cheat-library/src/user/cheat/cheat.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include "GenshinCM.h" @@ -109,7 +110,8 @@ namespace cheat FEAT_INST(PaimonFollow), FEAT_INST(HideUI), FEAT_INST(Browser), - FEAT_INST(EnablePeaking) + FEAT_INST(EnablePeaking), + FEAT_INST(TextureChanger), }); #undef FEAT_INST diff --git a/cheat-library/src/user/cheat/visuals/TextureChanger.cpp b/cheat-library/src/user/cheat/visuals/TextureChanger.cpp new file mode 100644 index 0000000..36f1c15 --- /dev/null +++ b/cheat-library/src/user/cheat/visuals/TextureChanger.cpp @@ -0,0 +1,128 @@ +#include "pch-il2cpp.h" +#include "TextureChanger.h" + +#include +#include +#include +#include + +namespace cheat::feature +{ + namespace GameObject { + app::GameObject* AvatarRoot = nullptr; + } + + TextureChanger::TextureChanger() : Feature(), + NF(f_Enabled, "Texture Changer", "Visuals::TextureChanger", false), + NF(f_HeadPath, "Head", "Visuals::TextureChanger", false), + NF(f_BodyPath, "Body", "Visuals::TextureChanger", false), + NF(f_DressPath, "Dress", "Visuals::TextureChanger", false), + toBeUpdate(), nextUpdate(0) + { + events::GameUpdateEvent += MY_METHOD_HANDLER(TextureChanger::OnGameUpdate); + } + + const FeatureGUIInfo& TextureChanger::GetGUIInfo() const + { + static const FeatureGUIInfo info{ "TextureChanger", "Visuals", true }; + return info; + } + + void TextureChanger::DrawMain() + { + ConfigWidget(f_Enabled, "Texture Changer."); + ImGui::Text("Active Hero: %s", ActiveHero.c_str()); + + ConfigWidget(f_HeadPath, "Head Texture.\n" \ + "Example path: C:\\Head.png"); + + ConfigWidget(f_BodyPath, "Body Texture.\n" \ + "Example path: C:\\Body.png"); + + ConfigWidget(f_DressPath, "Dress Texture.\n" \ + "Example path: C:\\Dress.png"); + + if (ImGui::Button("Apply")) + ApplyTexture = true; + } + + bool TextureChanger::NeedStatusDraw() const + { + return f_Enabled; + } + + void TextureChanger::DrawStatus() + { + ImGui::Text("Texture Changer"); + } + + TextureChanger& TextureChanger::GetInstance() + { + static TextureChanger instance; + return instance; + } + + void TextureChanger::OnGameUpdate() + { + if (!f_Enabled) + return; + + auto currentTime = util::GetCurrentTimeMillisec(); + if (currentTime < nextUpdate) + return; + + if (ApplyTexture) + { + GameObject::AvatarRoot = app::GameObject_Find(string_to_il2cppi("/EntityRoot/AvatarRoot"), nullptr); + + if (GameObject::AvatarRoot != nullptr) + { + auto Transform = app::GameObject_GetComponentByName(GameObject::AvatarRoot, string_to_il2cppi("Transform"), nullptr); + auto HeroCount = app::Transform_get_childCount(reinterpret_cast(Transform), nullptr); + + for (int i = 0; i <= HeroCount - 1; i++) + { + auto HeroComponent = app::Transform_GetChild(reinterpret_cast(Transform), i, nullptr); + auto HeroGameObject = app::Component_1_get_gameObject(reinterpret_cast(HeroComponent), nullptr); + auto isActiveHero = app::GameObject_get_active(HeroGameObject, nullptr); + + if (isActiveHero) + { + auto GameObjectName = app::Object_1_get_name(reinterpret_cast(HeroGameObject), nullptr); + ActiveHero = il2cppi_to_string(GameObjectName); + auto OffsetDummy = app::GameObject_Find(string_to_il2cppi("/EntityRoot/AvatarRoot/" + il2cppi_to_string(GameObjectName) + "/OffsetDummy"), nullptr); + auto TransformOffsetDummy = app::GameObject_GetComponentByName(OffsetDummy, string_to_il2cppi("Transform"), nullptr); + auto TransformChildOffsetDummy = app::Transform_GetChild(reinterpret_cast(TransformOffsetDummy), 0, nullptr); + auto OffsetGameObject = app::Component_1_get_gameObject(reinterpret_cast(TransformChildOffsetDummy), nullptr); + auto OffsetGameObjectName = app::Object_1_get_name(reinterpret_cast(OffsetGameObject), nullptr); + auto GameObjectBody = app::GameObject_Find(string_to_il2cppi("/EntityRoot/AvatarRoot/" + il2cppi_to_string(GameObjectName) + "/OffsetDummy/" + il2cppi_to_string(OffsetGameObjectName) + "/Body"), nullptr); + auto SkinnedMeshRenderer = app::GameObject_GetComponentByName(reinterpret_cast(GameObjectBody), string_to_il2cppi("SkinnedMeshRenderer"), nullptr); + auto Material = app::Renderer_GetMaterialArray(reinterpret_cast(SkinnedMeshRenderer), nullptr); + // 0 - Hair, 1 - Body, 2 - Dress + if (f_HeadPath && CheckFile(f_HeadPath)) { + auto HeadTexture = app::NativeGallery_LoadImageAtPath(string_to_il2cppi(f_HeadPath), 100, false, false, false, nullptr); + app::Material_set_mainTexture(Material->vector[0], reinterpret_cast(HeadTexture), nullptr); + } + if (f_BodyPath && CheckFile(f_BodyPath)) { + auto BodyTexture = app::NativeGallery_LoadImageAtPath(string_to_il2cppi(f_BodyPath), 100, false, false, false, nullptr); + app::Material_set_mainTexture(Material->vector[1], reinterpret_cast(BodyTexture), nullptr); + } + if (f_DressPath && CheckFile(f_DressPath)) { + auto DressTexture = app::NativeGallery_LoadImageAtPath(string_to_il2cppi(f_DressPath), 100, false, false, false, nullptr); + + if (Material->vector[2] != nullptr) + app::Material_set_mainTexture(Material->vector[2], reinterpret_cast(DressTexture), nullptr); + } + ApplyTexture = false; + } + } + } + } + nextUpdate = currentTime + (int)f_DelayUpdate; + } + + bool TextureChanger::CheckFile(const std::string& Filename) { + struct stat buffer; + return (stat(Filename.c_str(), &buffer) == 0); + } +} \ No newline at end of file diff --git a/cheat-library/src/user/cheat/visuals/TextureChanger.h b/cheat-library/src/user/cheat/visuals/TextureChanger.h new file mode 100644 index 0000000..934d355 --- /dev/null +++ b/cheat-library/src/user/cheat/visuals/TextureChanger.h @@ -0,0 +1,33 @@ +#pragma once +#include +#include +#include + +namespace cheat::feature +{ + class TextureChanger : public Feature + { + public: + config::Field> f_Enabled; + config::Field> f_HeadPath; + config::Field> f_BodyPath; + config::Field> f_DressPath; + std::string ActiveHero = "NONE"; + bool ApplyTexture; + + static TextureChanger& GetInstance(); + const FeatureGUIInfo& GetGUIInfo() const override; + void DrawMain() override; + bool NeedStatusDraw() const override; + void DrawStatus() override; + bool CheckFile(const std::string& name); + private: + SafeQueue toBeUpdate; + SafeValue nextUpdate; + int f_DelayUpdate = 15; + + void OnGameUpdate(); + TextureChanger(); + + }; +} \ No newline at end of file