- 2
- 0
- Версия MoonLoader
- .026-beta
Понимаю, что крайне редкая проблема, ибо касается по большей части одиночной игры, но:
Как я понимаю, в отличии от newOpcodes в MoonAdditions никто не переносил функционал Cleo+ как библиотеку, а так как у меня с С++ слабо, даже имея исходники данной библиотеки для Cleo шансы сделать с него lua-библиотеку крайне малы. В связи с этим у меня родилась странная идея, но, возможно, кто-то так уже делал: возможно ли вызывать каким-то образом сторонние cleo опкоды, например, через ffi с указанием параметров?
UPD: Я нашёл вот такое:
И оно прекрасно работает с стандартными опкодами San Andreas, но cleo+ сразу крашит, есть ли возможность это исправить? И к тому же, возможно ли добавить выведение значений, что возвращает опкод?
Думаю, это рано или поздно кому-то пригодится кроме меня, используя тот большой набор функций, включая тот же рендер объектов
Как я понимаю, в отличии от newOpcodes в MoonAdditions никто не переносил функционал Cleo+ как библиотеку, а так как у меня с С++ слабо, даже имея исходники данной библиотеки для Cleo шансы сделать с него lua-библиотеку крайне малы. В связи с этим у меня родилась странная идея, но, возможно, кто-то так уже делал: возможно ли вызывать каким-то образом сторонние cleo опкоды, например, через ffi с указанием параметров?
UPD: Я нашёл вот такое:
Lua:
local ffi = require 'ffi'
local memory = require 'memory'
ffi.cdef[[
struct CRunningScript {
struct CRunningScript *m_pNext;
struct CRunningScript *m_pPrev;
char m_szName[8];
unsigned char *m_pBaseIP;
unsigned char *m_pCurrentIP;
unsigned char *m_apStack[8];
unsigned short m_nSP;
char _pad3A[2];
int m_aLocalVars[32];
int m_anTimers[2];
unsigned char m_bIsActive;
unsigned char m_bCondResult;
unsigned char m_bUseMissionCleanup;
unsigned char m_bIsExternal;
unsigned char m_bTextBlockOverride;
char m_externalType;
char field_CA[2];
int m_nWakeTime;
unsigned short m_nLogicalOp;
unsigned char m_bNotFlag;
unsigned char m_bWastedBustedCheck;
unsigned char m_bWastedOrBusted;
char _padD5[3];
void *m_pSceneSkipIP;
unsigned char m_bIsMission;
char _padDD[3];
};
]]
local gst_mt = {}
gst_mt.__index = gst_mt
function gst_mt:writeInteger(pos, val)
self.buf[pos] = 1
pos = pos + 1
ffi.cast('int*', self.buf + pos)[0] = val
pos = pos + 4
return pos
end
function gst_mt:writeFloat(pos, val)
self.buf[pos] = 6
pos = pos + 1
ffi.cast('float*', self.buf + pos)[0] = val
pos = pos + 4
return pos
end
function gst_mt:writeVariable(pos, val)
self.buf[pos] = 3
pos = pos + 1
local idx = #paramvars
self.paramvars[idx] = val
self.gst[0].m_aLocalVars[idx] = ffi.cast('int*', val)[0]
ffi.cast('short*', self.buf + pos)[0] = idx
pos = pos + 2
return pos
end
function gst_mt:writeString(pos, val)
self.buf[pos] = 14
pos = pos + 1
ffi.cast('unsigned char*', self.buf + pos)[0] = val:len()
ffi.copy(self.buf + pos + 1, val)
pos = pos + 1 + val:len()
return pos
end
function gst_mt:writeZero(pos)
self.buf[pos] = 0
pos = pos + 1
return pos
end
local CRunningScript__ProcessOneCommand = ffi.cast('void(__thiscall*)(struct CRunningScript*)', 0x469EB0)
function gst_mt:execute()
-- memory.setuint16(0x469EF5, 0xD2FF) -- only for samp
self.gst[0].m_pCurrentIP = self.buf
CRunningScript__ProcessOneCommand(self.gst)
for i, k in ipairs(self.paramvars) do
ffi.cast('int*', k)[0] = self.gst[0].m_aLocalVars[i]
end
-- memory.setuint16(0x469EF5, 0xD08B) -- only for samp
end
local function new_gst()
local gst = ffi.new('struct CRunningScript[1]', {})
local buf = ffi.new('unsigned char[255]', {0})
return setmetatable({ gst = gst, buf = buf, paramvars = {} }, gst_mt)
end
local gst = new_gst()
local function callOpcode(opcode, ...)
local bufpos = 2
ffi.cast('short*', gst.buf)[0] = opcode
for i = 1, select('#', ...) do
local v = select(i, ...)
if v[2] == 'i' then bufpos = gst:writeInteger(bufpos, v[1])
elseif v[2] == 'f' then bufpos = gst:writeFloat(bufpos, v[1])
elseif v[2] == 'v' then bufpos = gst:writeVariable(bufpos, v[1])
elseif v[2] == 's' then bufpos = gst:writeString(bufpos, v[1])
elseif v[2] == 'z' then bufpos = gst:writeZero(bufpos, v[1]) end
end
gst:execute()
end
function main()
while true do wait(0)
if testCheat("TEST") then
print('running...')
callOpcode(0x00A1, { PLAYER_PED, 'i' }, { 0, 'f' }, { 0, 'f' }, { 0, 'f' })
end
end
end
И оно прекрасно работает с стандартными опкодами San Andreas, но cleo+ сразу крашит, есть ли возможность это исправить? И к тому же, возможно ли добавить выведение значений, что возвращает опкод?
Думаю, это рано или поздно кому-то пригодится кроме меня, используя тот большой набор функций, включая тот же рендер объектов
Последнее редактирование: