/
CMultiplayerSA_FixBadAnimId.cpp
163 lines (143 loc) · 5.89 KB
/
CMultiplayerSA_FixBadAnimId.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: multiplayer_sa/CMultiplayerSA_FixBadAnimId.cpp
* PORPOISE:
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/
#include "StdInc.h"
#include "../game_sa/CAnimBlendAssocGroupSA.h"
CAnimBlendAssocGroupSAInterface* getAnimAssocGroupInterface(AssocGroupId animGroup);
////////////////////////////////////////////////////////////////////////////////////////////////
// Check for anims that will crash and change to one that wont. (The new anim will be wrong and look crap though)
int _cdecl OnCAnimBlendAssocGroupCopyAnimation_FixBadAnim(AssocGroupId* pAnimGroup, int* pAnimId)
{
CAnimBlendAssocGroupSAInterface* pGroup = getAnimAssocGroupInterface(*pAnimGroup);
DWORD * pInterface = reinterpret_cast<DWORD*>(pGroup);
if (pInterface == (DWORD*)0x50 || pInterface == (DWORD*)0xA0)
{
LogEvent(534, "CopyAnimation", "Incorrect Group Interface", SString("GroupID = %d | AnimID = %d", *pAnimGroup, *pAnimId), 534);
// switch to idle animation
*pAnimGroup = ANIM_GROUP_DEFAULT;
*pAnimId = 3;
pGroup = getAnimAssocGroupInterface(*pAnimGroup);
}
// Apply offset
int iUseAnimId = *pAnimId - pGroup->iIDOffset;
if (pGroup->pAssociationsArray)
{
CAnimBlendStaticAssociationSAInterface* pAssociation = pGroup->pAssociationsArray + iUseAnimId;
if (pAssociation && pAssociation->pAnimHeirarchy == NULL)
{
// Choose another animId
int iNewAnimId = iUseAnimId;
for (int i = 0; i < pGroup->iNumAnimations; i++)
{
pAssociation = pGroup->pAssociationsArray + i;
if (pAssociation->pAnimHeirarchy)
{
// Find closest valid anim id
if (abs(iUseAnimId - i) < abs(iUseAnimId - iNewAnimId) || iNewAnimId == iUseAnimId)
iNewAnimId = i;
}
}
iUseAnimId = iNewAnimId;
LogEvent(534, "CopyAnimation", "", SString("Group:%d replaced id:%d with id:%d", pGroup->groupID, *pAnimId, iUseAnimId + pGroup->iIDOffset));
}
}
// Unapply offset
*pAnimId = iUseAnimId + pGroup->iIDOffset;
return *pAnimId;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Check for anims that will crash and change to one that wont. (The new anim will be wrong and look crap though)
int _cdecl OnCAnimBlendAssocGroupCopyAnimation_FixBadAnim_Smotra(CAnimBlendAssocGroupSAInterface* pGroup, int iAnimId)
{
// Apply offset
int iUseAnimId = iAnimId - pGroup->iIDOffset;
if (pGroup->pAssociationsArray)
{
CAnimBlendStaticAssociationSAInterface* pAssociation = pGroup->pAssociationsArray + iUseAnimId;
if (pAssociation && pAssociation->pAnimHeirarchy == NULL)
{
// Choose another animId
int iNewAnimId = iUseAnimId;
for (int i = 0; i < pGroup->iNumAnimations; i++)
{
pAssociation = pGroup->pAssociationsArray + i;
if (pAssociation->pAnimHeirarchy)
{
// Find closest valid anim id
if (abs(iUseAnimId - i) < abs(iUseAnimId - iNewAnimId) || iNewAnimId == iUseAnimId)
iNewAnimId = i;
}
}
iUseAnimId = iNewAnimId;
LogEvent(534, "CopyAnimation", "", SString("Group:%d replaced id:%d with id:%d", pGroup->groupID, iAnimId, iUseAnimId + pGroup->iIDOffset));
}
}
// Unapply offset
iAnimId = iUseAnimId + pGroup->iIDOffset;
return iAnimId;
}
DWORD RETURN_CAnimBlendAssocGroupCopyAnimation = 0x4CE136;
void _declspec(naked) HOOK_CAnimBlendAssocGroupCopyAnimation()
{
_asm
{
pushad
push[esp + 32 + 4 * 1]
push ecx
call OnCAnimBlendAssocGroupCopyAnimation_FixBadAnim_Smotra
add esp, 4 * 2
mov[esp + 32 + 4 * 1], eax
popad
mov eax, fs:0
jmp RETURN_CAnimBlendAssocGroupCopyAnimation
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Check for invalid RpHAnimHierarchy*
void _cdecl OnGetAnimHierarchyFromSkinClump(RpClump* pRpClump, void* pRpHAnimHierarchyResult)
{
if (pRpHAnimHierarchyResult == nullptr)
{
// Crash will occur at offset 003C51A8
uint uiModelId = pGameInterface->GetPools()->GetModelIdFromClump(pRpClump);
LogEvent(818, "Model bad anim hierarchy", "GetAnimHierarchyFromSkinClump", SString("Corrupt model:%d", uiModelId), 5418);
CArgMap argMap;
argMap.Set("id", uiModelId);
argMap.Set("reason", "anim_hierarchy");
SetApplicationSetting("diagnostics", "gta-model-fail", argMap.ToString());
}
}
#define HOOKPOS_GetAnimHierarchyFromSkinClump 0x734A5D
#define HOOKSIZE_GetAnimHierarchyFromSkinClump 7
DWORD RETURN_GetAnimHierarchyFromSkinClump = 0x734A64;
void _declspec(naked) HOOK_GetAnimHierarchyFromSkinClump()
{
_asm
{
pushad
push[esp + 32 + 0x0C] // RpHAnimHierarchy* (return value)
push[esp + 32 + 4 + 0x14] // RpClump*
call OnGetAnimHierarchyFromSkinClump
add esp, 4 * 2
popad
mov eax, [esp + 0x0C]
add esp, 10h
jmp RETURN_GetAnimHierarchyFromSkinClump
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Setup hooks
//
//////////////////////////////////////////////////////////////////////////////////////////
void CMultiplayerSA::InitHooks_FixBadAnimId(void)
{
EZHookInstall(GetAnimHierarchyFromSkinClump);
}