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 : 22944
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 Qua 26 Jul 2017, 18:34
Concluindo esta parte você irá:
Aprender a usar e saber dizer as utilidades do Thread Memory, mesmo que não aprenderá completamente todas as utilidades.

Já aprendeu sobre manipulação de memória? Já brincou um pouco? Que tal agora nos aprofundarmos um pouco mais?

Do mesmo modo que você pode ler/escrever memórias do jogo, você pode escrever memórias do seu próprio script... ou de tudo mais o que você imaginar.




Como criar "Thread Memory"

É super comum em códigos mais avançados serem criados os chamados por nós de "thread memory".

Thread memory é um espaço de dados que você reserva dentro do seu próprio script:

Pronto, isso é um thread memory.

O exemplo acima eu criei um thread memory de 4 x 4 bytes, ou seja, total de 16 bytes. Basta contar a quantidade de "00", onde cada "00" é 1 byte, né?

Organizei eles com 4 linhas de 4 bytes, não por questão de funcionamento, e sim por legibilidade / organização.
Ou seja, eu poderia ter organizado estes 16 bytes de qualquer maneira que ainda assim iria funcionar, mas eu organizei desta maneira (4 em cada linha) para ficar mais conveniente.

O que eu fiz aqui foi inserir um código hex dentro do meu próprio script. Mas por enquanto pense nisso simplesmente como "um espaço de memória onde podemos armazenar informações".

Veja um exemplo onde eu simplesmente escrevi o valor "100" nos primeiros 4 bytes daquela minha thread memory:

Agora, eu posso ir lá ler o valor novamente. Simples!

O princípio do thread memory é simplesmente isso.

E então? Eu tenho 4 linhas de 4 bytes, eu só usei uma. Como faço para usar as próximas linhas? Pense.

Olhe para o código, tente imaginar. Você deve saber.

(...)

Sim, simplesmente aumentando 4 bytes no endereço do thread memory para ir próxima linha, e mais 4 para ir pra próxima.
Assim podemos escrever diferentes números lá em diferentes linhas:

Leia atentamente a este exemplo acima pois ele é uma boa demonstração do que pode ser feito.


Utilidades

Certo, mas qual a real utilidade disso tudo?

Agora vamos focar mais nas utilidades e aprender mais na prática. Depois voltamos com mais explicações.

Manipulação de strings com mais de 16 bytes.

Um dos usos mais comuns é o uso de strings longas demais para caber em variáveis, assim, você pode improvisar:

(correção: é "$" não "&")

Este é um "hack" muito legal e útil. É simplesmente a criação de um buffer.
Código copiável:

Código:
SCRIPT_START
{
LVAR_INT pThreadMemory

GET_LABEL_POINTER Memory (pThreadMemory)

STRING_FORMAT (pThreadMemory) "O pato anda de costas quando o carro capota."

PRINT_STRING_NOW $pThreadMemory 5000
}
SCRIPT_END

Memory:
DUMP
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ENDDUMP
O que eu fiz foi pegar o endereço da thread memory, usar o comando STRING_FORMAT para escrever o valor lá, e, pronto. Agora eu posso usar a variável com o endereço como se fosse uma string. O que é bem interessante, não?

Perceba que no STRING_FORMAT você tem que colocar a variável de retorno no início e não no fim como você está acostumado, é porque é um comando da CLEO 4 e somos muito desorganizados!

Perceba também que não é sempre que você poderá usar strings desta forma. Há comandos que aceitam, e outros não.
Por exemplo você pode usar isso para o endereço do arquivo ao ler/escrever um arquivo .ini, mas, até o presente momento, a CLEO 4.3 não aceita usar para o nome da seção ou key do .ini.

Por último, saiba que o STRING_FORMAT adiciona um null terminator (00) no fim da string normalmente, você não precisa ter um "00" sobrando para isso. Por outro lado, cuidado! Se você tem uma thread memory de 16 bytes, se você escrever uma string de 16 caracteres lá, o null terminator será o 17º, assim sobrescrevendo o próximo byte do seu script!

Na real, com thread memory você pode ter strings de tamanhos ilimitados! — mas se o jogo / cleo aceita qualquer tamanho é outro assunto :)
Lembre-se que entradas GXT só suportam 128 bytes.

Abaixo, um exemplo disto para criar uma entrada GXT, e mostrá-la na tela por um comando que só aceita entrada GXT (DISPLAY_TEXT):


Resultado:


