Mas não é um jump por cima de outro, o jump é por cima de outra instrução. Acho que o valor retornado é inútil nesse caso [?].
Eu tentei usar o dynasm, mas não consegui. Acho que baixei errado.
Voltar para “[Mod deletado] Desligar o motor ao pegar fogo”
Mas não é um jump por cima de outro, o jump é por cima de outra instrução. Acho que o valor retornado é inútil nesse caso [?].
Eu tentei usar o dynasm, mas não consegui. Acho que baixei errado.
Você disse uma coisa interessante aí, eu não tinha pensado nisso. O mod só funcionava caso o carro fosse consertado pela função. Corrigido.Junior_Djjr escreveu: ↑27 Mai 2018, 07:41Só que daí ficaria incompatível caso algum mod tenha editado a saúde do veículo por valor
Código: Selecionar tudo
#include "plugin.h"
uintptr_t _006A70F3 = 0x006A70F3;
uintptr_t _006A75FF = 0x006A75FF;
void __declspec(naked) SetEngineBroken_TRUE() {
__asm {
or byte ptr [esi + 428h + 5], 2
mov eax, [esi + 428h]
and eax, 0xEF
or [esi + 428h], eax
mov eax, [esi + 57Ch]
jmp [_006A70F3]
}
}
void __declspec(naked) SetEngineBroken_FALSE() {
__asm {
and byte ptr[esi + 428h + 5], 0xFD
mov[esi + 57Ch], edi
jmp [_006A75FF]
}
}
class Test {
public:
Test() {
injector::MakeJMP(0x006A70ED, SetEngineBroken_TRUE);
injector::MakeJMP(0x006A75F9, SetEngineBroken_FALSE);
}
} test;
É, mas tem vários outros fatores como o carro parar mesmo pegando um foguinho de nada (não necessariamente para explodir), o carro parando quando vira (mesmo a opção de não pegar fogo estando desabilitada no MixSets) etc.
Código: Selecionar tudo
#include "plugin.h"
uintptr_t _006A70F3 = 0x006A70F3;
uintptr_t _006A3448 = 0x006A3448;
void __declspec(naked) SetEngineBroken_TRUE() {
__asm {
or byte ptr [esi + 428h + 5], 2
mov eax, [esi + 428h]
and eax, 0xEF
or [esi + 428h], eax
mov eax, [esi + 57Ch]
jmp[_006A70F3]
}
}
void __declspec(naked) SetEngineBroken_FALSE() {
__asm {
and byte ptr [ecx + 428h + 5], 0xFD
xor eax, eax
jmp[_006A3448]
}
}
class Test {
public:
Test() {
injector::MakeJMP(0x006A70ED, SetEngineBroken_TRUE);
injector::MakeJMP(0x006A3442, SetEngineBroken_FALSE);
}
} test;
Fiz uma versão em Lua também, pra ver se aprendia alguma coisa:HybridTheory escreveu: ↑O Israel disse que a melhor maneira é hackeando o .exe.
Ele que fez.SpoilerAbrirCódigo: Selecionar tudo
{$Cleo} 0AC6: 0@ = label @_006A70ED offset 1@ = 0x006A70F3 0AC7: 2@ = var 1@ offset 0A8E: 3@ = 0@ + 0x20 0A8C: write_memory 3@ size 4 value 2@ vp 0 0@ -= 0x006A70F2 0A8C: write_memory 0x006A70ED size 1 value 0xE9 vp 1 0A8C: write_memory 0x006A70EE size 4 value 0@ vp 1 0AC6: 10@ = label @_006A3442 offset 11@ = 0x006A3448 0AC7: 12@ = var 11@ offset 0A8E: 13@ = 10@ + 0x0B 0A8C: write_memory 13@ size 4 value 12@ vp 0 10@ -= 0x006A3447 0A8C: write_memory 0x006A3442 size 1 value 0xE9 vp 1 0A8C: write_memory 0x006A3443 size 4 value 10@ vp 1 while true wait 0x7FFFFFFF end :_006A70ED hex {00000000} 808E2D04000002 // or byte [esi + 428h + 5], 2 {00000007} 8B8628040000 // mov eax, [esi + 428h] {0000000D} 25EF000000 // and eax, 0xEF {00000012} 098628040000 // or [esi + 428h], eax {00000018} 8B867C050000 // mov eax, [esi + 57Ch] {0000001E} FF2500000000 // jmp [0x00000000] ; 1@ -> 0x006A70F3 end :_006A3442 hex {00000000} 80A12D040000FD // and byte [ecx + 42Dh], 0xFD {00000007} 31C0 // xor eax, eax {00000009} FF2500000000 // jmp [0x00000000] ; 11@ -> 0x006A3448 end
Código: Selecionar tudo
local ffi = require "ffi"
ffi.cdef([[
typedef unsigned char BYTE;
typedef unsigned long DWORD;
]])
function main()
local absolute = ffi.new("DWORD[2]")
absolute[0] = 0x006A70F3
absolute[1] = 0x006A3448
local absolute_ptr = {
ffi.cast("DWORD", absolute),
ffi.cast("DWORD", absolute) + ffi.sizeof("DWORD")
}
local SetEngineBroken_TRUE = ffi.new("BYTE[36]", {
--[[00000000]] 0x80, 0x8E, 0x2D, 0x04, 0x00, 0x00, 0x02, -- or byte [esi + 428h + 5], 2
--[[00000007]] 0x8B, 0x86, 0x28, 0x04, 0x00, 0x00, -- mov eax, [esi + 428h]
--[[0000000D]] 0x25, 0xEF, 0x00, 0x00, 0x00, -- and eax, 0xEF
--[[00000012]] 0x09, 0x86, 0x28, 0x04, 0x00, 0x00, -- or [esi + 428h], eax
--[[00000018]] 0x8B, 0x86, 0x7C, 0x05, 0x00, 0x00, -- mov eax, [esi + 57Ch]
--[[0000001E]] 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 -- jmp [0x00000000]
})
local SetEngineBroken_FALSE = ffi.new("BYTE[15]", {
--[[00000000]] 0x80, 0xA1, 0x2D, 0x04, 0x00, 0x00, 0xFD, -- and byte [ecx + 428h + 5], 0xFD
--[[00000007]] 0x31, 0xC0, -- xor eax, eax
--[[00000009]] 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 -- jmp [0x00000000]
})
ffi.cast("DWORD*", SetEngineBroken_TRUE + 0x20)[0] = absolute_ptr[1]
ffi.cast("DWORD*", SetEngineBroken_FALSE + 0x0B)[0] = absolute_ptr[2]
MakeJMP(0x006A70ED, SetEngineBroken_TRUE)
MakeJMP(0x006A3442, SetEngineBroken_FALSE)
wait(-1)
end
function MakeJMP(at, dest)
local relative = ffi.cast("uintptr_t", dest)
relative = relative - (at + 5)
ffi.cast("BYTE*", at)[0] = 0xE9 -- jmp
ffi.cast("DWORD*", at + 1)[0] = relative
end
De nada.
É o tipo da entidade, tente assim:
Código: Selecionar tudo
SCRIPT_START
{
LVAR_INT car, p, i
IF IS_AUSTRALIAN_GAME
CREATE_CAR 0 0.0 0.0 0.0 (car)
ENDIF
main_loop:
WAIT 0
READ_MEMORY 0x00B74494 4 0 (p)
p += 0x04
READ_MEMORY p 4 0 (p)
i = 0
WHILE i <= 0x6D00
READ_MEMORY p 1 0 (car)
p++
IF car >= 0x00
AND car < 0x80
car += i
IF IS_CAR_ON_FIRE car
SET_CAR_ENGINE_BROKEN car TRUE
ENDIF
ENDIF
i += 0x100
ENDWHILE
GOTO main_loop
}
SCRIPT_END
Código: Selecionar tudo
READ_MEMORY 0x00B74494 4 0 (p)
p += 0x04
READ_MEMORY p 4 0 (p)
i = 0
WHILE i <= 0x6D00
READ_MEMORY p 1 0 (car)
p++
IF car >= 0x00
AND car < 0x80
car += i
// car
ENDIF
i += 0x100
ENDWHILE
Código: Selecionar tudo
READ_MEMORY 0x00B74490 4 0 (p)
p += 0x04
READ_MEMORY p 4 0 (p)
i = 0
WHILE i <= 0x8B00
READ_MEMORY p 1 0 (char)
p++
IF char >= 0x00
AND char < 0x80
char += i
// char
ENDIF
i += 0x100
ENDWHILE
Código: Selecionar tudo
READ_MEMORY 0x00B7449C 4 0 (p)
p += 0x04
READ_MEMORY p 4 0 (p)
i = 0
WHILE i <= 0x15D00
READ_MEMORY p 1 0 (obj)
p++
IF obj >= 0x00
AND obj < 0x80
obj += i
// obj
ENDIF
i += 0x100
ENDWHILE
Código: Selecionar tudo
i = 0x009788C0
WHILE i <= 0x0097D620
pickup = i + 0x1A
READ_MEMORY pickup 2 0 (pickup)
pickup *= 0x10000
p = i - 0x009788C0
p /= 0x20
pickup += p
// pickup
i += 0x20
ENDWHILE
GOTO_IF_FALSE loop
aí é desnecessário. Se a condição retornar false já vai pro GOTO loop
ali...