Skip to content

Commit

Permalink
Add Multiplayer support
Browse files Browse the repository at this point in the history
  • Loading branch information
Sora-yx committed Feb 21, 2024
1 parent dcff4a0 commit 02fea4f
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 51 deletions.
6 changes: 5 additions & 1 deletion SADXWeightedCharacters/SADXWeightedCharacters.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down
6 changes: 6 additions & 0 deletions SADXWeightedCharacters/SADXWeightedCharacters.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand All @@ -32,5 +35,8 @@
<ClCompile Include="mod.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="multiplayer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
84 changes: 34 additions & 50 deletions SADXWeightedCharacters/mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
Expand Down Expand Up @@ -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 };
Expand Down
93 changes: 93 additions & 0 deletions SADXWeightedCharacters/multiplayer.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
36 changes: 36 additions & 0 deletions SADXWeightedCharacters/weights.h
Original file line number Diff line number Diff line change
@@ -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();

0 comments on commit 02fea4f

Please sign in to comment.