Veja o código copiável com comentários explicativos:
Código:
SCRIPT_START
{
LVAR_INT scplayer
LVAR_INT pThreadMemory
LVAR_FLOAT x y z

GET_PLAYER_CHAR 0 scplayer


main_loop:
WAIT 0

// Peguei a coordenada do player
GET_CHAR_COORDINATES scplayer (x y z)

// Peguei o ponteiro pra thread memory
GET_LABEL_POINTER Memory pThreadMemory

// Formatei uma string com os valores das coordenadas.
// Usei "%f" para indicar que quero adicionar um float ali.
// mais especificamente, "%.3f" para dizer que eu quero 3 números de precisão pra direita.
STRING_FORMAT (pThreadMemory) "%.3f %.3f %.3f" x y z

// Apliquei a string que criei. Agora quando eu usar a entrada GXT "TEMPGXT" vou ter o meu texto.
ADD_TEXT_LABEL (TEMPGXT) $pThreadMemory

// Apliquei algumas formatações de texto, para o texto aparecer mais bonito na tela.
SET_TEXT_CENTRE TRUE
SET_TEXT_CENTRE_SIZE 640.0
SET_TEXT_EDGE 1 (0 0 0 255)

// Mostrei a minha entrada GXT "TEMPGXT" na tela.
DISPLAY_TEXT (320.0 240.0) TEMPGXT

// Não podemos esquecer deste comando sempre que desenharmos coisas na tela em loop!
USE_TEXT_COMMANDS 0

GOTO main_loop
}
SCRIPT_END


Memory:
DUMP
// 32 Bytes
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
ENDDUMP

Isso não seria possível no jogo sem utilizar o thread memory, pois precisamos de uma variável com mais de 16 bytes para criar este texto com a coordenada. Neste caso, utilizei de uma thread memory com 32 bytes, ou seja, posso escrever até 31 letras lá (sombrando 1 "00" como null terminator).

Perceba que há um problema aqui:
Se você for numa coordenada MUITO longe, irá criar um número tão grande que ultrapassará os 32 bytes, assim sobrescrevendo o que está abaixo desta thread memory, e o que tem embaixo? No nosso código, nada, mas durante o gameplay, na sua memória RAM tem — sobrescreverá informações do jogo (acredito que informações desta ou outras threads), assim causando bugs e crashes, o chamado "stack overflow".


Variáveis extras

O jogo originalmente suporta somente 32 variáveis em threads externas (+2 timers). Mas tudo tem solução!

Importante: a ideia é que numa futura versão da CLEO exista um número ilimitado de variáveis possíveis. Quando isso acontecer, este tutorial será atualizado com o aviso. De qualquer modo, é importante e interessante você aprender.

Eu nem preciso explicar pois logo no início desta parte você já viu isso, só lembre-se: você pode guardar informações no script sem usar variáveis!

Mas vamos para um exemplo prático:


Este script cria 40 chars e guarda cada um deles na memória — não precisei guardá-los em variáveis!!! Bastou eu usar um espaço de 40 x 4 bytes.

(usei o comando "CREATE_RANDOM_CHAR" mas criou somente o MALE01.dff/txd pois apliquei o script sem esperar o jogo carregar os modelos de peds)

Agora eu posso criar uma outra função que pega novamente os chars que eu guardei lá na memória, e assim controlá-los novamente:

Estamos batendo recordes aqui! O maior e mais complexo script do tutorial, até agora. E mesmo assim você está conseguindo entender tudo, né?

Acredito que o CJ não gostou muito do exemplo...


Mas vamos entender o que diabos estamos fazendo:
Código:
SCRIPT_START
{
  LVAR_INT scplayer char chars_created i
  LVAR_FLOAT x y z y_distance

  GET_PLAYER_CHAR 0 scplayer

  main_loop:
  WAIT 0

  IF TEST_CHEAT CREATE
    y_distance = 1.0
    chars_created = 0
    WHILE chars_created < 40
      GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS scplayer (0.0 y_distance 0.0) (x y z)
      CREATE_RANDOM_CHAR (x y z) (char)
      CLEO_CALL StoreChar 0 (char, chars_created)
      y_distance += 1.0
      chars_created++
    ENDWHILE
  ENDIF

  IF TEST_CHEAT APPLY
    REPEAT 40 i
      CLEO_CALL GetChar 0 (i)(char)
      TASK_KILL_CHAR_ON_FOOT char scplayer
    ENDREPEAT
  ENDIF

  GOTO main_loop
}
SCRIPT_END

{
  LVAR_INT char // In
  LVAR_INT slot // In
  LVAR_INT memory offset

  StoreChar:
  GET_LABEL_POINTER Memory memory
  offset = slot * 4
  memory += offset
  WRITE_MEMORY memory 4 char FALSE
  CLEO_RETURN 0
}

{
  LVAR_INT slot // In
  LVAR_INT memory offset char

  GetChar:
  GET_LABEL_POINTER Memory memory
  offset = slot * 4
  memory += offset
  READ_MEMORY memory 4 FALSE (char)
  CLEO_RETURN 0 (char)
}


Memory:
DUMP
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
ENDDUMP
Quando eu digito "CREATE" o script entra em um loop criando e guardando 40 chars na memória.
Os chars são guardados na memória por uma função super simples:
Código:
{ // CLEO_CALL StoreChar 0 (char_handle, slot_id)()
  LVAR_INT char // In
  LVAR_INT slot // In
  LVAR_INT memory offset

  StoreChar:
  GET_LABEL_POINTER Memory memory
  offset = slot * 4
  memory += offset
  WRITE_MEMORY memory 4 char FALSE
  CLEO_RETURN 0
}
Você pode querer reutilizá-la em seus mods.

