From 02fea4fcccf6d16beb8f959d4d2a452824f671b3 Mon Sep 17 00:00:00 2001 From: Sora <sora.x@hotmail.fr> Date: Wed, 21 Feb 2024 02:49:55 +0100 Subject: [PATCH] Add Multiplayer support --- .../SADXWeightedCharacters.vcxproj | 6 +- .../SADXWeightedCharacters.vcxproj.filters | 6 ++ SADXWeightedCharacters/mod.cpp | 84 +++++++---------- SADXWeightedCharacters/multiplayer.cpp | 93 +++++++++++++++++++ SADXWeightedCharacters/weights.h | 36 +++++++ 5 files changed, 174 insertions(+), 51 deletions(-) create mode 100644 SADXWeightedCharacters/multiplayer.cpp create mode 100644 SADXWeightedCharacters/weights.h diff --git a/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj b/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj index 809f8ca..4fb6648 100644 --- a/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj +++ b/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj @@ -15,7 +15,7 @@ <Keyword>Win32Proj</Keyword> <ProjectGuid>{31d0c5e0-0d00-45ce-a39d-915221d2fcbd}</ProjectGuid> <RootNamespace>SADXWeightedCharacters</RootNamespace> - <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion>7.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> @@ -45,9 +45,11 @@ <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)bin\</OutDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)bin\</OutDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> @@ -90,10 +92,12 @@ <ItemGroup> <ClInclude Include="framework.h" /> <ClInclude Include="pch.h" /> + <ClInclude Include="weights.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp" /> <ClCompile Include="mod.cpp" /> + <ClCompile Include="multiplayer.cpp" /> <ClCompile Include="pch.cpp"> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> diff --git a/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj.filters b/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj.filters index 337abe3..14ba221 100644 --- a/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj.filters +++ b/SADXWeightedCharacters/SADXWeightedCharacters.vcxproj.filters @@ -21,6 +21,9 @@ <ClInclude Include="pch.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="weights.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="dllmain.cpp"> @@ -32,5 +35,8 @@ <ClCompile Include="mod.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="multiplayer.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file diff --git a/SADXWeightedCharacters/mod.cpp b/SADXWeightedCharacters/mod.cpp index 785dcea..7a5248d 100644 --- a/SADXWeightedCharacters/mod.cpp +++ b/SADXWeightedCharacters/mod.cpp @@ -6,39 +6,13 @@ #include "UsercallFunctionHandler.h" #include <map> #include <vector> +#include "weights.h" using std::map; using std::vector; using std::string; +extern bool isMPMod; -struct ModelWeightInfo -{ - WeightInfo* weights; - int rightHandNode = -1; - int leftHandNode = -1; - int rightFootNode = -1; - int leftFootNode = -1; - int user0Node = -1; - int user1Node = -1; - int rightHandDir; - int leftHandDir; - int rightFootDir; - int leftFootDir; - int user0Dir; - int user1Dir; -}; - -struct CharInfo -{ - const char* modelPath; - const char* objectsArray; - int objectsLength; - const char* actionsArray; - int actionsLength; - const intptr_t* pointersArray; - int pointersLength; - map<NJS_OBJECT*, ModelWeightInfo> modelWeights; -}; const intptr_t sonicWeldPointers[] = { 0x49AB7E, @@ -211,6 +185,32 @@ void ProcessWeights(CharObj2* a3, NJS_OBJECT*& object, NJS_MOTION* motion, float } } +void __cdecl ProcessVertexWelds_Check_(EntityData1* a1, EntityData2* a2, CharObj2* a3) +{ + NJS_OBJECT* object; + NJS_MOTION* motion; + if (a3->AnimationThing.State == 2) + { + object = a3->AnimationThing.action->object; + motion = a3->AnimationThing.action->motion; + } + else + { + object = a3->AnimationThing.AnimData[(unsigned __int16)a3->AnimationThing.Index].Animation->object; + motion = a3->AnimationThing.AnimData[(unsigned __int16)a3->AnimationThing.Index].Animation->motion; + } + if (MetalSonicFlag) + { + if (object == SONIC_OBJECTS[0]) + object = SONIC_OBJECTS[68]; + else if (object == SONIC_OBJECTS[66]) + object = SONIC_OBJECTS[69]; + else if (object == SONIC_OBJECTS[67]) + object = SONIC_OBJECTS[70]; + } + ProcessWeights(a3, object, motion, a3->AnimationThing.Frame); +} + FunctionHook<void, EntityData1*, EntityData2*, CharObj2*> ProcessVertexWelds_h(ProcessVertexWelds); void __cdecl ProcessVertexWelds_Check(EntityData1* a1, EntityData2* a2, CharObj2* a3) { @@ -220,28 +220,10 @@ void __cdecl ProcessVertexWelds_Check(EntityData1* a1, EntityData2* a2, CharObj2 auto charinf = charInfos.find(id); if (charinf != charInfos.end() && charinf->second.modelWeights.size() > 0) { - NJS_OBJECT* object; - NJS_MOTION* motion; - if (a3->AnimationThing.State == 2) - { - object = a3->AnimationThing.action->object; - motion = a3->AnimationThing.action->motion; - } - else - { - object = a3->AnimationThing.AnimData[(unsigned __int16)a3->AnimationThing.Index].Animation->object; - motion = a3->AnimationThing.AnimData[(unsigned __int16)a3->AnimationThing.Index].Animation->motion; - } - if (MetalSonicFlag) - { - if (object == SONIC_OBJECTS[0]) - object = SONIC_OBJECTS[68]; - else if (object == SONIC_OBJECTS[66]) - object = SONIC_OBJECTS[69]; - else if (object == SONIC_OBJECTS[67]) - object = SONIC_OBJECTS[70]; - } - ProcessWeights(a3, object, motion, a3->AnimationThing.Frame); + if (isMPMod) //we don't want this whole function to run at all if MP is enabled, the code will run externally in the character display function for accurate render + return; + + ProcessVertexWelds_Check_(a1, a2, a3); } else ProcessVertexWelds_h.Original(a1, a2, a3); @@ -515,6 +497,8 @@ extern "C" mr_join_vertex_exec.Hook(mr_join_vertex_exec_Check); mr_join_vertex_end.Hook(mr_join_vertex_end_Check); ec_join_vertex_end.Hook(ec_join_vertex_end_Check); + + initWeightsMultiplayer(); } __declspec(dllexport) ModInfo SADXModInfo = { ModLoaderVer }; diff --git a/SADXWeightedCharacters/multiplayer.cpp b/SADXWeightedCharacters/multiplayer.cpp new file mode 100644 index 0000000..ef80a26 --- /dev/null +++ b/SADXWeightedCharacters/multiplayer.cpp @@ -0,0 +1,93 @@ +#include "pch.h" +#include "SADXModLoader.h" +#include "FunctionHook.h" +#include <map> +#include <vector> +#include "weights.h" + +using std::map; +using std::vector; +using std::string; + +//The multiplayer mod updates the render for each screen using the display function of the task. +//This makes the weights rendering wrong when they are running in a main function (such as ProcessWelds in Sonic_Main) +//We move the weights in the display of each character if the MP mod is detected so it will render properly + + +#define TaskHook FunctionHook<void, task*> + +TaskHook SonicDisplay_t(SonicDisplay); +TaskHook MilesDisplay_t(MilesDisplay); +TaskHook KnuxDisplay_t(KnucklesDisplay); +TaskHook AmyDisplay_t(AmyDisplay); +TaskHook BigDisplay_t(BigDisplay); + +bool isMPMod = false; + +void SetWeights(task* tp) +{ + if (!tp || !tp->twp) + return; + + char id = tp->twp->counter.b[1]; + + if (id == 0 && MetalSonicFlag) + id = Characters_MetalSonic; + + auto charinf = charInfos.find(id); + + if (charinf != charInfos.end() && charinf->second.modelWeights.size() > 0) + { + EntityData1* a1 = (EntityData1*)tp->twp; + EntityData2* a2 = (EntityData2*)tp->mwp; + if (a2) + { + CharObj2* a3 = a2->CharacterData; + ProcessVertexWelds_Check_(a1, a2, a3); + } + } +} + +void SonicDisplay_r(task* tp) +{ + SetWeights(tp); + SonicDisplay_t.Original(tp); +} + +void MilesDisplay_r(task* tp) +{ + SetWeights(tp); + MilesDisplay_t.Original(tp); +} + +void KnuxDisplay_r(task* tp) +{ + SetWeights(tp); + KnuxDisplay_t.Original(tp); +} + +void AmyDisplay_r(task* tp) +{ + SetWeights(tp); + AmyDisplay_t.Original(tp); +} + +void BigDisplay_r(task* tp) +{ + SetWeights(tp); + BigDisplay_t.Original(tp); +} + +void initWeightsMultiplayer() +{ + isMPMod = GetModuleHandle(L"sadx-multiplayer"); + + if (isMPMod) + { + SonicDisplay_t.Hook(SonicDisplay_r); + MilesDisplay_t.Hook(MilesDisplay_r); + KnuxDisplay_t.Hook(KnuxDisplay_r); + AmyDisplay_t.Hook(AmyDisplay_r); + BigDisplay_t.Hook(BigDisplay_r); + } +} \ No newline at end of file diff --git a/SADXWeightedCharacters/weights.h b/SADXWeightedCharacters/weights.h new file mode 100644 index 0000000..cd70014 --- /dev/null +++ b/SADXWeightedCharacters/weights.h @@ -0,0 +1,36 @@ +#pragma once + +using std::map; + +struct ModelWeightInfo +{ + WeightInfo* weights; + int rightHandNode = -1; + int leftHandNode = -1; + int rightFootNode = -1; + int leftFootNode = -1; + int user0Node = -1; + int user1Node = -1; + int rightHandDir; + int leftHandDir; + int rightFootDir; + int leftFootDir; + int user0Dir; + int user1Dir; +}; + +struct CharInfo +{ + const char* modelPath; + const char* objectsArray; + int objectsLength; + const char* actionsArray; + int actionsLength; + const intptr_t* pointersArray; + int pointersLength; + map<NJS_OBJECT*, ModelWeightInfo> modelWeights; +}; + +extern map<int, CharInfo> charInfos; +void __cdecl ProcessVertexWelds_Check_(EntityData1* a1, EntityData2* a2, CharObj2* a3); +void initWeightsMultiplayer(); \ No newline at end of file