Jump to content

SA Memory handling


Seemann

Recommended Posts

You could not pass a string parameter to the thread.

 

 

create_thread @CLV thread_name 'vchng'

 

This is the problem. Pass the string array index, or a label where the string's stored:

 

 

:mystringhex"vchng" 00end

 

Link to comment
Share on other sites

I've tried this:

:debug_var_testthread 'VCHNG'2@ = 2create_thread @CLV thread_name @mystring local_num 2 set_value 40wait 2000054C: use_GXT_table 'POOL'01E3: text_1number_styled 'NUM' 2@ 5000 ms 1  // ~1~end_thread:mystringhex"vchng" 00end

 

 

But it didn't work. confused.gif

I also tried to be smartass and do this:

:debug_var_testthread 'VCHNG'2@ = 205AA: 1@s = 'vchng' // 8-byte strings create_thread @CLV thread_name 1@s local_num 2 set_value 40wait 2000054C: use_GXT_table 'POOL'01E3: text_1number_styled 'NUM' 2@ 5000 ms 1  // ~1~end_thread

 

 

And it output weird results; depending on the value, it either crashes, or successfully modifies the thread's local var, but always to '103'. :\

 

Please be more detailed in the next reply since I didn't really get everything, what do you mean about array index? Use a global array with strings, and pass the index to the wanted string, maybe? Well I want to use Darkpact so I can't use globals, which is a major reason to use the CLV thread in the first place. Actually, thinking about it, I'm an idiot, I don't think Darkpact even works with Sanny... sucks.

Link to comment
Share on other sites

Yes, I mean the global array as it's the way it may work. But if you dont want to use it, there's another way:

 

 

:CLV{ 0@ thread_name index at @Thread_Names  1@ local var num to modify 2@ value to set to var} 03A4: name_thread 'CLV'0006: 3@ = 67251:CLV_LOOP008B: 3@ = &0(3@,1i)00D6: if8039:   not  3@ == 0004D: jump_if_false @CLV_END// 0001: wait 0 // not necessary0085: 4@ = 3@0016: 4@ /= 8000E: 4@ -= 13483950016: 3@ /= 4000E: 3@ -= 269679200D6: if// 05AD: &0(4@,1s) == &@Thread_Names(0@,1s)hexAD05           // opcode      (05AD)0C             // data type0000           // array name  (&0)0400           // index name  (4@)0102           // size&type0C             // data type@Thread_Names  // array name&index name (0@)0102           // size&typeend004D: jump_if_false @CLV_LOOP//add to 3@ (local var num + 15)000A: 1@ += 15005A: 3@ += 1@008A: &0(3@,1i) = 2@:CLV_END004E: end_thread// thread names, all of 8 bytes:Thread_Nameshex"vchng" 00 00 00 // 8 bytes"vchng2" 00 00   // 8 bytesend

 

 

 

and example:

 

 

:TEST1thread 'VCHNG'2@ = 2create_thread @CLV thread_name_index 0 local_num 2 set_value 12wait 2000054C: use_GXT_table 'POOL'01E3: text_1number_styled 'NUM' 2@ 5000 ms 1  // ~1~end_thread

 

 

 

But it works only if the CLV thread and Thread_Names are located at the first 64k of the main.scm (single globalvar limitation). Otherwise use CLEO.

 

As for DP, Y_Less posted the Sanny's version of it (with pdescobar's corrections). I guess it should work.

Link to comment
Share on other sites

  • 1 month later...

It's a code to get the handle of nearest random ped / car / object to a variable.


Originally was written by PLPynton
but that code was buggy and never worked for me. I've fixed and improved it.

The code accepts 4 parameters for the search: XYZ coord of the point from where begin to search and radius of the searching.
If there's any ped (or car, whatever you wish) in this radius, the code stores. its handle in variable 9@.
Otherwise it returns -1. It will ignore the player or his car also.


This code is written in native line-by-line syntax so it could be used in SAMB as well (if there's someone still using it, he-he..).
Only labels and aDMA (&) should be converted (@ -> JJ, & -> $)



{   The Interceptor        by PLPynton and Seemann       Parameters:   0@ - input coord X   1@ - input coord Y   2@ - input coord Z   3@ - search radius   variables [email protected]@ in use      9@ = Result (returns -1 if not found)         }:AIC_GETACTOR0006: 16@ = 3058680006: 17@ = @AIC_TESTACTORHANDLE0006: 20@ = 19880002: jump @AIC_STARTSEARCH:AIC_GETVEHICLE0006: 16@ = 3058690006: 17@ = @AIC_TESTVEHICLEHANDLE0006: 18@ = -10006: 20@ = 25840256:   player $PLAYER_CHAR defined004D: jump_if_false @AIC_STARTSEARCH00DF:   actor $PLAYER_ACTOR driving004D: jump_if_false @AIC_STARTSEARCH03C0: 18@ = actor $PLAYER_ACTOR car0002: jump @AIC_STARTSEARCH:AIC_GETOBJECT0006: 16@ = 3058710006: 17@ = @AIC_TESTOBJECTHANDLE0006: 20@ = 412:AIC_STARTSEARCH0085: 4@ = 16@ // (int)008B: 4@ = &0(4@,1i) // (int)0085: 19@ = 4@ // (int)000E: 19@ -= 107871600016: 19@ /= 4008B: 19@ = &0(19@,1i) // (int)000E: 4@ -= 107871680016: 4@ /= 4008B: 4@ = &0(4@,1i) // (int)0006: 9@ = -10085: 11@ = 4@ // (int)0006: 10@ = 0:AIC_SEARCHLOOPMAIN000A: 4@ += 200050: gosub @AIC_READ4B0085: 4@ = 5@ // (int)8039:   not  4@ == 0004D: jump_if_false @AIC_SEARCHLOOPNEXT000A: 4@ += 480050: gosub @AIC_READ4B0085: 12@ = 5@ // (int)000A: 4@ += 40050: gosub @AIC_READ4B0085: 13@ = 5@ // (int)000A: 4@ += 40050: gosub @AIC_READ4B0085: 14@ = 5@ // (int)050A: 15@ = distance_between_XYZ 0@ 1@ 2@ and_XYZ 12@ 13@ 14@0025:   3@ > 15@ // (float)004D: jump_if_false @AIC_SEARCHLOOPNEXT0085: 9@ = 10@ // (int)0085: 4@ = 16@ // (int)008B: 4@ = &0(4@,1i) // (int)000A: 4@ += 40050: gosub @AIC_READ4B0085: 4@ = 5@ // (int)005A: 4@ += 9@ // (int)0050: gosub @AIC_READ1B0012: 9@ *= 256005A: 9@ += 5@ // (int)0002: jump 17@:AIC_TESTVEHICLEHANDLE056E:   is 9@ valid_vehicle_handle004D: jump_if_false @AIC_NOHANDLE00D6: if or003B:   18@ == 9@ // (int)0119:   car 9@ wrecked004D: jump_if_false @AIC_NEWSEARCHRADIUS0002: jump @AIC_NOHANDLE:AIC_TESTACTORHANDLE056D:   is 9@ valid_actor_handle004D: jump_if_false @AIC_NOHANDLE00D6: if or003C:   $PLAYER_ACTOR == 9@ // (int)0118:   actor 9@ dead004D: jump_if_false @AIC_NEWSEARCHRADIUS0002: jump @AIC_NOHANDLE:AIC_TESTOBJECTHANDLE//0001: wait 083CA:   not object 9@ exists004D: jump_if_false @AIC_NEWSEARCHRADIUS:AIC_NOHANDLE0006: 9@ = -10002: jump @AIC_SEARCHLOOPNEXT:AIC_NEWSEARCHRADIUS{    use 0051: return to break the loop  immediately when found at least one actor/car/object,  does not matter if he's nearest one.}// v EXTRA SEARCH CRITERIA GOES HERE v{ 21@ contains the handle of an actor/car/object that should be excluded from the search result (for example a handle found previously).}//803B:   21@  9@//004D: jump_if_false @AIC_NOHANDLE   0085: 3@ = 15@:AIC_SEARCHLOOPNEXT005A: 11@ += 20@ // (int)0085: 4@ = 11@ // (int)000A: 10@ += 1002D:   10@ >= 19@ // (int)004D: jump_if_false @AIC_SEARCHLOOPMAIN0051: return// ---------------------------------:AIC_READ1B0085: 6@ = 4@ // (int)0085: 8@ = 4@ // (int)0016: 4@ /= 40012: 4@ *= 40062: 8@ -= 4@ // (int)0012: 8@ *= 8000E: 4@ -= 107871680016: 4@ /= 4008B: 7@ = &0(4@,1i) // (int)0085: 4@ = 6@ // (int)0006: 5@ = 00006: 6@ = 0:AIC_READ1B_LOOP08B9:   test 7@ bit 8@004D: jump_if_false @AIC_READ1B_NEXTBIT08BF: set 5@ bit 6@:AIC_READ1B_NEXTBIT000A: 6@ += 1000A: 8@ += 10039:   6@ == 8004D: jump_if_false @AIC_READ1B_LOOP0051: return:AIC_READ4B0085: 6@ = 4@ // (int)000E: 4@ -= 107871680016: 4@ /= 4008B: 5@ = &0(4@,1i) // (int)0085: 4@ = 6@ // (int)0051: return


Example:

 while truewait 100 00A0: store_actor $PLAYER_ACTOR position_to 0@ 1@ 2@ 3@ = 15.0 gosub @AIC_GETVEHICLE if   9@  -1 then    020B: explode_car 9@ // versionA    // 0085: 21@ = 9@ // exclude this handle from the next search, see extra search criteria in the code endend


Screenshot:

A marker above random object
t719381_mfff.JPG

Edited by Seemann
Link to comment
Share on other sites

  • 10 months later...

 

-------------------------------------------------

 

EXAMPLE 1.

Make extremely long trains, 15+ carriages!

 

Original (in Russian)

Screenshot

-------------------------------------------------

 

 

:LONGTRAINSthread 'TRAINS'   for 0@ = -382229 to -382216    wait 0     &0(0@,1i) = #STREAKC          end                                                // type0 changed!  // load models  #FREIGHT.Load  #FREIFLAT.Load  #STREAKC.Load  while true    if and      Model.Available(#FREIGHT)      Model.Available(#FREIFLAT)      Model.Available(#STREAKC)       then       Break    end    wait 0  end      // create train with new carriages   06D8: 1@ = create_train_at 2278.1771 -1144.8823 27.5108 type 0 direction 1   #FREIGHT.Destroy  #FREIFLAT.Destroy  #STREAKC.Destroy  end_thread

 

 

 

You describe how to change train type 0. But How can I change other train Types?

Maybe I stands in The Russian version But cant Russian. Can You Explain how to Change The Other train Types?

Is it Possible To add for example only 5 Carrigages and not 15?

Link to comment
Share on other sites

Read this post to find out the addresses where the game keeps the info about train types.

 

If you wanna change another type, say 3, and make it 5 carriages in length, do the following:

 

take an address of train type (0x8D45B8). it will be the address of the locomotive. write to this address which model you want for it. next 5 dwords (4 bytes each) will be carriages models. so, write to the 0x8D45B8+4, 0x8D45B8+8, 0x8D45B8+12, 0x8D45B8+16, 0x8D45B8+20 addresses models ID for carriages. then write zero to the next address (0x8D45B8+24). so, when you create a train of type 3, the game will read these addresses until it will find zero, and you will get a train with 5 carriages.

 

to write to a memory address use CLEO opcode 0A8C.

 

 

0A8C: write_memory 0x8D45BC size 4 value #FREIFLAT virtual_protect 0

 

 

Link to comment
Share on other sites

 

Read this post to find out the addresses where the game keeps the info about train types.

 

If you wanna change another type, say 3, and make it 5 carriages in length, do the following:

 

take an address of train type (0x8D45B8). it will be the address of the locomotive. write to this address which model you want for it. next 5 dwords (4 bytes each) will be carriages models. so, write to the 0x8D45B8+4, 0x8D45B8+8, 0x8D45B8+12, 0x8D45B8+16, 0x8D45B8+20 addresses models ID for carriages. then write zero to the next address (0x8D45B8+24). so, when you create a train of type 3, the game will read these addresses until it will find zero, and you will get a train with 5 carriages.

 

to write to a memory address use CLEO opcode 0A8C.

 

 

0A8C: write_memory 0x8D45BC size 4 value #FREIFLAT virtual_protect 0

 

 

 

Ok Thanks That works.

Edited by X_ATP_X
Link to comment
Share on other sites

  • 10 months later...

 

-------------------------------------------------

Making cheats

the easiest way

-------------------------------------------------

 

Making cheats (custom keypresses) seems to be a very common problem in SA scripting. People keep asking how to make them. Even there are ways to check the keys typed (first post of this topic has one of them), they are complex and require knowledge of memory structure.

 

Time ago I wrote a code that allows to make the cheats easily. All you need is to store a cheat string to a variable, call the scm function and check the result (true or false).

 

First of all, read this post to understand how passing the strings to scm functions or threads work.

 

Now, the code to check a custom cheat:

 

 

:TestCheatif   0AA9:    is_game_version_originalthen   10@ = 0x969110 // keypresses buffer 1.0   11@ = 0xA48960 // mission locals 1.0else   10@ = 0x96B790 // keypresses buffer 1.01   11@ = 0xA4AFE0 // mission locals 1.01end// get 0@'s offset0A9F: 4@ = current_thread_pointer0A8E: 5@ = 4@ + 0xDC // mission Flag0A8D: 5@ = read_memory 5@ size 1 virtual_protect 0if   5@ == 1then   0085: 4@ = 11@else   4@ += 0x3Cend// get cheat string length6@ = 0while true   0A8D: 5@ = read_memory 4@ size 1 virtual_protect 0   if and       5@ > 0       6@  0   dec(4@)          dec(6@)   0A8D: 5@ = read_memory 4@ size 1 virtual_protect 0 // last cheat char   // lowercase to uppercase (a->A)   if       5@ > 90   then       5@ -= 32   end   0A8D: 7@ = read_memory 8@ size 1 virtual_protect 0 // last pressed key   inc(8@)      if       803B:   5@  7@ // (int)   then       059A: return_false       0AB2: ret 0   endend0A8C: write_memory 10@ size 1 value 0 virtual_protect 00485: return_true0AB2: ret 0

 

 

Copy this code without any changes to your script (it does not matter is it a mission or just a script; the code is designed in the way it works for both).

 

You may save the provided code to an external file and include it to your script using directive $INCLUDE (or $I). For example, download the file TestCheat.inc, copy it to the directory with your script's source, add the line

 

{$I TestCheat.inc}

 

at the very end of the script and that all. When you compile, the code will be read from the external file by the compiler automatically.

 

So, how to use this code and check your own cheats. Very easy.

 

Save the cheat string (for example, the cheat will be NOCOPS) to a variable

 

0@s = 'nocops'

 

Now call the scm function TestCheat with this string as argument (the post I linked above explains the way it works).

 

0AB1: call_scm_func @TestCheat 2 0@ 1@

 

And if the function returned true it means the player typed this cheat in-game. So you need to put the function' call in a loop:

 

CLEO script example:

 

{$CLEO}0000:while true   wait 250 ms   0@s = 'nocops'   if        0AB1: call_scm_func @TestCheat 2 0@ 1@   then        0110: clear_player $PLAYER_CHAR wanted_level   endend{$I TestCheat.inc}

 

 

^ When you typed nocops in-game the function return true, and the command clear_wanted_level will be executed.

 

If your cheat is longer than 7 symbols, use long strings:

 

 

{$CLEO}0000:while true   wait 250 ms   22@v = "leavemealone"   if        0AB1: call_scm_func @TestCheat 4 22@ 23@ 24@ 25@   then        0110: clear_player $PLAYER_CHAR wanted_level   endend    {$I TestCheat.inc}

 

 

Notes:

1. the cheat string is case-insensitive. You may write 0@s = 'nocops', 0@s = 'NoCoPs', 0@s = 'nOCOPs', it will still work.

2. The cheat could be from 1 to 16 symbols in length.

 

Link to comment
Share on other sites

  • 2 years later...

I know it's an awsum topic n'all.. but 'bumping' is heavily frowned upon wink.gif

 

No, because I believe VC doesn't support arrays. That's what "CLEO For VC" was created for.

Link to comment
Share on other sites

Well, that's cool, but I don't really know how I'm able to do cheats like this. I mean, by typing words, not just pressing combinations.

Link to comment
Share on other sites

  • 2 months later...

hello everyone i was wondering if it is possible to make a cheat that can make the current savegame 100% finished with everything unlocked, completed and all territories taken over

 

thx biggrin.gifalien.gif

  • KEKW 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.