É fácil entender. Perceba que o "4" é a quantidade de bytes para cada "slot" (cada "espaço").
Código:
offset = slot * 4
Ou seja, se estou guardando um char no slot "0", fará "0 * 4", ou seja, guardará no espaço "memory + 0", ou seja, nos primeiros bytes da minha thread memory;
Se estou guardando no slot "1", fará "1 * 4", ou seja, o offset será "4", portanto guardará em "memory + 4", ou seja, na nossa segunda linha de bytes;
Se estou guardando no slot "2", fará "2 * 4", ou seja, "memory + 8", ou seja, na terceira linha de bytes.

É um sistema super simples de implementar!

Para pegar o char devolta, é só fazer a exata mesma coisa, mas, ao invés de escrever, vamos ler e retornar o valor:
Código:
{ // CLEO_CALL GetChar 0 (slot_id)(char_handle)
  LVAR_INT slot // In
  LVAR_INT memory offset char

  GetChar:
  GET_LABEL_POINTER Memory memory
  offset = slot * 4
  memory += offset
  READ_MEMORY memory 4 FALSE (char)
  CLEO_RETURN 0 (char)
}

Viu o que conseguimos fazer aqui? Nós criamos e temos o controle de 40 chars, sem gastar variáveis! Todos eles estão seguros, guardados na memória, onde a qualquer momento você pode ir lá pegá-los.


Valores compartilhados globalmente

Em mods grandes, é muito comum isso ser usado.

A explicação é simples: Os valores estão guardados na memória, e você tem acesso ao endereço daquele local... Você pode ler e escrever valores lá de onde você estiver.

Um dos exemplos é o meu mod MDPMv5, onde eu utilizo vários scripts que se comunicam entre si... ...por thread memory!

Eu utilizo um script chamado por mim de "raiz", onde lá você ativa, e quando ativa, o carro é guardado na memória (para no futuro eu saber se aquele carro já está ativo ou não), e um novo script diferente é chamado. No novo script, eu recebo o endereço da thread memory onde está guardado todos os carros ativos. Quando eu desativo um tal carro, o script do carro remove ele mesmo da memória.
Também neste script raiz eu armazeno informações globais, como qual é o atual carro que você está com o "controle remoto" selecionado, e cada script de cada carro também tem acesso à mesma thread memory com este valor lá para saber se o atual "controle remoto" é o tal carro ou não.
O MDPMv5 é um exemplo tão bom, que, para você ter noção, eu uso até thread memory para guardar ponteiros para outras thread memories. É louco.
Nota: o mesmo poderia ser feito pelas chamadas "CLEO VARS" (comandos SET_CLEO_SHARED_VAR e GET_CLEO_SHARED_VAR) mas elas são limitadas e pode causar conflitos entre mods que também usam, portanto eu não gosto de usá-las.

Também há outros modos, como usar manipulamento de memória para um script ler as variáveis de outro (quando estamos falando de manipulamento de memória, tudo é possível, meu jovem), mas, também, eu prefiro sempre por thread memory, por ser mais simples, dinâmico...

E não só entre scripts, mas, simplesmente, CLEO_CALLs, diferentes escopos etc.

E como sempre, eu tenho exemplos:
Em todos os mods que eu já fiz onde são multilíngues, eu fiz do mesmo modo:

Tenho uma função que lê o idioma configurado no arquivo .ini:


Outra que pega o valor armazenado e checa se é tal:


Assim, basta eu simplesmente chamar esta função com um IF para checar se é o tal idioma:


O ponto é: o valor ID do idioma está armazenado na memória, e não numa variável, portanto, eu posso fazer a checagem de idioma em absolutamente qualquer lugar do script!


Sinta-se livre!

Você pode criar Buffer, simular Class, criar Tables ou simplesmente guardar 1 byte de alguma informação para ser lido depois.

Em assunto de thread memory, você tem que se sentir totalmente livre.


Entenda o que temos aqui:
Nós temos, não só um espaço para armazenar informações, mas um código escrito em hexadecimal dentro do nosso script! (simplesmente, vários bytes de dados).

Você pode até mesmo pegar todo o hexadecimal de um arquivo de áudio e adicionar dentro de um DUMP...ENDDUMP, quando necessário, você pode fazer seu script criar um novo arquivo e escrever todo o conteúdo daquele thread memory dentro do arquivo que você criou. Pronto! Seu script criou um arquivo de áudio! É como se você tivesse acoplado um arquivo dentro do seu .cs.

