summaryrefslogtreecommitdiff
path: root/source/sourcemod/scripting/movementapi/stocks.sp
blob: e080efc9fa2ed689643a3f3ee6963f6513472672 (plain)
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
stock void GameMove_SetVelocity(Address addr, float velocity[3])
{
	if (velocity[0] != velocity[0] || velocity[1] != velocity[1] || velocity[2] != velocity[2])
	{
		return;
	}
	static int mvOffset;
	static int velocityOffset;
	if (!mvOffset)
	{
		char buffer[8];
		if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CGameMovement::mv offset.");
			return;
		}
		mvOffset = StringToInt(buffer);
		if (!gH_GameData.GetKeyValue("CMoveData::m_vecVelocity", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CMoveData::m_vecVelocity offset.");
			return;
		}
		velocityOffset = StringToInt(buffer);
	}

	Address mvAddress = view_as<Address>(LoadFromAddress(view_as<Address>(view_as<int>(addr) + mvOffset), NumberType_Int32));
	// TODO: idk if raw cast works here or not
	StoreToAddress(view_as<Address>(view_as<int>(mvAddress) + velocityOffset), view_as<int>(velocity[0]), NumberType_Int32);
	StoreToAddress(view_as<Address>(view_as<int>(mvAddress) + velocityOffset + 4), view_as<int>(velocity[1]), NumberType_Int32);
	StoreToAddress(view_as<Address>(view_as<int>(mvAddress) + velocityOffset + 8), view_as<int>(velocity[2]), NumberType_Int32);
}

stock void GameMove_SetOrigin(Address addr, float origin[3])
{
	if (origin[0] != origin[0] || origin[1] != origin[1] || origin[2] != origin[2])
	{
		return;
	}
	static int mvOffset;
	static int originOffset;
	if (!mvOffset)
	{
		char buffer[8];
		if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CGameMovement::mv offset.");
			return;
		}
		mvOffset = StringToInt(buffer);
		if (!gH_GameData.GetKeyValue("CMoveData::m_vecAbsOrigin", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CMoveData::m_vecAbsOrigin offset.");
			return;
		}
		originOffset = StringToInt(buffer);
	}

	Address mvAddress = view_as<Address>(LoadFromAddress(view_as<Address>(view_as<int>(addr) + mvOffset), NumberType_Int32));
	// TODO: idk if raw cast works here or not
	StoreToAddress(view_as<Address>(view_as<int>(mvAddress) + originOffset), view_as<int>(origin[0]), NumberType_Int32);
	StoreToAddress(view_as<Address>(view_as<int>(mvAddress) + originOffset + 4), view_as<int>(origin[1]), NumberType_Int32);
	StoreToAddress(view_as<Address>(view_as<int>(mvAddress) + originOffset + 8), view_as<int>(origin[2]), NumberType_Int32);
}

stock void GameMove_GetVelocity(Address addr, float result[3])
{
	static int mvOffset;
	static int velocityOffset;
	if (!mvOffset)
	{
		char buffer[8];
		if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CGameMovement::mv offset.");
			return;
		}
		mvOffset = StringToInt(buffer);
		if (!gH_GameData.GetKeyValue("CMoveData::m_vecVelocity", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CMoveData::m_vecVelocity offset.");
			return;
		}
		velocityOffset = StringToInt(buffer);
	}

	Address mvAddress = view_as<Address>(LoadFromAddress(view_as<Address>(view_as<int>(addr) + mvOffset), NumberType_Int32));
	result[0] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + velocityOffset), NumberType_Int32));
	result[1] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + velocityOffset + 4), NumberType_Int32));
	result[2] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + velocityOffset + 8), NumberType_Int32));
}

