-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathGameScripting.cpp
More file actions
129 lines (111 loc) · 3.95 KB
/
GameScripting.cpp
File metadata and controls
129 lines (111 loc) · 3.95 KB
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
#include "main.h"
// from here https://github.com/jovazxc/samp/blob/master/client/game/scripting.cpp
GAME_SCRIPT_THREAD *gst;
FARPROC ProcessOneCommand = (FARPROC)0x469EB0;
BYTE ScriptBuf[255];
DWORD *pdwParamVars[18];
int __declspec (naked) ExecuteScriptBuf()
{
__asm
{
mov eax, OFFSET ScriptBuf // Move our script buffer base into eax.
mov ecx, gst // Move GAME_SCRIPT_THREAD structure into ecx.
mov[ecx + 0x14], eax // Move eax into the gst->dwScriptIP.
call ProcessOneCommand // Call the game's script opcode processor.
mov ecx, gst // Move game script thread into ecx again.
mov eax, [ecx + 0xC5] // Move the dwIfFlag into eax (return value).
ret // return.
}
}
int ScriptCommand(const SCRIPT_COMMAND *pScriptCommand, ...)
{
va_list ap;
const char *p = pScriptCommand->Params; // Get parameter string.
va_start(ap, pScriptCommand); // Initialize varargs.
memcpy(&ScriptBuf, &pScriptCommand->OpCode, 2); // Copy opcode to script buf.
int buf_pos = 2; // Position in buffer after opcode.
WORD var_pos = 0; // Init var_pos.
// (aru) Reset all vars before proceeding (To fix some nasty 0x00465CB4 crashes)
// May cause problems with functions that use local vars returned from previous calls
for (int i = 0; i < 18; i++)
gst->dwLocalVar[i] = 0;
while (*p) // While we've not ran out of parameters...
{
switch (*p) // Switch current parameter.
{
case 'i': // If integer...
{
int i = va_arg(ap, int); // Grab an int off the stack.
ScriptBuf[buf_pos] = 0x01; // Variable data type = 0x01 (4b int).
buf_pos++;;
// Increment buffer position.
memcpy(&ScriptBuf[buf_pos], &i, 4); // Insert the int.
buf_pos += 4; // Increment buffer by 4b.
break;
}
case 'f': // If float...
{
/* Take note, MSVC++ puts a double on the stack
even if you typecase as a float. <3 Microsoft. */
float f = (float)va_arg(ap, double); // Get float off the stack.
ScriptBuf[buf_pos] = 0x06; // Variable data type = 0x06 (float).
buf_pos++; // Increment buffer position.
memcpy(&ScriptBuf[buf_pos], &f, 4); // Copy float into script buf.
buf_pos += 4; // Increment buffer by 4b.
break;
}
case 'v': // If variable...
{
DWORD *v = va_arg(ap, DWORD *); // Get the pointer to the passed variable.
ScriptBuf[buf_pos] = 0x03; // Variable data type = 0x03 (Local Var).
buf_pos++; // Increment buffer position.
pdwParamVars[var_pos] = v; // Save pointer to passed variable.
gst->dwLocalVar[var_pos] = *v; // Put value of passed variable into local.
memcpy(&ScriptBuf[buf_pos], &var_pos, 2); // Copy the offset into the script.
buf_pos += 2; // Increment buffer by 2b.
var_pos++; // Increment the variable position.
break;
}
case 's': // If string... Updated 13th Jan 06.. (kyeman) SA string support
{
char* sz = va_arg(ap, char*);
unsigned char aLen = (unsigned char)strlen(sz);
ScriptBuf[buf_pos] = 0x0E;
buf_pos++;
ScriptBuf[buf_pos] = aLen;
buf_pos++;
memcpy(&ScriptBuf[buf_pos], sz, aLen);
buf_pos += aLen;
break;
}
case 'z': // If the params need zero-terminating...
{
ScriptBuf[buf_pos] = 0x00;
buf_pos++;
break;
}
default:
{
return 0;
}
}
++p; // Next parameter
}
va_end(ap); // End varargs.
// Execute script stub.
int result = 0;
result = ExecuteScriptBuf();
if (var_pos) // if we've used a variable...
{
for (int i = 0; i < var_pos; i++) // For every passed variable...
{
*pdwParamVars[i] = gst->dwLocalVar[i]; // Retrieve variable from local var.
}
}
return result;
}
void InitScripting()
{
gst = new GAME_SCRIPT_THREAD;
ZeroMemory(gst, sizeof(GAME_SCRIPT_THREAD));
}