Mas uma das coisas mais fodas que podemos fazer é adicionar códigos de outras programações dentro do seu script cleo, e neste caso, o Fabio nos fez este tutorial, onde inclui um auxiliador criado por ele: http://brmodstudio.forumeiros.com/t4721-avancado-facilitador-de-conversao-de-c-para-assembly-para-usar-em-scripts-cleo-scm

Veja por exemplo o script do mod Dynamic Tram Signs do Wesser (escrito no Sanny Builder, mas em GTA3script ficaria quase igual):
https://pastebin.com/QE4spHk1

Você pode até criar scripts inteiros com thread memory. Na real, se você pegar todo o hexadecimal de um arquivo .cs e colocar dentro de um novo script com nenhum comando, somente uma thread memory, e irá funcionar.

Veja este exemplo não muito útil, mas interessante:
Código:
SCRIPT_START
{
NOP

main_loop:
WAIT 0

IF IS_KEY_PRESSED VK_KEY_Y
  DUMP
  CD 0A 0E 08 55 6D 20 70 61 74 6F 2E 05 88 13
  ENDDUMP
ENDIF

GOTO main_loop
}
SCRIPT_END
O código hexadecimal
Código:
CD 0A 0E 08 55 6D 20 70 61 74 6F 2E 05 88 13
é o equivalente a:
Código:
PRINT_STRING_NOW "Um pato." 5000

Veja:
CD 0A = Opcode "0ACD:" que indica o "PRINT_STRING_NOW" (quem mexe com Sanny Builder está acostumado com isso!)
0E = Data type do próximo argumento ("long string")
08 = Quantidade de bytes da nossa long string.
55 6D 20 70 61 74 6F 2E = Caracteres da string "Um pato." (perceba que não tem null terminator (00) pois quem diz a quantidade de bytes da string é o "08" acima, portanto, null terminator aqui seria inútil.
05 = Data type do próximo argumento ("integer")
88 13 = Valor "5000" — Experimente colocar "13 88" na calculadora do Windows no modo "Programador" com "HEX" selecionado e olhe no "DEC", você verá o valor "5000"!

Perceba que nós começamos este tutorial com uma coisa super-ultra-extremamente simples, e olha até onde chegamos...

Thread memory vai desde uma "variável extra" a até acoplar arquivos e códigos de outra programação dentro do seu script. É uma coisa que você provavelmente usará tanto em mods complexos, quanto em mods mais simples.




Próxima parte:
Classes


Última edição por Junior_Djjr em Dom 06 Ago 2017, 17:09, editado 3 vez(es)

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 19290
Reputação : 384
Desde : 04/05/2012
Idade : 21
Link : gtamodvicio.blogspot.com
Ver perfil do usuáriohttp://gtamodvicio.blogspot.com
em Qua 26 Jul 2017, 18:54


Não tem algo errado aqui? philosoraptor

______________________________

Modifico quase qualquer coisa.   :)
------------------>>>http://gtamodvicio.blogspot.com/<<<------------------

Meu PC:
Spoiler:

Configurações PC:
*Processador: Intel Core i7 4790K 4.00GHz LGA1150
*Placa Mãe: GIGABYTE GA-H97M-D3H Intel (LGA1150)
*HD: 1TB Seagate Barracuda 64MB Sata III 7200RPM (2x - RAID 0)
*HD²: SAMSUNG M3 Externo USB 5400RPM 1TB
*Placa de vídeo: Nvidia GTX660 2GB DDR5 192bit EVGA
*RAM: 8GB DDR3 1600MHZ Kingston HYPER X BEAST (2x4GB)
*Fonte: Corsair 600W Reais CX600M Modular - CP-9020060-WW (80 Plus Bronze)
*Gabinete: Gabinete Raidmax Super Hurricane Branco - 248WB
*Monitor: LG 23MP55HQ Full HD HDMI 23'
avatar
Scripter CLEO - Básico
Scripter CLEO - Básico
Mensagens : 981
Reputação : 36
Desde : 13/08/2015
Idade : 13
Localização : Passo de Torres - SC
Ver perfil do usuário
em Qua 26 Jul 2017, 19:37
O erro é que ele não deveria ter aumentado 4 bytes pra escrever o valor "100", né?

______________________________
Se eu te ajudei em algo, clique no botão de reputação (o "coraçãozinho" na parte de cima da mensagem).
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 Qua 26 Jul 2017, 19:39
@Fabio escreveu:Não tem algo errado aqui? philosoraptor
Opa, não era pra ter o primeiro += 4 :v:
Corrigi.

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Mensagens : 846
Reputação : 134
Desde : 22/09/2015
Ver perfil do usuário
em Qua 26 Jul 2017, 19:40
@Matheus Rivaldo escreveu:O erro é que ele não deveria ter aumentado 4 bytes pra escrever o valor "100", né?
Exato. :v:

______________________________
Everyone gonna remember my name !
avatar
Scripter CLEO - Intermediário
Scripter CLEO - Intermediário
Título : Carinha que mora logo ali
Mensagens : 758
Reputação : 158
Desde : 07/03/2017
Localização : BH - MG
Link : https://gta-geek.blogspot.com.br/
Ver perfil do usuáriohttps://gta-geek.blogspot.com.br/
em Qua 26 Jul 2017, 20:09
Isto é mais útil e mais fácil do que parece (acho que quem me apresentou isto foi o @Fabio até)
Já me salvou varias vezes estes 00 00 00 00 :)

Até aprendi sobre allocate_memory, mas prefiro este método.
avatar
Scripter CLEO - Básico
Scripter CLEO - Básico
Mensagens : 71
Reputação : 10
Desde : 08/06/2017
Idade : 18
Localização : São Gabriel - RS
Ver perfil do usuário
em Qua 26 Jul 2017, 20:14
Caramba, os Programadores veem a palavra limite e riem.
vamos deixar o limite em aberto, quando atingirmos o limite dobraremos o limite

______________________________
Certa vez perguntaram ao Dalai Lama:
Oque mais te decepciona em Custom Scripts ?
E ele respondeu:
reached maximum local variable limit (32).
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 Qua 26 Jul 2017, 20:41
@Um Geek escreveu:Até aprendi sobre allocate_memory, mas prefiro este método.
Nem toquei nesse assunto, porque é difícil alguém preferir isso. Isso é até assunto de necessidade e não preferência.

Esse método é aconselhável para coisas maiores e principalmente variáveis, por exemplo:

Imagine que você esteja carregando todos os arquivos .txt de uma pasta para a memória. Você tem um número variável de arquivos, pode ter 5 ou 10... ou 50, então é interessante você usar este método, pois você pode ir alocando mais memória quando necessário, até acabar a RAM disponível :v: e depois, quando não precisar mais, liberar (FREE).

No thread memory é diferente pois você tem uma quantidade fixa de bytes disponíveis. Os bytes estão lá dentro do .cs (e serão "copiados" para a memória RAM). Se você cria um thread memory de 128 bytes, quer dizer que seu script estará 128 bytes mais "pesado" pra memória RAM... Porra, o que são 128 bytes?

Ou seja, é raro alguém precisar disso (eu mesmo, juro, só usei isso 1 vez na vida, e nem foi o comando da CLEO, foi a função direta no .exe mesmo). Isso pode ser pra algum tutorial mais no futuro.

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Mensagens : 846
Reputação : 134
Desde : 22/09/2015
Ver perfil do usuário
em Qua 26 Jul 2017, 21:17
@Junior_Djjr escreveu:[...] Isso é até assunto de necessidade e não preferência. [...]
Como é o caso do meu Veh Renamer, que não dá para pressupor o conteúdo do arquivo .fxt. Sendo assim não é possível usar "thread memory", tendo de optar por alocação.

SB Code :
Código:
{$Cleo}  
/* Veh Renamer
            By : Israel */                                
const
    NULL 0x00
    isnumpad 10@
    spacerep 15@
    renamer_Flag 20@v

    VK_BACK 0x08    
    VK_RETURN 0x0D    
    VK_SHIFT 0x10    
    VK_CAPITAL 0x14        
  
    cheat_string 0x969110    

    CPad__AddToCheatString 0x438480
    StartNewScript 0x464C20
    GetKeyState 0x81E64C
    strlen 0x826330
    strcmp 0x8263C0  
end

if 8AF4: renamer_Flag = read_string_from_ini_file "Cleo\Renamer.ini" section "Settings" key "Rename Command"
then
    renamer_Flag = "Rename" // default
end

0AB1: call_scm_func @StartNewThread 1 labelName @NumpadCheats
                                            
