diff --git a/DivaGL.sln b/DivaGL.sln
index 127720f..89f0913 100644
--- a/DivaGL.sln
+++ b/DivaGL.sln
@@ -17,6 +17,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AFTModsShared", "src\AFTMod
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpriteDrawLimit", "src\SpriteDrawLimit\SpriteDrawLimit.vcxproj", "{87D41F20-B8C6-43BB-A89D-3A1979928613}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RobTexAnim", "src\RobTexAnim\RobTexAnim.vcxproj", "{761037C2-9F05-4EB0-B28A-D666981F2725}"
+ ProjectSection(ProjectDependencies) = postProject
+ {65707AD3-568A-4FE9-A75E-BDBF3D5EFC88} = {65707AD3-568A-4FE9-A75E-BDBF3D5EFC88}
+ {BCF448EA-DCFF-49AF-97FF-361204C69358} = {BCF448EA-DCFF-49AF-97FF-361204C69358}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -39,6 +45,10 @@ Global
{87D41F20-B8C6-43BB-A89D-3A1979928613}.Debug|x64.Build.0 = Debug|x64
{87D41F20-B8C6-43BB-A89D-3A1979928613}.Release|x64.ActiveCfg = Release|x64
{87D41F20-B8C6-43BB-A89D-3A1979928613}.Release|x64.Build.0 = Release|x64
+ {761037C2-9F05-4EB0-B28A-D666981F2725}.Debug|x64.ActiveCfg = Debug|x64
+ {761037C2-9F05-4EB0-B28A-D666981F2725}.Debug|x64.Build.0 = Debug|x64
+ {761037C2-9F05-4EB0-B28A-D666981F2725}.Release|x64.ActiveCfg = Release|x64
+ {761037C2-9F05-4EB0-B28A-D666981F2725}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/RobTexAnim/RobTexAnim.rc b/src/RobTexAnim/RobTexAnim.rc
new file mode 100644
index 0000000..3513335
--- /dev/null
+++ b/src/RobTexAnim/RobTexAnim.rc
@@ -0,0 +1,37 @@
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+#include "winres.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,1,0,0
+ PRODUCTVERSION 0,1,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x0L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000904b0"
+ BEGIN
+ VALUE "FileDescription", "Rob Tex Anim plugin for PDAFT 7.10"
+ VALUE "FileVersion", "0.1.0.0"
+ VALUE "InternalName", "RobTexAnim"
+ VALUE "LegalCopyright", "korenkonder (C) 2025"
+ VALUE "OriginalFilename", "RobTexAnim.dll"
+ VALUE "ProductName", "RobTexAnim"
+ VALUE "ProductVersion", "0.1.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x9, 1200
+ END
+END
diff --git a/src/RobTexAnim/RobTexAnim.vcxproj b/src/RobTexAnim/RobTexAnim.vcxproj
new file mode 100644
index 0000000..31ac2b4
--- /dev/null
+++ b/src/RobTexAnim/RobTexAnim.vcxproj
@@ -0,0 +1,135 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ {761037c2-9f05-4eb0-b28a-d666981f2725}
+ Win32Proj
+ 10.0
+
+
+
+ DynamicLibrary
+ false
+ v142
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v142
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+ false
+ RobTexAnim
+ $(SolutionDir)bin\
+ $(SolutionDir)obj\debug\RobTexAnim\
+ .dva
+
+
+ false
+ RobTexAnim
+ $(SolutionDir)bin\
+ $(SolutionDir)obj\release\RobTexAnim\
+ .dva
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ WIN32;DEBUG;%(PreprocessorDefinitions)
+ $(SolutionDir)extern\src
+ true
+ ProgramDatabase
+ false
+ OnlyExplicitInline
+ FastCall
+ true
+ CompileAsCpp
+ $(IntDir)/%(RelativeDir)
+ MultiThreaded
+ 26812
+ false
+ true
+
+
+ MachineX64
+ DebugFull
+ Windows
+ $(SolutionDir)extern\lib;$(SolutionDir)lib\debugopt\
+ detours.lib;syelog.lib;libdeflatestatic.lib;AFTModsShared.lib;KKdLib.lib;%(AdditionalDependencies)
+ /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions)
+ false
+
+
+
+
+ NotUsing
+ Level3
+ MaxSpeed
+ WIN32;%(PreprocessorDefinitions)
+ $(SolutionDir)extern\src
+ true
+ false
+ ProgramDatabase
+ OnlyExplicitInline
+ true
+ FastCall
+ CompileAsCpp
+
+
+ $(IntDir)/%(RelativeDir)
+ Speed
+
+
+ false
+ MultiThreaded
+ 26812
+ true
+
+
+ MachineX64
+ true
+ Windows
+ $(SolutionDir)extern\lib;$(SolutionDir)lib\release\
+ detours.lib;syelog.lib;libdeflatestatic.lib;AFTModsShared.lib;KKdLib.lib;%(AdditionalDependencies)
+ true
+ /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions)
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/RobTexAnim/RobTexAnim.vcxproj.user b/src/RobTexAnim/RobTexAnim.vcxproj.user
new file mode 100644
index 0000000..429333d
--- /dev/null
+++ b/src/RobTexAnim/RobTexAnim.vcxproj.user
@@ -0,0 +1,6 @@
+
+
+
+ true
+
+
\ No newline at end of file
diff --git a/src/RobTexAnim/dllmain.cpp b/src/RobTexAnim/dllmain.cpp
new file mode 100644
index 0000000..9352320
--- /dev/null
+++ b/src/RobTexAnim/dllmain.cpp
@@ -0,0 +1,34 @@
+/*
+ by korenkonder
+ GitHub/GitLab: korenkonder
+*/
+
+#include "rob/rob.hpp"
+#include
+#include
+#define WIN32_LEAN_AND_MEAN
+#include
+
+bool APIENTRY DllMain(HMODULE handle, DWORD ul_reason_for_call, LPVOID lpReserved) {
+ switch (ul_reason_for_call) {
+ case DLL_PROCESS_ATTACH:
+ printf("[Rob Tex Anim] Current version - v0.1.0.0\n");
+ printf("[Rob Tex Anim] Attach\n");
+ printf("[Rob Tex Anim] Patching memory\n");
+ rob_patch();
+ break;
+ }
+ return true;
+}
+
+extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void) {
+ return L"Rob Tex Anim";
+}
+
+extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void) {
+ return L"Rob Tex Anim Plugin by korenkonder";
+}
+
+extern "C" __declspec(dllexport) LPCWSTR GetBuildDate(void) {
+ return L"v0.1.0.0";
+}
diff --git a/src/RobTexAnim/resource.h b/src/RobTexAnim/resource.h
new file mode 100644
index 0000000..480b823
--- /dev/null
+++ b/src/RobTexAnim/resource.h
@@ -0,0 +1,8 @@
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/RobTexAnim/rob/rob.cpp b/src/RobTexAnim/rob/rob.cpp
new file mode 100644
index 0000000..a5a422f
--- /dev/null
+++ b/src/RobTexAnim/rob/rob.cpp
@@ -0,0 +1,193 @@
+/*
+ by korenkonder
+ GitHub/GitLab: korenkonder
+*/
+
+#include "rob.hpp"
+#include "../../AFTModsShared/auth_3d.hpp"
+#include
+
+#define TEXTURE_PATTERN_COUNT 24
+#define TEXTURE_TRANSFORM_COUNT 24
+
+static void(FASTCALL* item_table_handler_array_get_item_objset)(::chara_index chara_index,
+ int32_t item_no, prj::list*& objset)
+ = (void(FASTCALL*)(::chara_index chara_index,
+ int32_t item_no, prj::list*& objset))0x000000014052C270;
+
+HOOK(void, FASTCALL, TaskRobLoad__UnloadCharaItem, 0x0000000140525560,
+ ::chara_index chara_index, int32_t item_no) {
+ if (!item_no)
+ return;
+
+ prj::list* item_objset = 0;
+ item_table_handler_array_get_item_objset(chara_index, item_no, item_objset);
+ if (!item_objset)
+ return;
+
+ for (const int32_t& i : *item_objset)
+ if (i != -1) {
+ objset_info_storage_unload_set(i);
+ auth_3d_data_unload_category(objset_info_storage_get_set_name(i));
+ }
+}
+
+HOOK(void, FASTCALL, TaskRobLoad__LoadCharaItem, 0x000000014052B0F0,
+ ::chara_index chara_index, int32_t item_no) {
+ if (!item_no)
+ return;
+
+ prj::list* item_objset = 0;
+ item_table_handler_array_get_item_objset(chara_index, item_no, item_objset);
+ if (!item_objset)
+ return;
+
+ for (const int32_t& i : *item_objset)
+ if (i != -1) {
+ objset_info_storage_load_set(i);
+ auth_3d_data_load_category(objset_info_storage_get_set_name(i));
+ }
+}
+
+HOOK(bool, FASTCALL, TaskRobLoad__LoadCharaItemCheckNotRead, 0x000000014052D4C0,
+ ::chara_index chara_index, int32_t item_no) {
+ if (!item_no)
+ return false;
+
+ prj::list* item_objset = 0;
+ item_table_handler_array_get_item_objset(chara_index, item_no, item_objset);
+ if (!item_objset)
+ return true;
+
+ for (const int32_t& i : *item_objset)
+ if (i != -1 && objset_info_storage_load_obj_set_check_not_read(i)) {
+ if (auth_3d_data_check_category_loaded(objset_info_storage_get_set_name(i)))
+ return true;
+ }
+ return false;
+}
+
+HOOK(rob_chara_item_equip_object*, FASTCALL, rob_chara_item_equip_object__rob_chara_item_equip_object,
+ 0x00000001405ED890, rob_chara_item_equip_object* This) {
+ This->auth_obj_index = -1;
+ This->auth_3d_id = -1;
+ return originalrob_chara_item_equip_object__rob_chara_item_equip_object(This);
+}
+
+HOOK(void, FASTCALL, rob_chara_item_equip_object_ctrl, 0x00000001405F2310, rob_chara_item_equip_object* itm_eq_obj) {
+ originalrob_chara_item_equip_object_ctrl(itm_eq_obj);
+
+ if (itm_eq_obj->auth_3d_id != -1 && itm_eq_obj->auth_obj_index == -1
+ && (*(auth_3d_id*)&itm_eq_obj->auth_3d_id).check_loaded()) {
+ const char* obj_name = object_database_get_obj_name(itm_eq_obj->obj_info);
+
+ auth_3d* auth = (*(auth_3d_id*)&itm_eq_obj->auth_3d_id).get_auth_3d();
+ for (auth_3d_object& i : auth->object)
+ if (i.uid_name.compare(obj_name)) {
+ itm_eq_obj->auth_obj_index = (int32_t)(&i - auth->object.data());
+ break;
+ }
+ }
+}
+
+HOOK(void, FASTCALL, rob_chara_item_equip_object_disp, 0x00000001405F2700, rob_chara_item_equip_object* itm_eq_obj) {
+ if (itm_eq_obj->obj_info.is_null())
+ return;
+
+ char buf[0x80];
+ int32_t tex_pat_count = 0;
+ texture_pattern_struct tex_pat[TEXTURE_PATTERN_COUNT];
+
+ int32_t tex_trans_count = 0;
+ texture_transform_struct tex_trans[TEXTURE_TRANSFORM_COUNT];
+
+ static void(FASTCALL * disp_manager_set_texture_transform)(int32_t count, texture_transform_struct * data)
+ = (void(FASTCALL*)(int32_t count, texture_transform_struct * data))0x000000014043A600;
+
+ auth_3d_id& id = *(auth_3d_id*)&itm_eq_obj->auth_3d_id;
+ if (id.check_not_empty()) {
+ auth_3d* auth = id.get_auth_3d();
+ if (itm_eq_obj->auth_obj_index >= 0 && itm_eq_obj->auth_obj_index < auth->object.size()) {
+ auth_3d_object* o = &auth->object.data()[itm_eq_obj->auth_obj_index];
+
+ for (auth_3d_object_texture_pattern& i : o->texture_pattern) {
+ if (!i.pattern.curve || i.name.size() <= 3)
+ continue;
+ else if (tex_pat_count >= TEXTURE_PATTERN_COUNT)
+ break;
+
+ sprintf_s(buf, sizeof(buf), "%.*s%03d",
+ (int32_t)(i.name.size() - 3), i.name.c_str(), (int32_t)prj::roundf(i.pattern.value));
+
+ tex_pat[tex_pat_count].src = texture_id(0x00, i.texture_id);
+ tex_pat[tex_pat_count].dst = texture_id(0x00, texture_info_get_id(buf));
+ tex_pat_count++;
+ }
+
+ for (auth_3d_object_texture_transform& i : o->texture_transform) {
+ if (tex_trans_count >= TEXTURE_TRANSFORM_COUNT || i.texture_id == -1
+ || !texture_manager_get_texture(i.texture_id))
+ continue;
+
+ tex_trans[tex_trans_count].id = i.texture_id;
+ tex_trans[tex_trans_count].mat = i.mat;
+ tex_trans_count++;
+ }
+
+ if (tex_trans_count > 0)
+ disp_manager_set_texture_transform(tex_trans_count, tex_trans);
+ }
+ }
+
+ prj::vector& itm_tex_pat = itm_eq_obj->texture_pattern;
+
+ if (tex_pat_count > 0)
+ itm_tex_pat.insert(itm_tex_pat.end(), tex_pat, tex_pat + tex_pat_count);
+
+ originalrob_chara_item_equip_object_disp(itm_eq_obj);
+
+ if (tex_pat_count > 0)
+ itm_tex_pat.resize(itm_tex_pat.size() - tex_pat_count);
+
+ if (tex_trans_count > 0)
+ disp_manager_set_texture_transform(0, 0);
+}
+
+HOOK(bool, FASTCALL, rob_chara_item_equip_object__init_members, 0x00000001405F36F0,
+ rob_chara_item_equip_object* This, size_t index) {
+ This->auth_obj_index = -1;
+ (*(auth_3d_id*)&This->auth_3d_id).unload();
+ return originalrob_chara_item_equip_object__init_members(This, index);
+}
+
+HOOK(bool, FASTCALL, rob_chara_item_equip_object_load_object_info_ex_data, 0x00000001405F6E30,
+ rob_chara_item_equip_object* itm_eq_obj, uint32_t obj_info, bone_node* bone_nodes, bool osage_reset) {
+ auth_3d_id id(objset_info_storage_get_set_name((*(object_info*)&obj_info).set_id));
+ if (id.check_not_empty()) {
+ id.read_file();
+ id.set_enable(true);
+ id.set_repeat(true);
+ id.set_paused(false);
+ id.set_visibility(false);
+
+ itm_eq_obj->auth_obj_index = -1;
+ (*(auth_3d_id*)&itm_eq_obj->auth_3d_id) = id;
+ }
+ else {
+ itm_eq_obj->auth_obj_index = -1;
+ itm_eq_obj->auth_3d_id = -1;
+ }
+
+ return originalrob_chara_item_equip_object_load_object_info_ex_data(itm_eq_obj, obj_info, bone_nodes, osage_reset);
+}
+
+void rob_patch() {
+ INSTALL_HOOK(TaskRobLoad__UnloadCharaItem);
+ INSTALL_HOOK(TaskRobLoad__LoadCharaItem);
+ INSTALL_HOOK(TaskRobLoad__LoadCharaItemCheckNotRead);
+ INSTALL_HOOK(rob_chara_item_equip_object__rob_chara_item_equip_object);
+ INSTALL_HOOK(rob_chara_item_equip_object_ctrl);
+ INSTALL_HOOK(rob_chara_item_equip_object_disp);
+ INSTALL_HOOK(rob_chara_item_equip_object__init_members);
+ INSTALL_HOOK(rob_chara_item_equip_object_load_object_info_ex_data);
+}
diff --git a/src/RobTexAnim/rob/rob.hpp b/src/RobTexAnim/rob/rob.hpp
new file mode 100644
index 0000000..6a40451
--- /dev/null
+++ b/src/RobTexAnim/rob/rob.hpp
@@ -0,0 +1,10 @@
+/*
+ by korenkonder
+ GitHub/GitLab: korenkonder
+*/
+
+#pragma once
+
+#include "../../AFTModsShared/rob/rob.hpp"
+
+extern void rob_patch();