stock void GameMove_GetOrigin(Address addr, float result[3])
{
	static int mvOffset;
	static int originOffset;
	if (!mvOffset)
	{
		char buffer[8];
		if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CGameMovement::mv offset.");
			return;
		}
		mvOffset = StringToInt(buffer);
		if (!gH_GameData.GetKeyValue("CMoveData::m_vecAbsOrigin", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CMoveData::m_vecAbsOrigin offset.");
			return;
		}
		originOffset = StringToInt(buffer);
	}
	
	Address mvAddress = view_as<Address>(LoadFromAddress(view_as<Address>(view_as<int>(addr) + mvOffset), NumberType_Int32));
	result[0] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + originOffset), NumberType_Int32));
	result[1] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + originOffset + 4), NumberType_Int32));
	result[2] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + originOffset + 8), NumberType_Int32));
}

stock void GameMove_GetEyeAngles(Address addr, float result[3])
{
	static int mvOffset;
	static int viewAngleOffset;
	if (!mvOffset)
	{
		char buffer[8];
		if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CGameMovement::mv offset.");
			return;
		}
		mvOffset = StringToInt(buffer);
		if (!gH_GameData.GetKeyValue("CMoveData::m_viewAngleOffset", buffer, sizeof(buffer)))
		{
			ThrowError("Failed to get CMoveData::m_viewAngleOffset offset.");
			return;
		}
		viewAngleOffset = StringToInt(buffer);
	}
	
	Address mvAddress = view_as<Address>(LoadFromAddress(view_as<Address>(view_as<int>(addr) + mvOffset), NumberType_Int32));
	result[0] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + viewAngleOffset), NumberType_Int32));
	result[1] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + viewAngleOffset + 4), NumberType_Int32));
	result[2] = view_as<float>(LoadFromAddress(view_as<Address>(view_as<int>(mvAddress) + viewAngleOffset + 8), NumberType_Int32));
}

stock int GetEntityFromAddress(Address pEntity) {
	static int offs_RefEHandle;
	if (offs_RefEHandle) {
		return EntRefToEntIndex(LoadFromAddress(pEntity + view_as<Address>(offs_RefEHandle), NumberType_Int32) | (1 << 31));
	}

	// if we don't have it already, attempt to lookup offset based on SDK information
	// CWorld is derived from CBaseEntity so it should have both offsets
	int offs_angRotation = FindDataMapInfo(0, "m_angRotation"),
			offs_vecViewOffset = FindDataMapInfo(0, "m_vecViewOffset");
	if (offs_angRotation == -1) {
		ThrowError("Could not find offset for ((CBaseEntity) CWorld)::m_angRotation");
	} else if (offs_vecViewOffset == -1) {
		ThrowError("Could not find offset for ((CBaseEntity) CWorld)::m_vecViewOffset");
	} else if ((offs_angRotation + 0x0C) != (offs_vecViewOffset - 0x04)) {
		char game[32];
		GetGameFolderName(game, sizeof(game));
		ThrowError("Could not confirm offset of CBaseEntity::m_RefEHandle "
				... "(incorrect assumption for game '%s'?)", game);
	}
	
	// offset seems right, cache it for the next call
	offs_RefEHandle = offs_angRotation + 0x0C;
	return GetEntityFromAddress(pEntity);
}

stock int GetClientFromGameMovementAddress(Address addr) 
{
	char buffer[8];
	if (!gH_GameData.GetKeyValue("CGameMovement::player", buffer, sizeof(buffer)))
	{
		ThrowError("Failed to get CGameMovement::player offset.");
		return -1;
	}
	int offset = StringToInt(buffer);
	Address playerAddr = view_as<Address>(LoadFromAddress(view_as<Address>(view_as<int>(addr) + offset), NumberType_Int32));
	return GetEntityFromAddress(playerAddr);
}

stock void HookGameMovementFunction(DynamicDetour handle, char[] fName, DHookCallback preCallback, DHookCallback postCallback)
{
	handle = DynamicDetour.FromConf(gH_GameData, fName);
	if (!handle)
	{
		SetFailState("Failed to find %s config", fName);
	}
	if (!handle.Enable(Hook_Pre, preCallback))
	{
		SetFailState("Failed to enable detour on %s", fName);
	}
	if (!handle.Enable(Hook_Post, postCallback))
	{
		SetFailState("Failed to enable detour on %s", fName);
	}
}