while true
    wait 0  

    if and
        0ADC:   test_cheat renamer_Flag
        Actor.Driving($Player_Actor)
    jf continue
    
    25@ = 0x36
    
    Player.CanMove(0, 0)  
    0AC6: 0@ = label @Buffer offset // pTempbuffer
    0A8E: 25@ = 0@ + 25@ // pMainbuffer
  
    repeat
        wait 0

        0A8D: 1@ = read_memory cheat_string size 1 virtual_protect 0
        
        if and
        1@ >= 0x30
        1@ <= 0x39
        8AB0:   not key_pressed 1@
        then
            1@ += 0x30 // to key
            isnumpad = true
        else
            isnumpad = false    
        end

        if 0AB0:   key_pressed 1@
        then                          
            0AB1: call_scm_func @KeyWait 1 key1 1@

            if isnumpad == true
            then
                1@ -= 0x30 // to char
            end

            0AA7: call_function GetKeyState num_params 1 pop 0 VK_CAPITAL -> 2@

            if 1@ == 0x20
            then          
                1@ = 0xFF // spaces do hide the text on the screen
                spacerep = true
            end

            if or
            1@ < 0x30
            1@ > 0x39
            then
                if and
                2@ == 0
                8AB0:   not key_pressed VK_SHIFT              
                then
                    1@ += 0x20 // lowercase  
                end
            end
                        
            if 3@ < 40 // max_length
            then
                0A8C: write_memory 0@ size 1 value 1@ virtual_protect 0
                0@++
                if spacerep == true
                then
                    0A8C: write_memory 25@ size 1 value 0x20 virtual_protect 0
                    spacerep = false
                else
                    0A8C: write_memory 25@ size 1 value 1@ virtual_protect 0                
                end
                25@++                
            end          
        end
        
        0AC6: 2@ = label @Buffer offset
        0AA7: call_function strlen num_params 1 pop 1 2@ -> 3@
      
        if 0AB0:   key_pressed VK_BACK
        then
            if 3@ > 0
            then
                0@--
                25@--
                0A8C: write_memory 0@ size 1 value NULL virtual_protect 0                
                0A8C: write_memory 25@ size 1 value NULL virtual_protect 0            
            else
                break
            end    
        end
        0AB1: call_scm_func @KeyWait 1 key1 VK_BACK
        
        0AD1: show_formatted_text_highpriority "~g~Nome: ~s~%s" time 250 2@
    until 0AB0:   key_pressed VK_RETURN
    
    if 3@ > 0
    then        
        0@ = Actor.CurrentCar($Player_Actor)
        
        0@ = Car.Model(0@)
        0ADB: 0@s = car_model 0@ name
        
        2@ += 0x36 // pMainbuffer
          
        3@ = File.Open("Cleo\Cleo_Text\Renamer.fxt", "r")
        
        0A9C: 4@ = file 3@ size
        4@ += 50 // max_length per line
        
        0AC8: 5@ = malloc 4@
        0A8C: write_memory 5@ size 4@ value NULL virtual_protect 0
        
        6@ = 0x36
        0A8E: 6@ = 2@ + 6@ // pFxtLinebuffer
        
        while File.ReadString(3@, 6@, 50)
            0AD4: 33@ = scan_string 6@ format "%s" 7@s // split first word

            0AA7: call strcmp num_params 2 pop 2 0@s 7@s -> 9@
            
            if 9@ <> 0
            then
                0AD3: 5@ = format "%s%s" 5@ 6@
            end                  
        end

        33@ = 0x0A // LF
        0AD3: 5@ = format "%s%s %s%s" 5@ 0@s 2@ 33@s

        File.Close(3@)
                                    
        10@ = File.Open("Cleo\Cleo_Text\Renamer.fxt", "w")        
        File.WriteString(10@, 5@)
        
        File.Close(10@)
        0AC9: free 5@
        
        2@ -= 0x36
        0A8C: write_memory 2@ size 120 value NULL virtual_protect 0 // clear main/temp buffers
        
        0ACD: show_text_highpriority "~g~Renomeado." time 1000
    else
        0ACD: show_text_highpriority "~r~Cancelado." time 1000
    end
    
    0AB1: call_scm_func @KeyWait 1 key1 VK_RETURN
    Player.CanMove(0, 1)
end

:StartNewThread
0AC6: 1@ = label 0@ offset
0AA7: call_function StartNewScript num_params 1 pop 1 1@ -> 2@
  
2@ += 0x10 // CRunningScript->baseIp

005A: 1@ += 0@
0A8C: write_memory 2@ size 4 value 1@ virtual_protect 0  
2@ += 0xB7    
0A8C: write_memory 2@ size 1 value 1 virtual_protect 0

0AB2: ret 0

:NumpadCheats
0AAA: 0@ = thread 'nCheats' pointer

if or
0@ <> NULL
0AAB:   file_exists "Cleo\CPad.DoCheats_Numpad_and_KeyPressedFlag.cs"
then
    end_thread // do not duplicate numpad cheats
end

thread 'nCheats'
while true
    wait 0
      
    for 1@ = 0x60 to 0x69    
        0AB0:   key_pressed 1@
        jf continue
        
        0A8F: 2@ = 1@ - 0x30              
        0AA5: call_function CPad__AddToCheatString num_params 1 pop 1 2@
        0AB1: call_scm_func @KeyWait 1 key1 1@                
    end
end

:KeyWait
repeat
    while 0AB0:   key_pressed 0@(31@,1i)
        wait 0
    end    
    31@++
until 0@(31@,1i) == NULL

0AB2: ret 0

:Buffer
hex
// temp buffer
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// main buffer
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// fxt_line buffer
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
end      

______________________________
Everyone gonna remember my name !
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 10511
Reputação : 265
Desde : 08/11/2012
Ver perfil do usuário
em Qui 27 Jul 2017, 03:53
Por que não implementar uma extensão pra alocar essa memória estática com uma sintaxe familiar, em vez de meter um monte de zero? Algo como:

Código:
Memory:
DUMP(16) 00 ENDDUMP

Ou até:

Código:
Memory:
DUMP
RESERVE(16)
ENDDUMP

@LINK/2012
Eu posso forkar o negócio e implementar isso eu mesmo?
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 Qui 27 Jul 2017, 04:24
↑ Isso seria bom.
E o DUMP é coisa à parte do GTA3script original da Rockstar, então acredito que não há "regras" de implementação.

Ah, e fale direto com o LINK no face, melhor.

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Scripter CLEO - Intermediário
Scripter CLEO - Intermediário
Mensagens : 1241
Reputação : 99
Desde : 04/03/2013
Idade : 18
Ver perfil do usuário
em Qui 27 Jul 2017, 15:16
@Thelost escreveu:
Código:
Memory:
DUMP
RESERVE(16)
ENDDUMP
Curti mais esse.
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 Qui 27 Jul 2017, 17:02
Thelost, você que curte tanto programação, tente continuar umas coisas que o LINK/2012 não fez por falta de tempo.
Falta, por exemplo, implementar a possibilidade de escrever strings dentro do DUMP...ENDDUMP
Código:
DUMP
"STRING" 00
ENDDUMP
(sinto falta disto)

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 19290
Reputação : 384
Desde : 04/05/2012
Idade : 21
Link : gtamodvicio.blogspot.com
Ver perfil do usuáriohttp://gtamodvicio.blogspot.com
em Qui 27 Jul 2017, 18:00
Nex' escreveu:
@Thelost escreveu:
Código:
Memory:
DUMP
RESERVE(16)
ENDDUMP
Curti mais esse.

Seria bom especificar o número a ser preenchido.
Código:

RESERVE(16, 0x00)
RESERVE(16, 0xFF)

______________________________

Modifico quase qualquer coisa.   :)
------------------>>>http://gtamodvicio.blogspot.com/<<<------------------

Meu PC:
Spoiler:

Configurações PC:
*Processador: Intel Core i7 4790K 4.00GHz LGA1150
*Placa Mãe: GIGABYTE GA-H97M-D3H Intel (LGA1150)
*HD: 1TB Seagate Barracuda 64MB Sata III 7200RPM (2x - RAID 0)
*HD²: SAMSUNG M3 Externo USB 5400RPM 1TB
*Placa de vídeo: Nvidia GTX660 2GB DDR5 192bit EVGA
*RAM: 8GB DDR3 1600MHZ Kingston HYPER X BEAST (2x4GB)
*Fonte: Corsair 600W Reais CX600M Modular - CP-9020060-WW (80 Plus Bronze)
*Gabinete: Gabinete Raidmax Super Hurricane Branco - 248WB
*Monitor: LG 23MP55HQ Full HD HDMI 23'
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 10511
Reputação : 265
Desde : 08/11/2012
Ver perfil do usuário
em Qui 27 Jul 2017, 18:48
@Fabio escreveu:
Seria bom especificar o número a ser preenchido.
Código:

RESERVE(16, 0x00)
RESERVE(16, 0xFF)

Aí seria FILL, RESERVE significa deixar um espaço válido ali.
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 19290
Reputação : 384
Desde : 04/05/2012
Idade : 21
Link : gtamodvicio.blogspot.com
Ver perfil do usuáriohttp://gtamodvicio.blogspot.com
em Qui 27 Jul 2017, 19:39
@Thelost escreveu:
@Fabio escreveu:
Seria bom especificar o número a ser preenchido.
Código:

RESERVE(16, 0x00)
RESERVE(16, 0xFF)

Aí seria FILL, RESERVE significa deixar um espaço válido ali.

Ah sim, verdade.

Aproveitando o post, eu atualizei o tópico: http://brmodstudio.forumeiros.com/t4721-avancado-facilitador-de-conversao-de-c-para-assembly-para-usar-em-scripts-cleo-scm

______________________________

Modifico quase qualquer coisa.   :)
------------------>>>http://gtamodvicio.blogspot.com/<<<------------------

Meu PC:
Spoiler:

Configurações PC:
*Processador: Intel Core i7 4790K 4.00GHz LGA1150
*Placa Mãe: GIGABYTE GA-H97M-D3H Intel (LGA1150)
*HD: 1TB Seagate Barracuda 64MB Sata III 7200RPM (2x - RAID 0)
*HD²: SAMSUNG M3 Externo USB 5400RPM 1TB
*Placa de vídeo: Nvidia GTX660 2GB DDR5 192bit EVGA
*RAM: 8GB DDR3 1600MHZ Kingston HYPER X BEAST (2x4GB)
*Fonte: Corsair 600W Reais CX600M Modular - CP-9020060-WW (80 Plus Bronze)
*Gabinete: Gabinete Raidmax Super Hurricane Branco - 248WB
*Monitor: LG 23MP55HQ Full HD HDMI 23'
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 10511
Reputação : 265
Desde : 08/11/2012
Ver perfil do usuário
  • Reputação da mensagem: 100% (2 votos)
em Qui 27 Jul 2017, 22:28
@Junior_Djjr escreveu:Thelost, você que curte tanto programação, tente continuar umas coisas que o LINK/2012 não fez por falta de tempo.
Falta, por exemplo, implementar a possibilidade de escrever strings dentro do DUMP...ENDDUMP
Código:
DUMP
"STRING" 00
ENDDUMP
(sinto falta disto)

https://github.com/thelink2012/gta3sc/pull/116
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 Sex 28 Jul 2017, 17:00
Boa.
E esqueci dessa coisa de especificar o valor que o Fabio falou, é útil também.
Por exemplo se você quer guardar handle dos carros, você tem que usar FF para dizer "vazio", pois o handle do primeiro carro que aparecer no jogo terá o valor "0", se você tratar "0" como vazio, vai bugar pro primeiro carro que aparecer no jogo.

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Scripter CLEO - Básico
Scripter CLEO - Básico
Mensagens : 981
Reputação : 36
Desde : 13/08/2015
Idade : 13
Localização : Passo de Torres - SC
Ver perfil do usuário
em Sex 28 Jul 2017, 17:13
Aproveitando o tópico: Junior, você pensa em fazer um tutorial novo de engenharia reversa, para os novos programadores de GTA3Script que não entendem a sintaxe do Sanny Builder?

______________________________
Se eu te ajudei em algo, clique no botão de reputação (o "coraçãozinho" na parte de cima da mensagem).
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 Sex 28 Jul 2017, 17:16
@Matheus Rivaldo escreveu:Junior, você pensa em fazer um tutorial novo de engenharia reversa, para os novos programadores de GTA3Script que não entendem a sintaxe do Sanny Builder?
E mudaria o quê?
O tutorial de engenharia reversa tem o objetivo de usar o IDA Pro para encontrar endereços de memória, só.

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 10511
Reputação : 265
Desde : 08/11/2012
Ver perfil do usuário
em Sex 28 Jul 2017, 18:18
@Junior_Djjr escreveu:Boa.
E esqueci dessa coisa de especificar o valor que o Fabio falou, é útil também.
Por exemplo se você quer guardar handle dos carros, você tem que usar FF para dizer "vazio", pois o handle do primeiro carro que aparecer no jogo terá o valor "0", se você tratar "0" como vazio, vai bugar pro primeiro carro que aparecer no jogo.

Eu deixei um issue aqui, tou com preguiça de fazer, outra hora faço.
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 30 Jul 2017, 04:38
E foi fechado. Até justo mesmo...

Vamos esperar pelo aumento das variáveis, uma coisa que vai mudar muita coisa no nosso modo de criar os mods.

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Scripter CLEO - Intermediário
Scripter CLEO - Intermediário
Mensagens : 1241
Reputação : 99
Desde : 04/03/2013
Idade : 18
Ver perfil do usuário
em Seg 31 Jul 2017, 22:34
No exemplo do buffer você usou & invés de $. Confundiu com o reference operator do C++, né?
avatar
Scripter CLEO - Avançado
Scripter CLEO - Avançado
Título : Censurando since 2011
Mensagens : 22944
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 Ter 01 Ago 2017, 05:20
Nex' escreveu:No exemplo do buffer você usou & invés de $. Confundiu com o reference operator do C++, né?
Ops :)

Eu também faço esse erro enquanto codando... Ainda mais pelo costume do Sanny Builder que me fez ver "$" como uma coisa errada.

______________________________
BMS agora em nova plataforma:
Forum.MixMods.com.br
avatar
Programador - Avançado
Programador - Avançado
Mensagens : 19290
Reputação : 384
Desde : 04/05/2012
Idade : 21
Link : gtamodvicio.blogspot.com
Ver perfil do usuáriohttp://gtamodvicio.blogspot.com
em Ter 01 Ago 2017, 12:28
@Junior_Djjr escreveu:Ainda mais pelo costume do Sanny Builder que me fez ver "$" como uma coisa errada.

Não vai chegar perto do PHP então Fuch That Guy

______________________________

Modifico quase qualquer coisa.   :)
------------------>>>http://gtamodvicio.blogspot.com/<<<------------------

Meu PC:
Spoiler:

Configurações PC:
*Processador: Intel Core i7 4790K 4.00GHz LGA1150
*Placa Mãe: GIGABYTE GA-H97M-D3H Intel (LGA1150)
*HD: 1TB Seagate Barracuda 64MB Sata III 7200RPM (2x - RAID 0)
*HD²: SAMSUNG M3 Externo USB 5400RPM 1TB
*Placa de vídeo: Nvidia GTX660 2GB DDR5 192bit EVGA
*RAM: 8GB DDR3 1600MHZ Kingston HYPER X BEAST (2x4GB)
*Fonte: Corsair 600W Reais CX600M Modular - CP-9020060-WW (80 Plus Bronze)
*Gabinete: Gabinete Raidmax Super Hurricane Branco - 248WB
*Monitor: LG 23MP55HQ Full HD HDMI 23'
Conteúdo patrocinado
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum