Brazilian Modding Studio
Olá, seja bem vindo à Comunidade BMS!

Para se registrar no fórum, siga os passos:

1 - Clique em "Registrar-se" aqui em baixo;
2 - Aceite os termos de serviço;
3 - Escolha um nome de usuário e senha;
4 - Realize o login no fórum clicando em "Conectar-se".

Compartilhe
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22943
Reputação : 727
Desde : 03/05/2012
Idade : 22
Localização : Ibitinga - SP
Link : www.MixMods.com.br
Ver perfil do usuáriohttp://MixMods.com.br
  • Reputação da mensagem: 100% (1 votos)
em Dom 06 Ago 2017, 17:01


Concluindo esta parte você vai:
Entrar na "deep web" do jogo. Nas profundezas onde você pode conseguir ler e escrever vários valores antes inacessíveis.
Você irá aprender a manipular valores nas classes do jogo, "caminhando" pelas classes etc para encontrar as informações que você deseja em seu mod.

Esta é mais uma parte onde você vai entrar (novamente) em um novo mundo; aprender a, realmente, criar mods como bem entender. Ultrapassar mais limites.
Eu já falei isso anteriormente na parte sobre Condições, e realmente, eu não estava brincando, né?

Se você já tem conhecimento sobre alguma programação orientada à objetos, parabéns! Você já sabe tudo e pode ir pra próxima parte- mentira, o que vamos fazer aqui é muito diferente do que você deve saber. E provavelmente você odiará :)
Se você é novo no assunto, vai achar muito interessante!

Quando eu aprendi (iniciando diretamente em CLEO) eu tive um pouco de dificuldade no início, e isso é bom, pois agora eu acredito que sei como evitar que você também tenha dificuldade..




Introdução

O GTA III, VC, SA e vários outros jogos foram programados em C++ ou alguma outra programação orientada à objetos (C#, Java etc etc...). É um tipo de programação extremamente útil para jogos, pois nela você pode criar várias "class", onde elas podem organizar uma coleção de informações sobre alguma coisa, como algum veículo, um pedestre, ou até mesmo a câmera do jogo e coisas que você nunca vai saber o que significa.

Imagine: Você tem uma class com nome "Carro", onde, é claro, ela está interligada com algum carro específico dentro do jogo.
Dentro desta class você tem informações como: Qual é a massa; Velocidade máxima; Quantidade de marchas (for english: "Marchas" = "Gears") e Ocupantes:
Código:
Carro {
Massa
VelocidadeMáxima
Marchas
Ocupantes
}
Que tipo de data type cada "membro" usaria?

Você consegue imaginar?

Bem, vamos colocar:
Código:
Carro {
FLOAT Massa
FLOAT VelocidadeMáxima
BYTE Marchas
BYTE Ocupantes
}
Faz sentido, certo?
1 byte vai até "255" (-128 até 127 caso signed, mas não vem ao caso), só precisamos de 1 byte para a quantidade de marchas e ocupantes, mas a massa e velocidade precisam de números mais definidos: floats.

Atenção: Eu só estou mostrando pseudocodes. Estes códigos não existem, são somente didáticos!

Agora, tente imaginar estes valores preenchidos:
Código:
Carro {
FLOAT Massa = 1500.0
FLOAT VelocidadeMáxima = 200.0
BYTE Marchas = 5
BYTE Ocupantes = 3
}
Certo, nós temos um carro com estes valores.

Estas informações são usadas durante o processamento do carro no jogo!
Ou seja, quando o jogo precisar saber quantos ocupantes este carro tem, ele pega o valor em Carro -> Ocupantes
Quando um novo ocupante entrar no carro, o jogo aumentará este valor.

Mas como exatamente é isso?

Dentro da memória, toda esta "estrutura" (struct) está, é claro, em algum lugar!

Vamos supor que o endereço onde está localizado esta estrutura (mais especificamente o início dela), é "1000". (vamos esquecer dos "0xD34DC0DE" e simplificar a conta com um "1000")

No início dela, temos:
Código:
FLOAT Massa
Que guarda um valor "float", onde nosso float tem 4 bytes, lembra?
Portanto, se nós lermos 4 bytes de "1000 + 0" (ou seja, "1000", dã!) nós teremos o valor da massa deste carro (que é "1500.0").

Certo, se nos primeiros 4 bytes nós temos um valor, onde que está o segundo valor? +4!

Se você tem um valor de 4 bytes, basta você subir 4 bytes para "pular" este valor e assim encontrar o próximo. Exatamente a mesma coisa já explicada na parte sobre thread memory.

Enfim, se você ler "1000 + 4" (ou seja, o endereço "1004") você terá outro valor de 4 bytes, agora, a velocidade máxima.

Continuando, em "1000 + 8" você tem a quantidade de marchas! Leia 1 byte para ter o valor de marchas do carro, neste caso em específico, você terá o valor "5".

"1000 + 9" tem você a quantidade de ocupantes. Lembre-se, a quantidade de marchas é só 1 byte, portanto, o próximo número foi só "+1".

Aumentando mais um byte, portanto, "1000 + 10", nós chegamos no fim. Se você ler "1000 + 10" você encontrará coisas estranhas, pois a nossa class já acabou.
Perceba que esta class tem o total de 10 bytes.


O mundo real

Agora vamos ver um exemplo mais "verdadeiro":
Código:
00000000 RwRGBA          struc ; (sizeof=0x4)
00000000 red             db ?
00000001 green           db ?
00000002 blue            db ?
00000003 alpha           db ?
00000004 RwRGBA          ends
Certo, temos a class "RwRGBA" ("Rw" = RenderWare = a engine do jogo, o nome é basicamente "RGBA")
Com certeza você já sabe: RGBA = Red, Green, Blue, Alpha. Simplesmente, uma cor, e com transparência.
O primeiro byte, é o vermelho, depois verde... E assim sucessivamente.
A struct tem 4 bytes no total.

Tenha a nota de que essa struct foi retirada do IDA Pro por engenharia reversa, as classes não são originalmente definidas desta maneira (mesmo assim, muito semelhante). Mas este formato de leitura nos ajuda muito no nosso trabalho do "modding-hacking".

Imagine que você tenha o ponteiro dela numa variável com nome "pRGBA" e você quer ter somente o valor azul dela.

Você faria assim:
Código:
pRGBA += 2
READ_MEMORY pRGBA 1 FALSE (iBlue)
Ou, mais convenientemente, assim:
Código:
pBlue = pRGBA + 2
READ_MEMORY pBlue 1 FALSE (iBlue)
Simples. Você subiu 2 bytes e leu 1 byte deste local, agora, você tem o valor do azul dentro da variável "iBlue"
Perceba que eu uso "p" para "pointer" (ponteiro) e "i" para "integer" (número inteiro) nas variáveis. É só por organização. Está aí uma dica, caso você gostar!

Perceba que você facilmente consegue ler a struct desta class:
Código:
00000002 blue            db ?
Inclusive a própria struct diz qual é o offset de cada field.
Em +2 você tem um byte (o "b" do "db" é "byte") que aponta para a field "blue" (o valor do azul).

É muito importante notar que esse "2" não é decimal, e sim hexadecimal!!! Ou seja, é um "0x2"

Portanto, o mais correto seria assim:
Código:
pBlue = pRGBA + 0x2
READ_MEMORY pBlue 1 FALSE (iBlue)
Neste caso o resultado é o mesmo, mas em offsets maiores, você esquecer disso será um desastre.
Por exemplo "0x10" não é "10" e sim "16". Não se esqueça da contagem hexadecimal!!! 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B (...)

Outro detalhe importante é que do mesmo modo que "01" (decimal) é igual a "1", você digitar "0x01" (hexadecimal) é igual a "0x1", assim como "0x001", "0x000000001" etc. Só um detalhe para não se confundir.

Outra coisa que quero te lembrar, é que hexadecimal é simplesmente um modo diferente de digitar números, se você preferir digitar "10" ao invés de "0xA" (e vice versa) dá na mesma, não há obrigação.
Portanto, se você está contando de 4 em 4, você pode simplesmente fazer "4, 8, 12, 16", você não é obrigado a digitar "0x4, 0x8, 0xC, 0x10" (que é um tanto estranho para pessoas comuns)

Depois deste tira-dúvidas rápido sobre hexadecimal, vamos voltar ao foco:


Colocando a mão na massa

Vamos aplicar o que aprendemos até agora!

Abaixo temos a CPed (Class Ped) que a comunidade montou.


Código:
00000000 CPed            struc ; (sizeof=0x79C)
00000000 __parent        CPhysical ?
00000138 field_138       db 348 dup(?)           ; object_86C2A8
00000294 sound           CPedSound ?             ; object_85F310 (CPedSound?)
00000394 field_394       db 164 dup(?)           ; object_86C2AC
00000438                 db ? ; undefined
00000439                 db ? ; undefined
0000043A                 db ? ; undefined
0000043B                 db ? ; undefined
0000043C                 db ? ; undefined
0000043D                 db ? ; undefined
0000043E                 db ? ; undefined
0000043F                 db ? ; undefined
00000440                 db ? ; undefined
00000441                 db ? ; undefined
00000442                 db ? ; undefined
00000443                 db ? ; undefined
00000444                 db ? ; undefined
00000445                 db ? ; undefined
00000446                 db ? ; undefined
00000447                 db ? ; undefined
00000448                 db ? ; undefined
00000449                 db ? ; undefined
0000044A                 db ? ; undefined
0000044B                 db ? ; undefined
0000044C                 db ? ; undefined
0000044D                 db ? ; undefined
0000044E                 db ? ; undefined
0000044F                 db ? ; undefined
00000450                 db ? ; undefined
00000451                 db ? ; undefined
00000452                 db ? ; undefined
00000453                 db ? ; undefined
00000454                 db ? ; undefined
00000455                 db ? ; undefined
00000456                 db ? ; undefined
00000457                 db ? ; undefined
00000458                 db ? ; undefined
00000459                 db ? ; undefined
0000045A                 db ? ; undefined
0000045B                 db ? ; undefined
0000045C                 db ? ; undefined
0000045D                 db ? ; undefined
0000045E                 db ? ; undefined
0000045F                 db ? ; undefined
00000460 field_460       db ?
00000461                 db ? ; undefined
00000462                 db ? ; undefined
00000463                 db ? ; undefined
00000464                 db ? ; undefined
00000465                 db ? ; undefined
00000466                 db ? ; undefined
00000467                 db ? ; undefined
00000468 field_468       dd ?
0000046C pedFlags        dd ?                    ; flags: 0x100 - in vehicle
00000470 field_470       dd ?
00000474 field_474       dd ?                    ; 0x1000000 - special actor ?
00000478 field_478       dd ?                    ; 0x200 = ignore weapon range flag
0000047C intelligence    dd ?                    ; CPedIntelligence *
00000480 pPlayerData     dd ?
00000484 field_484       db ?
00000485                 db ? ; undefined
00000486                 db ? ; undefined
00000487                 db ? ; undefined
00000488 field_488       dd ?
0000048C                 db ? ; undefined
0000048D                 db ? ; undefined
0000048E                 db ? ; undefined
0000048F                 db ? ; undefined
00000490                 db ? ; undefined
00000491                 db ? ; undefined
00000492                 db ? ; undefined
00000493                 db ? ; undefined
00000494                 db ? ; undefined
00000495                 db ? ; undefined
00000496                 db ? ; undefined
00000497                 db ? ; undefined
00000498                 db ? ; undefined
00000499                 db ? ; undefined
0000049A                 db ? ; undefined
0000049B                 db ? ; undefined
0000049C                 db ? ; undefined
0000049D                 db ? ; undefined
0000049E                 db ? ; undefined
0000049F                 db ? ; undefined
000004A0                 db ? ; undefined
000004A1                 db ? ; undefined
000004A2                 db ? ; undefined
000004A3                 db ? ; undefined
000004A4                 db ? ; undefined
000004A5                 db ? ; undefined
000004A6                 db ? ; undefined
000004A7                 db ? ; undefined
000004A8                 db ? ; undefined
000004A9                 db ? ; undefined
000004AA                 db ? ; undefined
000004AB                 db ? ; undefined
000004AC                 db ? ; undefined
000004AD                 db ? ; undefined
000004AE                 db ? ; undefined
000004AF                 db ? ; undefined
000004B0                 db ? ; undefined
000004B1                 db ? ; undefined
000004B2                 db ? ; undefined
000004B3                 db ? ; undefined
000004B4                 db ? ; undefined
000004B5                 db ? ; undefined
000004B6                 db ? ; undefined
000004B7                 db ? ; undefined
000004B8                 db ? ; undefined
000004B9                 db ? ; undefined
000004BA                 db ? ; undefined
000004BB                 db ? ; undefined
000004BC                 db ? ; undefined
000004BD                 db ? ; undefined
000004BE                 db ? ; undefined
000004BF                 db ? ; undefined
000004C0                 db ? ; undefined
000004C1                 db ? ; undefined
000004C2                 db ? ; undefined
000004C3                 db ? ; undefined
000004C4                 db ? ; undefined
000004C5                 db ? ; undefined
000004C6                 db ? ; undefined
000004C7                 db ? ; undefined
000004C8                 db ? ; undefined
000004C9                 db ? ; undefined
000004CA                 db ? ; undefined
000004CB                 db ? ; undefined
000004CC                 db ? ; undefined
000004CD                 db ? ; undefined
000004CE                 db ? ; undefined
000004CF                 db ? ; undefined
000004D0                 db ? ; undefined
000004D1                 db ? ; undefined
000004D2                 db ? ; undefined
000004D3                 db ? ; undefined
000004D4 animGroupID     dd ?
000004D8 field_4D8       dd ?
000004DC field_4DC       dd ?
000004E0 acquaintance    CPedAcquaintance ?
000004F4 RpAtomic_Weapon1Model dd ?              ; RwObject of the weapon model ?
000004F8 RpAtomic_WeaponGunFlash dd ?
000004FC RpAtomic_Googles dd ?
00000500 pGooglesType    dd ?
00000504 weaponGunflashAlphaMP1 dw ?
00000506 weaponGunflashAlphaMP2 dw ?
00000508 field_508       dw ?
0000050A field_50A       dw ?
0000050C field_50C       db ?                    ; PedIK ?
0000050D                 db ? ; undefined
0000050E                 db ? ; undefined
0000050F                 db ? ; undefined
00000510                 db ? ; undefined
00000511                 db ? ; undefined
00000512                 db ? ; undefined
00000513                 db ? ; undefined
00000514                 db ? ; undefined
00000515                 db ? ; undefined
00000516                 db ? ; undefined
00000517                 db ? ; undefined
00000518                 db ? ; undefined
00000519                 db ? ; undefined
0000051A                 db ? ; undefined
0000051B                 db ? ; undefined
0000051C                 db ? ; undefined
0000051D                 db ? ; undefined
0000051E                 db ? ; undefined
0000051F                 db ? ; undefined
00000520                 db ? ; undefined
00000521                 db ? ; undefined
00000522                 db ? ; undefined
00000523                 db ? ; undefined
00000524                 db ? ; undefined
00000525                 db ? ; undefined
00000526                 db ? ; undefined
00000527                 db ? ; undefined
00000528 field_528       dd ?
0000052C field_52C       dd ?
00000530 field_530       dd ?
00000534 WalkMode        dd ?
00000538 field_538       dd ?
0000053C                 db ? ; undefined
0000053D                 db ? ; undefined
0000053E                 db ? ; undefined
0000053F                 db ? ; undefined
00000540 field_540       dd ?
00000544 field_544       dd ?
00000548 armour          dd ?
0000054C field_54C       dd ?
00000550 field_550       dd ?
00000554 field_554       dd ?
00000558 field_558       dd ?
0000055C field_55C       dd ?
00000560 field_560       dd ?
00000564 field_564       dd ?
00000568 field_568       dd ?
0000056C field_56C       RwV3D ?
00000578 field_578       RwV3D ?
00000584 field_584       dd ?
00000588 field_588       dd ?
0000058C vehicle         dd ?                    ; offset
00000590 field_590       dd ?
00000594 field_594       dd ?
00000598 pedType         dd ?
0000059C field_59C       dd ?
000005A0 weaponSlots     CWeaponSlot 13 dup(?)
0000070C field_70C       dd ?
00000710 field_710       dd ?
00000714                 db ? ; undefined
00000715                 db ? ; undefined
00000716                 db ? ; undefined
00000717                 db ? ; undefined
00000718 m_bActiveWeapon db ?                    ; activeWeapon
00000719 field_719       db ?
0000071A weaponAccuracy  db ?
0000071B                 db ? ; undefined
0000071C ?targetedObject dd ?
00000720                 db ? ; undefined
00000721                 db ? ; undefined
00000722                 db ? ; undefined
00000723                 db ? ; undefined
00000724                 db ? ; undefined
00000725                 db ? ; undefined
00000726                 db ? ; undefined
00000727                 db ? ; undefined
00000728                 db ? ; undefined
00000729                 db ? ; undefined
0000072A                 db ? ; undefined
0000072B                 db ? ; undefined
0000072C field_72C       db ?
0000072D field_72D       db ?
0000072E field_72E       db ?
0000072F field_72F       db ?
00000730 field_730       dd ?
00000734 field_734       dd ?
00000738 field_738       dd ?
0000073C field_73C       dd ?
00000740 field_740       dd ?
00000744 field_744       dd ?
00000748 field_748       dd ?
0000074C field_74C       dd ?
00000750 field_750       dd ?
00000754 field_754       db ?
00000755                 db ? ; undefined
00000756 field_756       dw ?
00000758 field_758       dd ?
0000075C                 db ? ; undefined
0000075D                 db ? ; undefined
0000075E                 db ? ; undefined
0000075F                 db ? ; undefined
00000760 field_760       db ?
00000761                 db ? ; undefined
00000762                 db ? ; undefined
00000763                 db ? ; undefined
00000764 field_764       dd ?
00000768 field_768       dd ?
0000076C                 db ? ; undefined
0000076D                 db ? ; undefined
0000076E                 db ? ; undefined
0000076F                 db ? ; undefined
00000770                 db ? ; undefined
00000771                 db ? ; undefined
00000772                 db ? ; undefined
00000773                 db ? ; undefined
00000774                 db ? ; undefined
00000775                 db ? ; undefined
00000776                 db ? ; undefined
00000777                 db ? ; undefined
00000778                 db ? ; undefined
00000779                 db ? ; undefined
0000077A                 db ? ; undefined
0000077B                 db ? ; undefined
0000077C                 db ? ; undefined
0000077D                 db ? ; undefined
0000077E                 db ? ; undefined
0000077F                 db ? ; undefined
00000780                 db ? ; undefined
00000781                 db ? ; undefined
00000782                 db ? ; undefined
00000783                 db ? ; undefined
00000784 field_784       dd ?
00000788 field_788       dd ?
0000078C field_78C       dd ?
00000790 field_790       dd ?                    ; float
00000794 m_sSpecialModelIndex dw ?
00000796                 db ? ; undefined
00000797                 db ? ; undefined
00000798 field_798       dd ?
0000079C CPed            ends
Ela está extremamente desatualizada... Paciência... Se você quer ela atualizada, veja aqui, mas neste caso não tem os offsets marcados, você vai ter que contar. Os "field_***" (como field_590) dão dicas.

Por exemplo, em CPed+0x548 nós temos o valor do colete:
Código:
00000548 armour          dd ?
Tá, mas como nós podemos ter acesso à uma "CPed"?

Código:
GET_PED_POINTER scplayer (pPed)
pPed += 0x548
READ_MEMORY pPed 4 FALSE (iArmour)
Ahhhhh... Agora comecei a falar a sua língua, né?

Originalmente na CLEO você tem os seguintes comandos:
Código:
GET_PED_POINTER // CPed
GET_VEHICLE_POINTER // CVehicle
GET_OBJECT_POINTER // CObject
Assim você pode pegar a class de algum CHAR, CAR ou OBJECT para ter acesso à várias (muitas!) informações extras para você usar nos seus mods.

Veja só: Em CPed+0x480 nós temos uma nova class:
Código:
00000480 pPlayerData     dd ?
Não está muito claro, mas se você ler este endereço (4 bytes) você vai receber um ponteiro para a CPlayerData.
Código:
GET_PED_POINTER scplayer (pPed)
pPed += 0x480
READ_MEMORY pPed 4 FALSE (pPlayerData)
Pronto, agora nós temos o início da CPlayerData na nossa variável "pPlayerData"!
E assim nós encontramos mais informações úteis:
Código:
00000000 CPlayerData     struc ; (sizeof=0xAC)
00000000 pWanted         dd ?
00000004 pClothesInfo    dd ?
00000008 field_8         dd ?
0000000C field_C         dd ?
00000010 field_10        dd ?
00000014 ?crimeSensitivity dd ?
00000018 fTimeCanRun     dd ?
0000001C field_1C        dd ?
00000020 field_20        db ?
00000021 field_21        db ?
00000022 __pad1          dw ?
00000024 ?Idle2StartScreenSaver dd ?
00000028 field_28        dd ?
0000002C field_2C        dd ?
00000030 field_30        dd ?
00000034 field_34        dd ?                    ; 2 - adrenaline flags; 0x100 - infinite breath
00000038 ?recruitesIndex dd ?
0000003C nAdrenalineTime dd ?
00000040 _isDrunk        db ?
00000041 field_41        db ?
00000042 field_42        db ?
00000043 field_43        db ?
00000044 fBreathMeter    dd ?
00000048 field_48        dd ?
0000004C field_4C        dd ?
00000050 field_50        dd ?
00000054 field_54        dd ?
00000058 field_58        dd ?
0000005C field_5C        dd ?
00000060 m_fMinigunRotation dd ?
00000064 field_64        dd ?
00000068 field_68        dd ?
0000006C field_6C        dd ?
00000070 field_70        dd ?
00000074 field_74        RwV3D ?
00000080 field_80        dd ?
00000084 field_84        db ?
00000085 field_85        db ?                    ; bUsingCellphone ?
00000086 field_86        db ?
00000087 field_87        db ?
00000088 field_88        dw ?
0000008A field_8A        dw ?
0000008C field_8C        db ?
0000008D field_8D        db ?
0000008E field_8E        db ?
0000008F field_8F        db ?
00000090 field_90        dd ?
00000094 field_94        dd ?
00000098 field_98        dd ?
0000009C lastModelShot   dd ?
000000A0 field_A0        dd ?
000000A4 field_A4        dd ?
000000A8 field_A8        dd ?
000000AC CPlayerData     ends
(CPlayerData atualizado aqui)
Se você ler pPlayerData+0x0 (ou seja, simplesmente o mesmo endereço, no mesmo ponteiro) você vai ler isto:
Código:
00000000 pWanted         dd ?
E assim nós encontramos o CWanted!
Código:
00000000 CWanted         struc ; (sizeof=0x29C)
00000000 Chaos           dd ?
00000004 field_4         dd ?
00000008 field_8         dd ?
0000000C timeWhenGotStars dd ?
00000010 field_10        dd ?
00000014 field_14        dd ?                    ; float
00000018 ncops           db ?
00000019 maxcops         db ?
0000001A nhelis          db ?
0000001B field_1B        db ?
0000001C field_1C        dw ?
0000001E field_1E        db ?
0000001F field_1F        db ?
00000020 field_20        dd ?
00000024 field_24        dd ?
00000028 field_28        dd ?
0000002C currentWantedLevel dd ?
00000030 maxWantedLevel  dd ?
00000034 cops            CWantedCops 16 dup(?)
000001F4 ?cops_vmt       dd 10 dup(?)
0000021C field_21C       dd ?
00000220 field_220       dd ?
00000224 field_224       dd ?
00000228 field_228       dd ?
0000022C field_22C       dd ?
00000230 field_230       dd ?
00000234 field_234       dd ?
00000238 field_238       dd ?
0000023C field_23C       dd ?
00000240 field_240       dd ?
00000244 field_244       dd ?
00000248 field_248       dd ?
0000024C field_24C       dd ?
00000250 field_250       dd ?
00000254 field_254       dd ?
00000258 field_258       dd ?
0000025C field_25C       dd ?
00000260 field_260       dd ?
00000264 field_264       dd ?
00000268 field_268       dd ?
0000026C field_26C       dd ?
00000270 field_270       dd ?
00000274 field_274       dd ?
00000278 field_278       dd ?
0000027C field_27C       dd ?
00000280 field_280       dd ?
00000284 field_284       dd ?
00000288 field_288       dd ?
0000028C field_28C       dd ?
00000290 field_290       dd ?
00000294 field_294       dd ?
00000298 field_298       dd ?
0000029C CWanted         ends
(CWanted atualizado aqui)

Você pode usar estes números para fazer checagens, e vários deles você pode editar para fazer alterações no gameplay.

Veja este script que lê o valor "ncops" (que é a quantidade de policiais te perseguindo) e mostra na tela:

Código copiável:

Código:
SCRIPT_START
{
LVAR_INT scplayer
LVAR_INT pPed pPlayerData pWanted pnCops iCops

GET_PLAYER_CHAR 0 scplayer

main_loop:
WAIT 0

GET_PED_POINTER scplayer (pPed)
pPlayerData = pPed + 0x480 // CPed.CPlayerData
READ_MEMORY pPlayerData 4 FALSE pPlayerData
pWanted = pPlayerData + 0x0 // CPlayerData.pWanted
READ_MEMORY pWanted 4 FALSE pWanted
pnCops = pWanted + 0x18 // CWanted.nCops
READ_MEMORY pnCops 1 FALSE (iCops)
PRINT_FORMATTED_NOW "Cops: %i" 1000 (iCops)

GOTO main_loop

}
SCRIPT_END
É claro, eu escrevi o código desta maneira para facilitar o entendimento.
Você pode otimizar para economizar variáveis e 1 linha:

Código copiável:

Código:
SCRIPT_START
{
LVAR_INT scplayer
LVAR_INT temp iCops

GET_PLAYER_CHAR 0 scplayer

main_loop:
WAIT 0

GET_PED_POINTER scplayer (temp)
temp += 0x480 // CPed.CPlayerData
READ_MEMORY temp 4 FALSE temp
//temp += 0x0 // CPlayerData.pWanted
READ_MEMORY temp 4 FALSE temp
temp += 0x18 // CWanted.nCops
READ_MEMORY temp 1 FALSE (iCops)
PRINT_FORMATTED_NOW "Cops: %i" 1000 (iCops)

GOTO main_loop

}
SCRIPT_END
Assim é um pouco menos organizado (por exemplo, você não guardou uma variável com o CPed, portanto você vai ter que pegar de novo caso precisar) mas mais aconselhável na maioria das vezes.

Os comentários que coloquei no script foram como se fosse uma "conversão" para o formato de linguagens de programação orientadas à objetos. Se você entende delas, conseguiu ter a noção do que nós fizemos aqui.
Chega a ser até engraçado, pois os mods cleos não são feitos em programações orientadas à objetos, mas a gente improvisa!


Se aprofundando

Vamos começar a complicar mais:
Código:
00000000 CPed            struc ; (sizeof=0x79C)
00000000 __parent        CPhysical ?
00000138 field_138       db 348 dup(?)           ; object_86C2A8
(...)
Veja que em CPed+0x0 nós temos um CPhysical, que é o "__parent" ("pai")

Isto não é um ponteiro para o CPhysical, se você pensou isso, preste mais atenção!

O CPhysical está dentro do CPed, perceba o offset do próximo field, é "0x138", ou seja, temos 0x138 (312) bytes ali!
Assim como não tem nenhum indicativo de que isso é um ponteiro nem nada, você tem que prestar atenção (eu já passei muitas horas de dor de cabeça por erros bobos assim)

Vamos ir no CPhysical ver o que temos lá:
Código:
00000000 CPhysical       struc ; (sizeof=0x138)
00000000 __parent        CEntity ?
00000038 field_38        dd ?
0000003C field_3C        dd ?
00000040 immunities      dd ?                    ; bit 22 - object immune to non player
00000044 m_vVelocity     CVector ?
00000050 m_vAngularVelocity RwV3D ?
0000005C m_vAcceleration RwV3D ?
00000068 m_vAngularAcceleration RwV3D ?
00000074 m_vForce        RwV3D ?
00000080 m_vTorque       RwV3D ?
0000008C m_fMass         dd ?                    ; mass ?
00000090 m_fTurnMass     dd ?                    ; turnMass ?
00000094 m_fVelocityFrequency dd ?               ; gripDivider ?
00000098 fAirResistance  dd ?                    ; massToGripMultiplier ?
0000009C m_fElasticity   dd ?
000000A0 m_fBuoyancyConstant dd ?                ; normalizedGrip ?
000000A4 field_A4        RwV3D ?
000000B0 field_B0        dd ?
000000B4 field_B4        dd ?
000000B8 field_B8        db ?
000000B9 field_B9        db ?
000000BA SurfaceType     db ?
000000BB field_BB        db ?
000000BC field_BC        dd 6 dup(?)
000000D4 field_D4        dd ?
000000D8 field_D8        dd ?
000000DC field_DC        dd ?
000000E0 field_E0        RwV3D ?
000000EC field_EC        RwV3D ?
000000F8 field_F8        dw ?
000000FA field_FA        dw ?
000000FC field_FC        dd ?
00000100 field_100       dd ?
00000104 field_104       dd ?
00000108 field_108       dd ?
0000010C field_10C       dd ?
00000110 field_110       dd ?
00000114 field_114       dd ?
00000118 field_118       dd ?
0000011C field_11C       dd ?
00000120 field_120       dd ?
00000124 field_124       dd ?
00000128 field_128       dd ?
0000012C field_12C       dd ?
00000130 field_130       dd ?
00000134 field_134       dd ?
00000138 CPhysical       ends
Vou parar de dar os links das classes atualizadas aqui; todas as classes atualizadas estão no repositório do DK22Pac! Nosso salvador! Dê uma olhada nos .h — se bem que os .cpp também podem ser interessantes para você
Perceba que nós temos mais outro parent! Agora o CEntity.
Código:
00000000 CEntity         struc ; (sizeof=0x38)
00000000 __parent        CPlaceable ?
00000018 m_pRWObject     dd ?                    ; offset
0000001C flags           dd ?                    ; flags: 23 - have skin; 7 - visible; 1 - collisions detected
00000020 RandomSeed      dw ?
00000022 m_wModelIndex   dw ?
00000024 m_reference     dd ?                    ; struct  offset
00000028 m_pLastRenderedLink dd ?                ; offset
0000002C field_2C        dw ?
0000002E field_2E        db ?
0000002F m_nbInterior    db ?
00000030 m_pLod          dd ?                    ; offset
00000034 m_nEntsIAmLodOf db ?
00000035 field_35        db ?
00000036 type            db ?                    ; object type (low 3 bits: 0 - object, 1 - building...)
00000037 field_37        db ?
00000038 CEntity         ends
E mais outro! CPlaceable.
Código:
00000000 CPlaceable      struc ; (sizeof=0x18)
00000000 __vmt           dd ?                    ; offset
00000004 stransform      CSimpleTransform ?
00000014 m_pMatrix       dd ?                    ; offset
00000018 CPlaceable      ends
Uffa, terminamos.
Você está entendendo onde estamos?
Tudo isso acima está dentro do CPed, logo no início dele.
É um pouco mindblow, mas se você ler 4 bytes de CPed+0x4, você encontrará a class CSimpleTransform:
Código:
00000000 CSimpleTransform struc ; (sizeof=0x10)
00000000 pos             RwV3D ?
0000000C angle           dd ?
00000010 CSimpleTransform ends
Certo, e logo no início não temos um ponteiro, mas sim um RwV3D (RenderWare Vector 3D) dentro do CSimpleTransform.
Código:
00000000 RwV3D           struc ; (sizeof=0xC)
00000000 x               dd ?
00000004 y               dd ?
00000008 z               dd ?
0000000C RwV3D           ends
Simplesmente um X Y Z...
E como chegar lá?
CPed+0x4
Sua mente já está com bug?
Entenda, nós só precisamos subir offset aqui:
Código:
00000004 stransform      CSimpleTransform ?
Nada mais, automaticamente chegamos no field "x" do RwV3D. Se você está perdido, leia atentamente o caminho que percorremos.

Curiosamente, aparentemente o CSimpleTransform não é utilizado aqui, o que não é comum de se ver — o mod Active Dashboard aproveita o não uso do CSimpleTransform para aplicar informações extras nos veículos, o que não é uma prática muito boa, mas enfim.

Ou seja, não adianta tentar ler, vai retornar "0.0".

Mas nós podemos testar isso lendo outra coisa lá atrás no CPhysical:
Código:
0000008C m_fMass         dd ?                    ; mass ?
Para chegarmos aí é só CPed+0x8C, simplesmente.

E assim nós podemos saber o peso do CJ:
Código:
GET_PED_POINTER scplayer (pPed)
pMass = pPed + 0x8C // CPed.CPhysical.m_fMass
READ_MEMORY pMass 4 FALSE (fMass)
Ele tem 70 kgs Dolan

Experimente escrever um valor alto, como 1000.0 e encostar num carro!
Ou abaixar um pouco. Fará o CJ pular mais alto e corrigirá a coisa irreal de "empurrar" carros com o corpo.

Num último exemplo, vamos no CVehicle:

https://pastebin.com/Fm3igq1v (tive que usar pastebin pois batia o limite do fórum)

É gigantesca!
E ainda, CVehicle é parent da CAutomobile:

https://pastebin.com/WQX5TynC

A CAutomobile tem um total de 2,44 KB.
GIGANTESCA.
Quando nós fazemos isso:
Código:
GET_VEHICLE_POINTER hCar (pVehicle)
Nós não estamos adquirindo somente a CVehicle, mas também a CAutomobile dele, assim como CPhysical, CEntity etc etc... etccc ETCCCCCC...

No CVehicle nós podemos por exemplo ter o ponteiro do handling do veículo:
Código:
00000384 pVehicleHandling dd ?                   ; offset
Veja que quando o valor é um ponteiro para outra class, o nome da field tem um "p" (ponteiro) no início, e/ou está escrito "offset", e/ou tem um asterisco "*", e, sempre o field tem 4 bytes (os ponteiros sempre têm 4 bytes!)

Basta nós lermos lá para ter as informações do handling, ou, mais especificamente, um CHandlingVehicle:
Código:
00000000 CHandlingVehicle struc ; (sizeof=0xE0)
00000000 index           dd ?
00000004 fMass           dd ?
00000008 field_8         dd ?                    ; 1/fMass
0000000C fTurnMass       dd ?
00000010 fDragMult       dd ?
00000014 centreOfMass    RwV3D ?
00000020 nPercentSubmerged db ?
00000021 field_21        db ?
00000022 field_22        db ?
00000023 field_23        db ?
00000024 field_24        dd ?                    ; fMass*0.8/(float)nPercentSubmerged
00000028 fTractionMultiplier dd ?
0000002C transmissionData dd 26 dup(?)           ; offset
00000094 fBrakeDeceleration dd ?
00000098 fBrakeBias      dd ?
0000009C bABS            db ?                    ; bool
0000009D field_9D        db ?
0000009E field_9E        db ?
0000009F field_9F        db ?
000000A0 fSteeringLock   dd ?
000000A4 fTractionLoss   dd ?
000000A8 fTractionBias   dd ?
000000AC fSuspensionForceLevel dd ?
000000B0 fSuspensionDampingLevel dd ?
000000B4 fSuspensionHighSpdComDamp dd ?
000000B8 fSuspensionUpperLimit dd ?
000000BC fSuspensionLowerLimit dd ?
000000C0 fSuspensionBiasBetweenFrontAndRear dd ?
000000C4 fSuspensionAntiDiveMultiplier dd ?
000000C8 fCollisionDamageMultiplier dd ?
000000CC modelFlags      dd ?
000000D0 handlingFlags   dd ?
000000D4 fSeatOffsetDistance dd ?
000000D8 nMonetaryValue  dd ?
000000DC frontLight      db ?
000000DD rearLight       db ?
000000DE animGroup       db ?
000000DF field_DF        db ?
000000E0 CHandlingVehicle ends
Ou seja, por exemplo, os freios:
Código:
00000094 fBrakeDeceleration dd ?
Para nós alterarmos os freios do nosso carro, basta:

Código copiável:

Código:
SCRIPT_START
{
LVAR_INT scplayer
LVAR_INT hCar pVehicle pHandling pBrakeDeceleration

GET_PLAYER_CHAR 0 scplayer

main_loop:
WAIT 0

IF TEST_CHEAT BRAKE
    IF IS_CHAR_SITTING_IN_ANY_CAR scplayer
        STORE_CAR_CHAR_IS_IN_NO_SAVE scplayer hCar
        GET_VEHICLE_POINTER hCar (pVehicle)
        pHandling = pVehicle + 0x384 // CAutomobile.CVehicle.pVehicleHandling
        READ_MEMORY pHandling 4 FALSE (pHandling) // CHandlingVehicle
        pBrakeDeceleration = pHandling + 0x94 // CHandlingVehicle.fBrakeDeceleration
        WRITE_MEMORY pBrakeDeceleration 4 0.0 FALSE
        PRINT_STRING_NOW "Ok" 1000
    ENDIF
ENDIF

GOTO main_loop

}
SCRIPT_END
No exemplo acima eu desativei totalmente os freios do veículo atual do player.
Detalhe sobre este exemplo: O handling dos veículos são compartilhados por modelo, portanto, se você ativou em um Elegy, todos os carros de modelo Elegy irão sofrer as alterações. Para corrigir isso é necessário usar IndieVehHandlings.cs (um cleo que vem em vários mods meus, como Tuning Mod e Real Traffic Fix). Neste caso, você pode simplesmente colocar um WAIT (para dar tempo do IndieVehHandlings fazer o trabalho), já deve servir, mas o mais aconselhável é usar uma função para checar se o ponteiro do handling recebeu o patch. Basta abrir o .cs com alguma versão mais atual do Sanny Builder que você terá muitas informações e códigos prontos, no entanto, até agora só no formato Sanny Builder.


Revisão e mais detalhes:

Código:
00000050 m_wTimesUsed    dw ?
50 — offset em hexadecimal.
m_wTimesUsed — nome da field, geralmente com letras dando dicas do seu conteúdo. Por exemplo se tem um "f" no início nós sabemos que é um float etc.
dw — a segunda letra indica a quantidade de bytes (BYTE, WORD, DWORD), como já foi explicado nas partes anteriores.
Código:
00000034 m_pHitColModel  dd ?                    ; CColModel *
O caractere "*", ou a palavra "offset", assim como o "p" no início do nome da field com tamanho de 4 bytes indicam que isso é um ponteiro para outra class.
Código:
000000AC field_AC        dd ?
O nome da field estando "field_{offset}" é porque simplesmente está sem nome (a comunidade não colocou ou simplesmente já colocaram mas a struct que você está olhando está desatualizada).
Lembre-se, 99,99% das fields são usadas no jogo por algum motivo. Esse monte de "field" pode ter coisas importantes, e, como eu disse, você pode ter as classes com nomes atualizados aqui.
Código:
00000074 m_vForce        RwV3D ?
A ausência de indicação de quantidade de bytes (e geralmente o próximo field estar mais do que 1, 2 ou 4 bytes à diante) indica que tem outra class dentro desta, não como ponteiro, mas simplesmente acoplada junto à ela.
Código:
000002B0 m_anPrimaryColors db 8 dup(?)
dup — indica um array, ou seja, não é só 1 elemento de 1 byte, mas sim, neste caso, 8 elementos de 1 byte. Neste exemplo específico (do CVehicle) é o offset para todas as 8 possíveis variações de cores primárias do veículo (perceba, os veículos suportam só 8 variações de cores!)
Código:
00000000 materials       dd ?                    ; RpMaterial **
Dois asteriscos juntos ("**") indicam um ponteiro para um ponteiro. Isso quer dizer que...
Código:
READ_MEMORY pointer 4 FALSE (pointer)
READ_MEMORY pointer 4 FALSE (value)

"Como eu obtenho um ponteiro para a class X?"
Isso varia demais, muito mesmo!
Geralmente, por base de uma class você encontra várias outras. Você tem que encontrar o caminho.
Muitas vezes elas estão em um endereço estático do .exe, como por exemplo a CCamera que sempre fica (literalmente) em 0xB6F028.

Certo, acredito que está bem explicado.


Download das structs:

Para você que não quer usar o IDA Pro, você pode baixar o IDA.txt que é um arquivo com a lista de todas as structs documentadas pela comunidade. Eu uso muitíssimo este arquivo!
Vou tentar deixá-lo atualizado como possível.
Há também o IDA - VC.txt que são as structs do GTA Vice City




Eu quero deixar claro que, se você acha isso poderoso, você tem razão. Na verdade, você ainda nem deve ter noção do real poder de saber fazer este tipo de coisa.
Com um simples GET_VEHICLE_POINTER é possível você até trocar texturas de um material específico do modelo do carro.
Praticamente (se não todos) os meus mods mais complexos/avançados usam isso... É ir além do normalmente acessível.

Você ter aprendido isso multiplicou (e muito) suas possibilidades de mods. Nós já estamos chegando ao fim das partes mais avançadas deste tutorial, você estando aqui já deve saber muita coisa!


Próxima parte:
(em breve)


Última edição por Junior_Djjr em Dom 06 Ago 2017, 18:05, editado 4 vez(es)

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22943
Reputação : 727
Desde : 03/05/2012
Idade : 22
Localização : Ibitinga - SP
Link : www.MixMods.com.br
Ver perfil do usuáriohttp://MixMods.com.br
em Dom 06 Ago 2017, 17:15
Eu acho que o modo que eu escrevi isso é interessante ler 2 vezes.

É que eu comecei somente explicando, e só na metade até o final foi deixando claro as coisas. Se reler pode ser que coisas do início-meio se tornem mais claras (além do fato de que é um assunto importante, merece atenção dobrada)

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Mensagens Nível 1
Mensagens Nível 1
Mensagens : 47
Reputação : 0
Desde : 12/12/2015
Ver perfil do usuário
em Seg 04 Set 2017, 20:04
Modificar o jogo por seus endereços de memórias, oh coisa boa... Quando tiver tempo irei voltar a ler os novos e antigos tutoriais de GTA3Script, ando muito ocupado pelo SA-MP xD!
Tutorial muito bom sobre as trevas do jogo, aquele lado obscuro kk.

______________________________
American State Roleplay
Conheça meu projeto para o SA-MP clicando na imagem acima ^ ^
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22943
Reputação : 727
Desde : 03/05/2012
Idade : 22
Localização : Ibitinga - SP
Link : www.MixMods.com.br
Ver perfil do usuáriohttp://MixMods.com.br
em Seg 11 Dez 2017, 00:53
Ninguém disposto à traduzir todo esse tutorial ao inglês?

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Mensagens Nível 1
Mensagens Nível 1
Mensagens : 8
Reputação : 0
Desde : 21/04/2018
Localização : Bangladesh
Link : gtaforums.com/uploads/profile/photo-1056481.jpg
Ver perfil do usuário
em Sab 12 Maio 2018, 12:25
@Junior_Djjr escreveu:Ninguém disposto à traduzir todo esse tutorial ao inglês?

It looks almost gd with google trnslate.read the full tutorial.Got some gramartical error in some points but fine.The pictures would need translation though.
Conteúdo patrocinado
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum