Tutorials

 Reply to this postStart new topic

[CLEO|TuT] finding out which save was loaded/saved

miki45
post Jun 26 2014, 11:02 AM
Post #1


The New Guy!

Posts: 9
Joined: 26-June 14



(not sure if this thread should be here, or in the coding section)
(this "tutorial" is for advanced coders)

Even with enable_thread_saving, you can only save 1000 global CLEO vars and 34 local vars.

With your own save file you can save as much as you want, the problem is how to find out which save was loaded/saved

EDIT:
Thanks to Deji's advices I implemented easy and relaible way:

- to get index of the last loaded save use (at the begining of your code, before your main loop):

CODE
CONST
    Tvar           = 0@
END

GET_INT_STAT 136 Tvar
IF Tvar > 0 // 0 saves = new game
THEN
    READ_MEMORY 0xBA68A7 1 0 Tvar  // index of the last loaded save
    Tvar now contains the index of the loaded save
    - do your stuff
END


- to get index of the last save use (just use GOSUB @CheckSave in your mainloop):
CODE
CONST
    MenuID         = 0@
    Tvar           = 1@
END

:CheckSave
READ_MEMORY 0xBA68A6 1 0 MenuID // ID of the last shown menu

IF Tvar == 0
THEN
    IF OR
        MenuID == 18 // save successfull
        MenuID == 19 // save successfull    
    THEN
        READ_MEMORY 0xBA68A7 1 0 Tvar   // index of the last save
        
        Tvar now contains the index of the save
        - do your stuff
        
        Tvar = 1
    END
ELSE
    IF OR
        MenuID > 19
        MenuID < 18    
    THEN
        Tvar = 0
    END
END

RETURN


This post has been edited by miki45: Jun 28 2014, 03:21 PM
Go to the top of the page
 
+Quote Post
Deji
post Jun 26 2014, 06:56 PM
Post #2


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



Interesting and inventive method (props for thinking of something new and using your own initiative to get there - that's rare for CLEO scripters, but I have a feeling you may be more than just a CLEO scripter), however reading the CLEO save file is not really a reliable and 'future-proof' workaround for the lack of save system, since if CLEO save files are updated in an imaginary future CLEO release, your script will fail to work on the new one. And as the current developer of CLEO, users will come to me and be angry about my meddling with the save format, that was a perfectly reasonable thing to meddle with, because they can't get your script to work after the update. Things like this get messy, and the exact same things happened when I released CLEO 4.3 to fix in part the issues caused by CLEO 4/3, or rather the numerous scripts which wrote something so dependent on a specific CLEO version.

However, say you wrote a plugin which simply checked the dates of recent CLEO save files and returned the number of the latest one, then that'd be a more reasonable workaround. Unfortunately there's still the original issue that CLEO libraries are always able to conflict by using one of the same 29887 possible opcodes another CLEO library may use, but at least that will be handled somewhat gracefully by CLEO itself.


I wrote a method, using my SuperVars extension to the SCM scripting engine, which did pretty much the same thing as this (the script, not SuperVars - SuperVars adds the ability access to memory like ALLOCATE_MEMORY using the SCM's native variables - allowing all sorts of optimisations where multiple READ_MEMORY/WRITE_MEMORY commands would occur to be replaced by iterating loops and arrays), however. You can get the used save slot for a loaded game via a byte at 0xBA68A7, and to actually test if the game was loaded at all, you can check the "number of safehouse visits" AKA "number of saves" stat, stat 136. You can then read parts of the menu structure to gather whether the last menu was the "Save Successful" screen. It fails if, say, the user was to force-terminate on THAT screen, instead of doing what you usually have to do and exiting, entering the menu again and selecting 'Quit', but that shouldn't be a huge problem, really.

Have a read: https://pastebin.com/0FADdbBL


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 26 2014, 09:36 PM
Post #3


The New Guy!

Posts: 9
Joined: 26-June 14



Thanks for the advices

Updated the code + I'm looking forward to that reply (read the code)

This post has been edited by miki45: Jun 26 2014, 09:37 PM
Go to the top of the page
 
+Quote Post
Deji
post Jun 26 2014, 10:42 PM
Post #4


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



QUOTE
0A8C: write_memory 0xBA68A6 size 1 value 1 virtual_protect 0 // I'm looking forward to replay from Deji


Not sure what you're trying to do here. You're setting the value of the "last menu screen" to the "start game" screen, which of course isn't likely to do anything, except disallow other scripts from also saving.

As in the example script, reading 0xBA67A7 (the CMenuManagers "show save screen" option) will allow you to determine whether the menu is going into the save game screen (which is set after picking up a save diskette by opcode 03D8) before CLEO loses control to the menu, letting you set a variable so you know to check to save when the menu exits.

Now I think about it, this might prove flawed when it comes to hacked menus which allow the user to go straight from a non-save related part of the menu to the save section. There are always ways another mod can completely break yours, though, and it's all easy to overlook. That's why now I preach to keep CLEO non-hacky and only use the carefully managed opcodes provided. Unfortunately, what's provided is obviously not enough, so hacky things will be the obvious choice until CLEO gets some serious changes in these areas. It's a weakness of R*'s SCM engine, not just CLEO, but CLEO shares it by being a relatively simple extension of the SCM engine, which people tend to treat as if it were immortal tongue.gif



Remember also that these memory writes can only be guaranteed to work on 1.0US .exe versions. So while you've dropped CLEO-specific dependency, you've added an .exe dependency. But after all, the SA .exe's are not as likely as CLEO to be updated in future and at least if you wanted to, you'd be able to collect the addresses for the other versions too and provide support for each, or just let your users know that your script has this dependency, which quite a lot of mods share anyway.


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 27 2014, 11:09 AM
Post #5


The New Guy!

Posts: 9
Joined: 26-June 14



QUOTE
0A8C: write_memory 0xBA68A6 size 1 value 1 virtual_protect 0


0xBA68A6 - holds the ID of the last displayed menu, so "save successfull" value is gonna be there till, the next menu is shown, which is of course unacceptable if it's checked every 100ms, so the easiest solution is to put there some value that ain't 18 or 19 (game ain't crashing, so it's OK)

I recommed to wait for example 500ms (it's after the save, so the chance that someone could make another save in less that 2s is very slim) and it gives another threads with this method 500ms to find out if the game was saved, that is more that enought.

And that, I consider to be the best thing about this method, it's gonna work till the next menu is shown, so
even after the save is done and there is no save menu.

EDIT:
Well you can solve that problem with a additional var
CODE
if
    1@ == 0
else_jump @SWAIT
if or
    0@ == 18 // save successfull
    0@ == 19 // save successfull
else_jump @NOTSAVED
0A8D: 0@ = read_memory 0xBA68A7 size 1 virtual_protect 0 // index of the last saved save
0@ now contains the index of the last save
- do your stuff
1@ == 1
jump @NOTSAVED

:SWAIT
if and
    not 0@ == 18 // save successfull
    not 0@ == 19 // save successfull
else_jump @NOTSAVED
1@ = 0

:NOTSAVED


but I don't see much gain in it (ok it's true that another script can detect save until some other menu is shown, but player may just go to the main menu after the save (not sure why) and the result will the be same as with the version with the write memory command)

Well .exe dependency is fine by me, I use Weapon Limit Adjuster so there is only one .exe for me + I think that .exe dependency if fine, cos that .exe ain't gonna change, which we can't say about CLEO.

BTW:
It there some tutorial about linked lists? (I can't find any) Cos if isn't, I think that there should be one (I know that advanced CLEO scripters probably know how to do it, but I think, that there may be some that just don't know the concept, advantages, disadvantages, etc.) (I may write one, If there really ain't one and someone considers that a good idea)


(random rambling, A.K.A. reason for a strike or ban)
Well it's not really my problem , cos this (GTA sa modding) is my vacation from my OFP modding (yes to relax from one modding I do some different modding (Fallout 3, STALKER, Mafia, now GTA), and as I say: If I paly it, I mod it), today it's my 6th day of CLEO scripting and I'm starting to get bored (vacation, don't take it personally), cos I did what I wanted to do (create weapon handling system, that limits the ammo that you can carry, allows dropping weapons, and when a weapon is replaced, the old one is dropped (dropped weapons are object not pickups, and I allow only 100 of them, after that the oldest is erased, (stored in linked list, which I needed to save and load, and well that's how this thread started))) (OK i'm really off-topic, good thing, that this is just my vacation, otherwise I would have to worry about not getting strikes, or ban)

This post has been edited by miki45: Jun 27 2014, 09:39 PM
Go to the top of the page
 
+Quote Post
Deji
post Jun 27 2014, 04:06 PM
Post #6


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



I've not really attempted to write any tutorials lately, since I'm currently working on things which may fix most of the problems we'd need tutorials to solve anyway. As I said, SCM/CLEO is pretty incomplete and where there's not an official way of doing something, there aren't any ways which can guarantee to be flawless.

Though, for a tutorial about linked lists, it doesn't need to be specific to CLEO syntax. It's a simple technique consisting of pure pointer reading (reading memory addresses for memory addresses). One could look for a C tutorial of it and gain the basic idea or look at the Wikipedia page which covers plenty of concepts like this in a variety of languages:
http://en.wikipedia.org/wiki/Linked_list


Anyway, writing that memory address is still problematic. You're doing it so your own code doesn't save twice? So then how will any other script perform a save? For example, my 'Black Market Mod' mod uses the original technique I posted, which relies on reading the same memory address. If your script runs first and changes the value before Black Market Mod reads it, it would fail to do its save. However, since I used the pre-checking I mentioned in order to set a local variable to prevent excessive saves, my script running first doesn't affect yours badly. If your script worked the same, my script and many more could run alongside it using the same technique and never fail.

However, I'm not sure why I didn't simply use:
CODE
09FA:   is_player_just_out_of_menu


It could be an option, or perhaps the reason I didn't use it is because it was problematic. You could give it a try though. Only attempt the save when that returns true, and leave the menu variables alone so you don't risk sabotaging other scripts.


About your rambling, the 'object pickups' idea is tricky but has already been pursued to perfection. DK22 released a mod including this feature: http://dk22pac.blogspot.co.uk/2011/12/ivlm...nformation.html
Not sure if it can be used alone. Unfortunately I never got around to fixing my technique.


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 27 2014, 04:13 PM
Post #7


The New Guy!

Posts: 9
Joined: 26-June 14



CODE
wait 500
0A8C: write_memory 0xBA68A6 size 1 value 1 virtual_protect 0


your script has at least 500ms before my changes it, which is like a year in human life

about my rambling,I forgot to write, that I have already done that, that's why I'm getting bored


This post has been edited by miki45: Jun 27 2014, 04:32 PM
Go to the top of the page
 
+Quote Post
Deji
post Jun 27 2014, 04:53 PM
Post #8


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



QUOTE (miki45 @ Jun 27 2014, 05:13 PM) *
CODE
wait 500
0A8C: write_memory 0xBA68A6 size 1 value 1 virtual_protect 0


your script has at least 500ms before my changes it, which is like a year in human life


WAIT's are no replacement for proper control of script flow. Using a WAIT anywhere in the script, will make the rest of your script essentially freeze or deactivate for that time. In case you intend to extend your script to things which may have to always be running, it's best to not use WAIT's like this. Plus you get all the other uncertainties of things which may need to happen in those 500ms. If you use WAIT's like this, for all you know, your script may end up being at a totally different WAIT when the game is saved, and your script would fail to save.

Best practise is to have a script run in one single loop, and use variables and other methods to control what code is executed and when.

I ranted about WAIT's a fair bit in this topic, as well as how their use is easily avoided:
http://gtaforums.com/topic/699108-sa-multi...e/?p=1065353791


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 27 2014, 05:37 PM
Post #9


The New Guy!

Posts: 9
Joined: 26-June 14



that wait happens after the save, there is no chance that you can do anything in that time (my script dosn't need to run in that time)

it's like:

CODE
:loop
wait 100
(I can froze script for 0.1s, cos it doesn't do anything that requires,quick response)


if saved
(else goto loop)
do stuff
wait 500
(now I can wait palyer just saved and is literally standing there and can't do anything (if you can do 2 saves in less that 600s, then you are very good, I'm unable to get control of my char in that time))

goto loop



+ no offence but explaining what a basic command like wait does, to a guy who has been using that comand for nearly a decade is pointless

I know that you don't know who I'm, so I understand, but that doesn't mean that I don't found the fact that you are explaining the absolutly basic things to me, like if i was a guy hwo just started coding iritating (again no offence I get wzhy you do it and I would've done the same thing)


just to make it clear, this is that script (again i know it's not compatible with other cleo scripts, cos it's using global cleo vars and I don't care, I don't want to release it, or use others mods in my game)

CODE
{$CLEO .cs}  
// 0@ - Linked list start
// 1@ - Linked list end
// 2@ - Linked list count of items
// 3@ - BUFF
// 4@ - BUFF (pos x)
// 5@ - BUFF (pos y)
// 6@ - BUFF (pos z)
// 7@ - BUFF (weapon)
// 8@ - BUFF (ammo)
// 9@ - BUFF (model, var 999,998)
// 10@ - BUFF

:pickup
03A4: name_thread "PICKUP"
0AC8: 0@ = allocate_memory 16
1@ = 12
005A: 1@ += 0@
0A8C: write_memory 1@ size 4 value 0 virtual_protect 0
2@ = 0

0652: 9@ = get_int_stat 136
if
    not 9@ == 0
else_jump @PC_LOOP
0A8D: 9@ = read_memory 0xBA68A7 size 1 virtual_protect 0
0A99: chdir "CLEO\CLEO_SAVES"
0AD3: 3@v = format "WD%d.sav" 9@
if
    0A9A: 10@ = open_file 3@v mode 0x6272
else_jump @PC_LOOP
0A9C: 3@ = file 10@ size
if
    not 3@ == 0
else_jump @PC_RDF


3@ /= 12
:PC_READ
0AC8: 5@ = allocate_memory 16
0A8C: write_memory 1@ size 4 value 5@ virtual_protect 0
0A9D: readfile 10@ size 4 to 4@
0A8C: write_memory 5@ size 4 value 4@ virtual_protect 0
5@ += 4
0A9D: readfile 10@ size 4 to 4@
0A8C: write_memory 5@ size 4 value 4@ virtual_protect 0
5@ += 4
0A9D: readfile 10@ size 4 to 4@
0A8C: write_memory 5@ size 4 value 4@ virtual_protect 0
5@ += 4
0A8C: write_memory 5@ size 4 value 0 virtual_protect 0
0085: 1@ = 5@
2@ += 1
if
    003B: 2@ == 3@
else_jump @PC_READ

:PC_RDF
0A9B: close_file 10@
wait 0
03F0: enable_text_draw 1
045A: text_draw_1number  50.0  425.0 'NUMBER'   9@
03F0: enable_text_draw 0



:PC_LOOP
wait 10
if
   Player.Defined($PLAYER_CHAR)
else_jump @PC_LOOP

0AB4: 3@ = var 0
if
    3@ == -1
else_jump @PC_SAV


0AB4: 4@ = var 1
0AB4: 5@ = var 2
0AB4: 6@ = var 3
0AB4: 7@ = var 4
0AB4: 8@ = var 5
0AB4: 9@ = var 6

if
    2@ == 100
else_jump @PC_ADD
2@ -= 1
0085: 3@ = 0@
3@ += 12
0A8D:3@ = read_memory 3@ size 4 virtual_protect 0

0085: 10@ = 3@
0A8D: 3@ = read_memory 10@ size 4 virtual_protect 0
Object.Destroy(3@)
10@ += 12
0A8D: 3@ = read_memory 10@ size 4 virtual_protect 0
10@ -= 12
0AC9: free_memory 10@

0085: 10@ = 0@
10@ += 12
0A8C: write_memory 10@ size 4 value 3@ virtual_protect 0


:PC_ADD
2@ += 1
10@ = Object.Create(9@, 4@, 5@, 6@)
0AC8: 3@ = allocate_memory 16
0A8C: write_memory 1@ size 4 value 3@ virtual_protect 0

0A8C: write_memory 3@ size 4 value 10@ virtual_protect 0
3@ += 4
0A8C: write_memory 3@ size 4 value 7@ virtual_protect 0
3@ += 4
0A8C: write_memory 3@ size 4 value 8@ virtual_protect 0
3@ += 4
0A8C: write_memory 3@ size 4 value 0 virtual_protect 0
0085: 1@ = 3@
0AB3: var 0 = 0
jump @PC_LOOP


:PC_SAV
0A8D: 9@ = read_memory 0xBA68A6 size 1 virtual_protect 0
if or
    9@ == 18
    9@ == 19
else_jump @PC_KEY

0A8D: 9@ = read_memory 0xBA68A7 size 1 virtual_protect 0

0A99: chdir "CLEO\CLEO_SAVES"
0AD3: 3@v = format "WD%d.sav" 9@
0AB3: var 998 = -1
if
    0A9A: 10@ = open_file 3@v mode 0x6277
else_jump @PC_KEY


0085: 3@ = 0@
3@ += 12
0A8D: 3@ = read_memory 3@ size 4 virtual_protect 0
if
    not 3@ == 0
else_jump @PC_WRF

:PC_WRITE
0A8D: 4@ = read_memory 3@ size 4 virtual_protect 0
0A9E: write_to_file 10@ size 4 from 4@
3@ += 4
0A8D: 4@ = read_memory 3@ size 4 virtual_protect 0
0A9E: write_to_file 10@ size 4 from 4@
3@ += 4
0A8D: 4@ = read_memory 3@ size 4 virtual_protect 0
0A9E: write_to_file 10@ size 4 from 4@
3@ += 4
0A8D: 3@ = read_memory 3@ size 4 virtual_protect 0
if
    3@ == 0
else_jump @PC_WRITE

:PC_WRF

0A9B: close_file 10@
:PC_SEND
wait 500
03F0: enable_text_draw 1
045A: text_draw_1number  50.0  425.0 'NUMBER'   9@
03F0: enable_text_draw 0
0A8C: write_memory 0xBA68A6 size 1 value 1 virtual_protect 0

:PC_KEY      
if  
   0AB0:   key_pressed 9
else_jump @PC_LOOP

0085: 3@ = 0@
:PC_TRV
3@ += 12
0085: 10@ = 3@
0A8D: 3@ = read_memory 3@ size 4 virtual_protect 0
if
    not 3@ == 0
else_jump @PC_LOOP
0A8D: 9@ = read_memory 3@ size 4 virtual_protect 0
01BB: get_object_coordinates 9@ store_to 4@ 5@ 6@
   00FF:   actor $PLAYER_ACTOR sphere 0 in_sphere 4@ 5@ 6@ radius 0.5 0.5 1.0 on_foot
else_jump @PC_TRV
2@ -= 1

3@ += 4
0A8D: 7@ = read_memory 3@ size 4 virtual_protect 0
3@ += 4
0A8D: 8@ = read_memory 3@ size 4 virtual_protect 0
3@ += 4

01B2: give_actor $PLAYER_ACTOR weapon 7@ ammo 8@
Object.Destroy(9@)
0A8D: 9@ = read_memory 3@ size 4 virtual_protect 0

0A8C: write_memory 10@ size 4 value 9@ virtual_protect 0
3@ -= 12
0AC9: free_memory 3@

if
    9@ == 0
else_jump @PC_RM

0085: 1@ = 10@
jump @PC_LOOP

:PC_RM
0085: 3@ = 10@
3@ -= 12
jump @PC_TRV


This post has been edited by miki45: Jun 27 2014, 05:48 PM
Go to the top of the page
 
+Quote Post
Deji
post Jun 27 2014, 08:33 PM
Post #10


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



QUOTE (miki45 @ Jun 27 2014, 06:37 PM) *
+ no offence but explaining what a basic command like wait does, to a guy who has been using that comand for nearly a decade is pointless


Well if you think that the mere fact the command is called 'WAIT' means it's directly related to any other implementation of a command with that name, then explaining these things is not so pointless after all. This is a problem with the way quite a lot of CLEO scripters write, no matter how much they happen to know simply what the word 'WAIT' means or how there's a command called 'WAIT' in another language. I'm explaining implementation-specific details which one couldn't possibly know for sure without reverse-engineering GTASA's SCM scripting engine AND knowing how CLEO extends it.

And I never said you didn't know what WAIT does, but that you were using it too liberally. It's an over-used command, even in other languages.

QUOTE
I know that you don't know who I'm, so I understand, but that doesn't mean that I don't found the fact that you are explaining the absolutly basic things to me, like if i was a guy hwo just started coding iritating (again no offence I get wzhy you do it and I would've done the same thing)


Who you are doesn't matter. Even if you were Einstein, I'd still correct you when you're using methods I know for a fact are very flawed tongue.gif

Whoever you are, you're definitely not the one working on extending CLEO or the one who's spent several years fixated on the SCM scripting engine, with a vast vision to improve it. In fact, if you had a true idea of how the SCM scripting engine was and its many caveats, you really wouldn't be using it at all. Until I've finished the next version of CLEO, not even I'm writing scripts for it. It's got all sorts of problems. Not even the straight forward things are as straight forward as they appear, and for years the only REALLY successful CLEO coders are the ones who have used it for years, because it requires a great load of familiarity.


This isn't "basic stuff", this is a brutally misused and abused scripting engine which was never meant to be used by us. Even the CLEO scripts themselves defy the very fundamentals of the SCR/GTA3script language. Every CLEO tutorial on the net teaches REALLY bad habits. I've been the most obsessive SCM engine researcher for years now, and have found many instances where everything I was taught, and every piece of information available online, was wrong. Until fairly recently (a few months ago) even I accepted WAIT's as a valid form of script flow control, as well as many other things I'd now condemn.


It would become quite clear if you decompiled the main.scm. Each individual script, which happened to be written by Rockstar North, within only has ONE 'WAIT'. The circumstances are very rare that a 'WAIT' value other than 0 or $DEFAULT_WAIT_TIME is used twice in one script, which isn't a script that will end soon or be to get around some weird limitation of the engine. The ONLY time to use a WAIT, is not when you want the script to 'SLEEP' but when you want to wait for the game engine to process things, which you only need to do once in every execution loop of your script. If you use it more than once in a script, it's quite likely you're going about writing the entire script wrong, or at the very least, there's a better way to write it.


If you don't care about the fact that using WAIT to control script flow IS a considerably amateur move because you're only using the script yourself anyway, that's fine. It still doesn't give you any reason to take an exception to me providing information, even if it is more than you wanted. After all, this topic is supposedly a "tutorial", so it would be silly not to try and provide the most accurate information available at all times, and this tutorial won't be very good if it's spreading bad habits even further. You're also writing your code in low-construct which I wouldn't recommend, using classes which I wouldn't recommend, and have quite a few more questionable lines in your script. I only focused on the most important one I saw.


In short, other languages don't count.


QUOTE
CODE
0A99: chdir "CLEO\CLEO_SAVES"
0AD3: 3@v = format "WD%d.sav" 9@


Luckily since CLEO 4.3, the value set by 'chdir' is script-dependent. However, in all versions of CLEO before that, this is not the case, and there could be serious problems caused by not restoring the 'chdir' value after you're done with the change, because it usually sets the working directory for the entire game.

So, while it's not a problem since I noticed it and added the fix in 4.3, it will be very dangerous on other versions of CLEO, so again, watch out.


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 27 2014, 09:36 PM
Post #11


The New Guy!

Posts: 9
Joined: 26-June 14



(just a side note I like you more and more)

about that "you don't know who I'm", it's not that i want to look like some know-it-all or something, it's just that I have a lot of experiences with people threating me like a guy who doesn't know what is a variable. Well this wasn't the case, so sorry about that.

Well about my code, I used code without functions and procedures, cos that code was never meant to have more that couple of lines.

Well I'm not stupid enought to argue with a guy, who spend years researching this game (I would just piss you off and you would be right), but I would like to hear more about this wait problem, cos I saw it with non-zero value in most of the cutscenes or text handling things in main.csm, so I just want to know more

(personal opinion)
Well about things that work now but would be problematic in older versions of CLEO, i personally would let it go, people should keep their stuff up to date (if you have windows 3.11 you can't expect to run GTA)

and about the save check, what about this piece

CODE
if
    1@ == 0
else_jump @SWAIT
if or
    0@ == 18 // save successfull
    0@ == 19 // save successfull
else_jump @NOTSAVED
0A8D: 0@ = read_memory 0xBA68A7 size 1 virtual_protect 0 // index of the last saved save
0@ now contains the index of the last save
- do your stuff
1@ = 1
jump @NOTSAVED

:SWAIT
if and
    not 0@ == 18 // save successfull
    not 0@ == 19 // save successfull
else_jump @NOTSAVED
1@ = 0

:NOTSAVED



(not relevant to this topic)
Well I don't agree, that wait is overused command in othrer languages, cos I know some when wait is a must, like OFP scripting, do 10 lops without wait and the game is frozen, or do C++ app with windows.h that checkes if a key was pressed, without sleep, and there is a lot of cases when, there is no point in checking something more often that 10 times per second, hell even when you are programming MCU, there are cases when you canuse wait, cos there is nothing more to do.

QUOTE
This isn't "basic stuff", this is a brutally misused and abused scripting engine which was never meant to be used by us


Most of the game languages that I worked with was just like that.

This post has been edited by miki45: Jun 27 2014, 09:38 PM
Go to the top of the page
 
+Quote Post
Deji
post Jun 28 2014, 01:05 AM
Post #12


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



Don't worry, we have plenty of things in mind for CLEO, and I am taking every obsessive step I can to ensure all these nagging problems are a thing of the past.

The problem with the low-construct-ness is, the original code would have never looked like that. It is a sort of pseudo-language of Sanny Builder's own, based on the syntax of much more ancient and now discontinued compilers. SB also provides the much easier to maintain high-level syntax, which unfortunately is not used enough by a lot of new CLEO scripters.

You can read about the older compilers here - it's interesting: http://www.gtamodding.com/index.php?title=...view)#The_Tools
My current major goal is to rewrite my 'SCR' compiler, which takes on and extends the original 'GTA3script' language made by R*.


(P.S. forgive me... it was all fine up until here... by all means, skim through this text tongue.gif)


Some people still refuse to use CLEO 4.3 because this-or-that (badly - or at least 'illegally' written) scrip still doesn't work in it. CLEO 4 always had some compatibility problems with scripts written in CLEO 3 - it was written in a whole different language, which doesn't help. Most notably was Ryosuke839's Missile Script - which of course was popular, as well as other popular scripts from 'expert' modders, who mostly had no knowledge of coding outside of "SCM language" (which isn't even a real language - a language generally has rules) and were in fact making all sorts of mistakes in their scripts. But people will rather blame the people updating CLEO than the people who wrote the marvellous script that broke the rules (which don't exist - so who can blame them either really?). People will judge what they can see, and not the code that pulls it off. Unfortunately, it's too easy to write an amazing script in this 'language' and actually not have a clue what you're doing. I mean that in two ways, it's easy for a complete moron to write one and it's easy for someone who has been writing them for years to be writing something totally wrong. There is no official documentation for this 'SCM language'. People made everything up by bashing rocks together until they made shapely looking statues tongue.gif

EVEN ROCKSTAR made some REALLY stupid mistakes writing in their original 'native' language. After a lot of time reverse-engineering the stuff they've done, I assume that it comes down to a lack of communication between the coding department ('content writers' who probably only used in-house tools and weren't involved in the more hardcore programming aspects) and whatever parts of the programming department were responsible for working on this scripting engine, which I should note is pretty weak and simplistic even without CLEO's hacking it. A child could have written it. They finally ditched and remade it quite well in the RAGE engine, however. I've written many rants here about 'popular mistakes' of both modders and R* Norths coding department. You can look at the outside language and think it to be pretty well made, but start prying into what's going on behind the scenes and you'll be a lot less impressed, and find that a lot of the things you thought about how it worked were wrong.

I'm interested to know what your first 'exposure' to CLEO/SCM has been. Most of the tutorials are written by those same scripters who haven't seen enough of the inner workings of the entire scripting engine or understood how the original scripts really would have been written, which taken a lot of time and the lucky '8-years-too-late' 'accidental' occurrances of hints left in parts of the mobile GTA releases (including a III/VC compiler, GTA III source files and a list of all the original SA command names! - a lot of which we guessed wrong) to have collected enough official information to know about it.


[that's not a ramble! THIS is a ramble...]

I can't act like I'm the only one who knows all these things about the scripting engine, but I'm sure anyone will agree I've cared the most. SCM was the 'language' that set the most important first binary digit of my understanding of computers, way back in like, um, 2010? Anyway, I abused it like most of the rest of us. Got a thirst for creating bigger and more elaborate things and stuffing them in. I read one tutorial (which I now understand is grossly inaccurate) all the way through and I felt unstoppable. More experienced coders warned me against many habits I had, but I didn't listen to as many as I probably should have. Well, I can even look down at all of them now and assert that I know more about this crazy scripting engine - a lot of them don't know what a scripting engine even is, they just learnt of the same tutorial I did, then learnt some more stuff on their own. Perhaps I'll even soon realise my advice is wrong, in place of learning something even more elaborate, but when considering all this, it's easy to realise that people should share, and perhaps even be a bit too overly pushy, about the information that they think is best, and even though it's easy to get angry at one for sharing false information, as I often did in my rants about the incorrect findings of those who originally broke down the basic elements of SCM, as long as they genuinely thought it was right, it should all be fine. All information is good information, kind of - but then again, there's always the RIGHT information... ah, there goes my philosophical side.

Anyway, my hunger for getting more and more out of the scripting engine grew more and more. This happens with all CLEO scripters, it's a really annoying and tiring process - because everything you learn, you find out is flawed a few months later. It wouldn't happen if there was an 'official' source of information for all this, but in a world where no one has the true answer, people are forced to make best-guesses based on observations of something which really isn't as straight-forward as it seems. Hey, perfect metaphor for religion? I, and every CLEO scripter, started learning every trick in the book. There's even ways to insert x86 assembler into a script and cause that to be executed. It was an amazing discovery and eventually prompted me (and the most 'advanced' CLEO-ers here now) to learn assembly. Could there BE a worse reason to learn assembly, to hackily put it in a damn byte-code file and manipulate the game into executing it? We didn't think of the 'artistic value' behind a coding language, or that it may be more than just artistic value, and despite the fact there still are annoying problems and limitations with trying to use it, what matters most is what you can force the game to do, right? What are rules for if they weren't made to be broken? That kind of thinking... Took me a while to adapt to languages like C++, which have standards.



... OH RIGHT, the WAIT problem...


It's not a problem with the parameter at all. And if you're really sure you want to completely lose control of the script for xx amount of time, it's great. But as modders we're usually never creating cutscenes, or other time-dependent "step sequencer" style stuff. Another critical difference is, while we only have one script to pull off everything we want to pull off, R* had the entire main.scm, which is a merged compilation of different scripts which run independently from each other. WAIT is like a macro for "do{}while(true);", the biggest problem is, that unlike a real "do{}while(true);", you can't put anything in the do{} part, ever, nor can you easily add an extra continuation condition. And because your one script file can only be one script, it's not like you can just create put any code you may need to run during that time somewhere else, ever.

When we write CLEO scripts, though, we generally are writing an equivalent to full applications instead of simply cutscenes and missions. It's another slight abuse of the SCM engine, but it's one that can be done, if done correctly. In most of R*'s scripts, they have something they called a "main loop", which was a master loop which all code went in. If you think about it, makes the most sense to always start off this way. Like in a C/C++ program, you eventually enter a 'while', probably named because you'll be in there a really long while! It's the 'main' part of your program, where the jobs get done. Games are obviously a continually running program as opposed to one that does its tasks and exits, however, so most scripts you write WILL want to run forever. Best to do it in one loop, and when you look at it at a high level, it's very neat and easy to read, especially if you're sure where the code will be every time the game processes a frame. If there's only one WAIT, there's no question. If the code is all procedural, and based on a combination of events, could end up WAITing in a variety of places, you'll lose "guarantees" of your script. Guarantees are an important concept, which I may have just made up, but are important nonetheless. You always want to have as many of them (or rather, as few of them, in as few conditions, which overall makes your guarantees more 'global') as possible. Actually, this concept isn't sounding so original, I think I read it up a while ago, it's called "principle of least astonishment", which was an interesting read, and also again applies to the SCM engine on the whole.

So to summarise a bit, this wildly unpredictable scripting engine could do with as many guarantees about its execution as possible. There are still things I am completely clueless about when it comes to how R* originally scripted with it, the biggest thing being debugging - they had all sorts of 'devices' which I could launch into a whole other rant about. Search "fake_entity_creation" in the main.scm, it looks pretty damn interesting. Most CLEO scripters prefer to write small manageable loops in their scripts (syntax uglified on purpose):
CODE
:ugly_label
wait 0 ms
// does stuff
if SOMETHING
jf @ugly_label_2
jump @ugly_label

:ugly_label_2
wait 0
// do stuff here for some reason
if SOMETHING
jf @ugly_label_2
jump @ugly_label_3 // etc


Code like this, that ends up getting bigger and bigger, just ends up looking hideous and starts to acquire all sorts of bugs which can't easily be found amidst the bloat of code. And there's one more wait than necessary, right after :ugly_label_2, which only needs to exist for the chance that the SOMETHING after that label will always return true unless the game changes, but the very first time the wait is encountered would be unnecessary. And with all the low-construct-ness, how easy it is for someone to think "oh, I'll reuse that label so I don't have to re-write that code, by jumping to it and setting up a condition to jump back" or something. Weaving a tangled web, possibly causing the script to run inefficiently and be buggy IF the wait's occur unnecessarily. Again, all of this is worsened by the fact people are limited to one script. Some might try to write their script in two separate files, which was what that very topic I linked to was all about - topics like that are what occur from not realising that they cam manage and make it a lot less confusing by having it all flow in a continuous loop, which can easily be extended at any time without causing some unpredictable problems. When you use a WAIT, other scripts run (or they may not if yours is last), which deduct even more guarantees which are harder to spot. Each WAIT is a spot where everything you currently know may be different once it has finished. Personally, I don't even agree with Rockstars use of it, and since they definitely have made mistakes before, perhaps this commands very use is one of them, but apparently they wanted something really low level for some occasions. The value of the parameter really doesn't matter, because just as much can change in a single frame as can change in ANY amount of time. All you need to be sure of is that in every place a WAIT occurs, your script is definitely ready to not do anything, for the game to be saved and loaded again right there (which isn't a problem in missions which shouldn't be saved, unlike it is in a CLEO script), for the game to end, or for gravity to start working in the opposite direction - I'd personally only rather have to think about that happening in ONE place tongue.gif

To put all that even more simply: if you only have one WAIT, you can't possibly ever make a WAIT-related mistake, of which there are many to make. Wait == weight.

But by all means, if your script is simple enough and will stay that way, do whatever is easiest. But hopefully next time you write a tutorial here it will be in high-construct so I can actually bother to read more of it tongue.gif

However, for time related things, there are also timers, '32@' and '33@' (originally TIMERA and TIMERB), in case you've never heard of them. One less point for WAIT and one more for control structures, if you ask me.




... OK, back to the excessive lecture ...



Aiighh... It's a shame I haven't had the chance to already have written all these rants down in their own topic. I go on a lot of rants, sometimes repeating myself, sometimes getting to mention stuff I've never put 'out there', sometimes even coming to totally new drastic realisations right on the spot (ranting is good for that, I find). I've felt the need to unleash a lot of that right here, unfortunately, and it may not be entirely appropriate to expect you to read all this. The most recent tutorials I've written here even go on things I now disagree, at least partially, with. In fact, I'm at the point where I feel like just saying "don't use CLEO, wait until I've changed the entire modding scene with my big ideas which you might not even like". Unfortunately my rants rarely change the state of the modding scene for better, apart from reaching a few common minds who are capable of accepting a change in thinking. I should really have written all these as 'tutorials' so I at least have a constant thing to reference and so my points aren't forgotten about a week later. I eventually resorted to actually gaining a knowledge of REAL programming with the small-minded goal to add a few more things here and there to SCM, and more years later I'm now working on entirely new tools, languages and 'solutions' as alternatives to the current state of SCM of my own (and additionally trying to come up with alternatives to this fashion of trying to understand whatever script engine comes with any future GTA game - or any other game for that matter), and just hoping they start at least setting some standard of how modders should and shouldn't go about writing yet another engine toggle script tongue.gif

I can't be assed to go back through my post and make this in-context:
http://gtagmodding.com/forums/index.php?showtopic=483
As you can see, R* kind of sucked at their own scripting engine... or maybe there's just some weird cuckoo logic that we don't know about yet. I also post some coding tricks in the replies that I now disagree with, because if it has to be a trick, it was never meant to be.


Imagine the C language, without a standard. Imagine no one had ever used it, and imagine it was 'given' (in some limited capacity) to a limited group of people with only big hearts and an eagerness to create new things in their favourite game, and there is also no compiler, those people have to create one themselves. Though it's slightly inaccurate as a metaphor in a more technical sense, you can imagine how screwed up the language would become. The stuff you read when you decompile a script in Sanny Builder is the result of many years worth of people who have come and most since left the modding scene, trying to make sense out of bytes. Luckily those bytes are in a really simple format, so that itself isn't hard, but the language they created to explain it, the command (though they mostly get referred to as their primitive 'opcode') names they gave them, and the understandings of the parameters and behaviour of all of it put together (mostly observed by the results they appeared to give in-game, often heightened by over-eagerness and imagination to figure out what they are) all range from okay, to okay enough, to downright ludicrous.

By the fact your else_gotos are 'else_jumps', I can assume you've not 'discovered' my slight improvement to the SB language, "SCR for SB3", which can be generated via the OpcodeDB (sascm.ini v2, opcodes.txt v2, keywords.txt v2):
http://gtagmodding.com/opcode-database/generator/

It's still "BETA", but that's just to absolve me of any responsibility that it isn't *perfect*. However, the names of things are more correct than the stock SB files, the parameters are in the right order (oh yeah, forgot to mention that), and the overall syntax is greatly simplified, and starts to look more like the language R* invented. There's still lots unknown, however every command name is at least known, thanks to R* treating us with GTASA Mobile's content. Not that they meant to give it to us, or did they? You may notice there's no "classes.db" which contributes to SB's own "Object.Member" syntax, which I also disagree with, fussy me. In my defence, the class and member names are based on the original names mined by people cracking it from byte code, so there are things misleadingly named, and I think the original language had much more potential, which is what I've based my own language, 'SCR', upon. SCR is like a wrapper language for GTA3script which also provides other things, such as actual known standards tongue.gif It should start to be more prominent outside of the SB version syntax once I complete SCRambl.


It's a shame you're apparently only here temporarily though, as I have a feeling you're one of the few that might actually read - and god knows, even appreciate - the abuse of time that are my rants. And because of that I felt obliged to summarise every detail of what's most known about this crazy world of inaccurate information and share the long path it has taken to get here. I probably SHOULD tutorialise this at some point, because if I have any hopes of getting everyone else to change their ways, I'll have to really push most of the observations I'm making right now, though I'd have to manage to convince people of all sorts of intelligence levels (which I won't hold my breath for), so I'm probably going to also have to dumb-down things a few levels and be more brief in alternate tutorials. But I guess I'll never be able to just 'teach' everyone to do everything perfectly. The best I can do is hope to improve the most important and fundamental things, teach the more skilled the more complex things, and spread the information to as many people who can bear it as possible, so that perhaps I'll actually make a change that sticks. We modders are fighting a civil war, and every single person has a different side, because they each know a different amount of information, and no source can actually be pointed at and said is truly correct.


I've probably missed a few points, but I've surely made up for it in irrelevant posts I have somehow come to include. I am honestly sorry for writing all this, but it's nice to have written it somewhere.

If I had a catchphase, it would probably be "Lorem Ipsum CLEO SCM, blah blah blah" - it's long and uncatchy on purpose tongue.gif


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 28 2014, 08:04 AM
Post #13


The New Guy!

Posts: 9
Joined: 26-June 14



OK, I will try to write some of my thoughs about every paragraph (great now I have to read it again)

OK here we go:

low-construct
(OK I know that, I talk about other game, but I do so, that you can actually understand my mindset on this)
I agree that it shouldn't be used, as I said I'm scripter in OFP and I have some scripts that have more that 10 000 lines (yeah yeah line count really ain't a indication of script complexity and stuff) (ok they actually have like 200 lines in script alone (which is low-construct, cos ofp doesn't support while (true), or even wait in a while) and are using functions that have about thousands of lines (ok they are all written in one line, cos OFP scripting language is an implemented language, and origanally hasn't had a functional support and this support was later added by a command that turns a string into a code, so functions are actually strings and ofp syntax doesn't allow to use breaks in variable assignment, and I don't want to use a program that will jut remove line breaks from my code, cos then I would have my source code with line breaks and a code cor a game, in an implemented language, which would be ironical at least))
(OK I know I'm off topic here, but bear with it of a little longer)

So you can say I'm a guy who is forced by his favourite scripting language to write a total mess and people like that usually like the idea of a clean and understandable code (which a functional code with one main loop that contains only comand to call some functions is)


Some people still refuse to use CLEO 4.3 ...
Well I don't have much to say to that, that's just how some people are, and you can't do much about that, no matter how hard you try. But IMO you shouldn't be much worried about the backward compatibility, progress can't be stopped, but can be slowed down by caring about backward compatibility, and the worst thing is, that that compatibility will eventually disappear, so from my point of view, you just slowed down you progress for no reason, + if a new version of something is uncompatible with the old one, you can look at it from 2 points of view:

1st - nothing works we are doomed
2nd - nothing works now we can have a clean start and this time we are gonna do things in a more propper way that we did them before (well ok that was obvious learning from our mistakes = learning to script)


EVEN ROCKSTAR made some REALLY stupid mistakes writing in their original 'native' language.
skipped


I'm interested to know what your first 'exposure' to CLEO/SCM has been.
I've Just opened main.csm looked at some code pieces, that revealed the syntax of the most basic commands, then searched some additional comamnds on the internet, stumbled upon CLEO, downloaded it, found out that I can use 34 local vars, and that I shouldn't use global vars, and that was it, that was enought for me to write what I wanted (OK I'm gonna be lectured, cos of this)


I can't act like I'm the only one who knows all these things about the scripting engine...
skipped, contains the description of your early years in scripting, which are identical to the early years of pretty much every scripter, (especially those, who ended up as pros)


... OH RIGHT, the WAIT problem...
OK, I totally agree with this:

CODE
:ugly_label
wait 0 ms
// does stuff
if SOMETHING
jf @ugly_label_2
jump @ugly_label

:ugly_label_2
wait 0                                    // this wait serves no purpose, and clearly shows that the guy who did this, just copied 2nd script in w/o thinking
// do stuff here for some reason
if SOMETHING
jf @ugly_label_2 // this jump should go to the @ugly_label, this will caunse the most bugs
jump @ugly_label_3 // etc



QUOTE
If there's only one WAIT, there's no question. If the code is all procedural, and based on a combination of events, could end up WAITing in a variety of places, you'll lose "guarantees" of your script.


Well, I would have to partially disagree with this one, cos yes if you use 2 waits you are going to lose "guarantees", but only in some cases, for example, in my script a have 3 "functions", 1st checkes if var 0 == -1, then does something, and var 0 is set to -1 by another script, that won't change it from -1, so I can wait as long as I want, 2nd is a save check (values 17 and 18 will stay in that adress till some next menu is shown, which brings a human factor in the play, and you can safely assume (ok, you can't safely assume anything) that those values will be there at least for a 0.1s, (OK now you are gonna disagree with me, but whatever)),3rd checkes if a key was pressed then does something, ok here we can also wait, cos if that thing, that the palyer want to happen doesn't happen he is just gonna hold the key longer (I'm talking about time like 0.1s or less)

so if you decompose your code like that, and you can see that, it doesn't contain any critical events, like, something that chnges it's value every instance, and you have to keep up, you actually can afford to wait, OK now you may say that I'm waiting for a 0.5s after the save, and that's just too much, well ,it is and it isn't, considering normal game save (sorry but I consider save anywhere as cheating, and thus I don't care if it doesn't work with it (that's what you get for cheting anyways)) you can't do anything after a safe for 0.5s, it's written in main.csm in @SUB_RESTORE_CONTROL (wait 500 then Player.CanMove($PLAYER_CHAR) = True), so I don't have to worry about the fact, that the player can save again in that time, my 1st "function" is time independent and my 3rd is a key press ,so the player just gonna have to hold that key down, no big deal

QUOTE
WAIT is like a macro for "do{}while(true);"

What? That's how they implemented that command, Wait command in multithreading should stop the thread for a certain ammount of time, thus giving extra CPU power to the rest of the threads, that is the purposse of wait, so if R* implemented it the way you just described, I fully understand your hate towards that command, but I wouldn't discard it's use, cos it's still less CPU demmanding to wait on a loop, that doing something like file reading + when you actully need to "wait" it's still easier to write wait, that use timer (you don't want to check anything just wait)



QUOTE
When you use a WAIT, other scripts run (or they may not if yours is last)

What? (I demand further explanation, cos that is one of those things that must be mentioned)

ranting about your rants and comunity
I understand what you wanted to say, but I since it's not really related to me,I don't feel the need to comment on that


By the fact your else_gotos are 'else_jumps'
What else_gotos?

QUOTE
It's a shame you're apparently only here temporarily though, as I have a feeling you're one of the few that might actually read - and god knows, even appreciate - the abuse of time that are my rants.

Well, I read which a lot of people should try at least from time to time.
and I kind of appreciate those rants, cos they provide informations or/and something to argue about and I appreciate informations (and arguing)




QUOTE
I am honestly sorry for writing all this, but it's nice to have written it somewhere.

Yeah, I know that feeling, well as long as you are OK with tha fact, that this topic is pretty much a dicusion between the 2 of us (which means that we are probably offtopic) I'm gonna continue in this discusion.

This post has been edited by miki45: Jun 28 2014, 08:46 AM
Go to the top of the page
 
+Quote Post
Wesser
post Jun 28 2014, 10:53 AM
Post #14


The Assistant

Posts: 84
From: Matera, IT
Joined: 16-June 11



QUOTE (Deji @ Jun 28 2014, 03:05 AM) *
I can't act like I'm the only one who knows all these things about the scripting engine, but I'm sure anyone will agree I've cared the most.

I'm sorry to interrupt your keen argument with a short and silly sentence but... may I disagree? tongue.gif
Go to the top of the page
 
+Quote Post
Deji
post Jun 28 2014, 12:34 PM
Post #15


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



QUOTE (miki45 @ Jun 28 2014, 09:04 AM) *
Some people still refuse to use CLEO 4.3 ...
Well I don't have much to say to that, that's just how some people are, and you can't do much about that, no matter how hard you try. But IMO you shouldn't be much worried about the backward compatibility, progress can't be stopped, but can be slowed down by caring about backward compatibility, and the worst thing is, that that compatibility will eventually disappear


Oh yes, I believe that. But since it is still a relatively recent and active problem, I thought I'd mention it. I only just released 4.3 earlier in the year, and I went to great lengths to fix most of the highly regarded mods such as that missile script and make CLEO 4 a bit more accepted, yet there's still some scripts here and there which I'd just say were terribly written from the start, but some people can't look past it tongue.gif

QUOTE
"I've Just opened main.csm looked at some code pieces"


Well yeah, the decompiled syntax aint much of a syntax at all. Everything lacks consistency, and it mostly can just be called a list of all the lowest-level elements tongue.gif

I was told I should have mentioned this... http://www.gtamodding.com/index.php?title=SCM_language - Thanks Wesser.
It's a little outdated now and had errors from the beginning (Sorry Wesser tongue.gif), as with almost every source of information, but it gives an idea of how much more complex the original language tried to be. It has since gone on to be recreated as a virtual machine using its own assembly language in GTA IV, and is much harder to crack. Yet, at the moment my feelings are that instead of cracking this SCM engine, it would have been much easier and better to implement a totally new one.

QUOTE
I can't act like I'm the only one who knows all these things about the scripting engine...
skipped, contains the description of your early years in scripting, which are identical to the early years of pretty much every scripter, (especially those, who ended up as pros)

Ya, I do romanticise history quite a bit tongue.gif


QUOTE
Well, I would have to partially disagree with this one, cos yes if you use 2 waits you are going to lose "guarantees", but only in some cases, for example, in my script a have 3 "functions", 1st checkes if var 0 == -1, then does something, and var 0 is set to -1 by another script, that won't change it from -1, so I can wait as long as I want, 2nd is a save check (values 17 and 18 will stay in that adress till some next menu is shown, which brings a human factor in the play, and you can safely assume (ok, you can't safely assume anything) that those values will be there at least for a 0.1s, (OK now you are gonna disagree with me, but whatever)),3rd checkes if a key was pressed then does something, ok here we can also wait, cos if that thing, that the palyer want to happen doesn't happen he is just gonna hold the key longer (I'm talking about time like 0.1s or less)


You can wait as long as you want in a 'mainloop', too. Better yet, you can choose what you actually want to wait for, which generally won't be time-based. I ESPECIALLY wouldn't use a timed WAIT for a keypress... what if the user lets go of the key and presses it again before the time is over? Nothing happens, which is a bug. Questions about using keypresses are quite common from new scripters, who will reveal to be doing it using some low-construct code which completely changes its position. You can write ANYTHING exactly the same with a 'mainloop', but you can't go through all the same complexities when the script is jumping around between several different loops, each of course requiring their own WAIT. It's the main loop, so really it should never stop running.


QUOTE
so if you decompose your code like that, and you can see that, it doesn't contain any critical events, like, something that chnges it's value every instance, and you have to keep up, you actually can afford to wait, OK now you may say that I'm waiting for a 0.5s after the save, and that's just too much, well ,it is and it isn't, considering normal game save (sorry but I consider save anywhere as cheating, and thus I don't care if it doesn't work with it (that's what you get for cheting anyways))


Imagine every program you installed on the computer reduced the amount of other programs you could install without your computer constantly blue-screening. You'd be pretty angry at those programs for being built in such a way that is so vulnerable to each other. In reality, this is probably all the operating systems fault for making programs share so many resources, but if the programmer knows there's something that can be done to reduce this problem, it should be somewhat of an obligation. We can all act like ours is the most important script, and others merely get in the way, but that goes against the very idea of CLEO, really.

QUOTE
you can't do anything after a safe for 0.5s, it's written in main.csm in @SUB_RESTORE_CONTROL (wait 500 then Player.CanMove($PLAYER_CHAR) = True), so I don't have to worry about the fact, that the player can save again in that time, my 1st "function" is time independent and my 3rd is a key press ,so the player just gonna have to hold that key down, no big deal


Well, more specifically, that routine is called after loading, and not just after a save. This PSAVE1 script is a very tricky side-script, yet still isn't an exception, if you read it in a more original high-level construct:
https://pastebin.com/8JKBkGGr

After sub-ing to PSAVE1_923, the parent code then has to check again if the $PLAYER_CHAR is 'defined' (or rather 'IS_PLAYER_PLAYING' - checking if the player isn't being "wasted" or "busted", without actually checking at all if the player even exists), and WAITs are further used for reasons that can't really be explained without asking R*. Where it WAITs for 500 'ms', which is only at least half a second, it has to repeat that check again. What happens is, it loses guarantees about what is still true about the game. The player character could have been deleted, the player could have been killed, they might be in a totally different area of the map triggering other scripts, anything (so wonder why they still WAIT 500ms even though the player might not be 'playing'?). We still don't understand all these weird intricacies, or why R* felt the need to do so many checks we can't see any proper reason for, yet they must have known something we didn't. We still can't guarantee what will still be true or false after a WAIT, but it's much easier to track and follow the logic in one loop with a single WAIT. You can easily repeat checks without repeating code, you can set variables to essentially change 'states' and exclude certain parts. It's all about control and predictability. If you had a less visual process going on, and there were WAITs in all sorts of places, when it crashes, where do you start analysing the code from? I know I'd start at the WAIT, and work my way completely downwards and following the logic for that point.

And look, the entire script still runs in a loop with one main WAIT. The only time another one occurs is a special circumstance.. the game is saved, which is a whole world of its own complexities. It's nicely structured and easy to follow, except in the instance where it WAITs.


QUOTE
What? That's how they implemented that command, Wait command in multithreading should stop the thread for a certain ammount of time, thus giving extra CPU power to the rest of the threads, that is the purposse of wait, so if R* implemented it the way you just described, I fully understand your hate towards that command, but I wouldn't discard it's use, cos it's still less CPU demmanding to wait on a loop, that doing something like file reading + when you actully need to "wait" it's still easier to write wait, that use timer (you don't want to check anything just wait)


Well, I'm not saying you have to use a WAIT value of zero all the time, but you could in fact use a mainloop which only executed your script every ~250ms, it's a often used technique to get "more CPU power" (though today's most common CPU's are overpowered when it comes to this game anyway) by essentially de-prioritising the script. And that's great, especially if you only do it once in the script, as otherwise you'll be placing other WAITs that will, assuming the script eventually has to go back to where it started, accumulating WAITing time over its execution. You have your main WAIT, then another one occurs, and unless you intentionally skip that WAIT after your other one, your script WAITs longer than you expected. But if you do skip that WAIT, you somewhat have to make up for it in case the specific WAIT time happens to be more important.

GTASA doesn't multithread. All scripts run sequentially and a WAIT stops executing one immediately until the next frame. There should be considered no such thing as a "thread" within the actual language, either. It's again a term which was made up by those cracking the engine. There are scripts and sub-scripts, and each one can have separate positions, but at any time outside of execution, every script is WAITing. With R*'s least important scripts, they could WAIT wherever, because their other script is still running as a 'mainloop' - in fact, :MAIN is that mainloop which (from ':MAIN_4075', anyway) constantly runs, and never WAITs more than it needs to. It's the MAIN part of the script, and since in our case we only get one script, we don't want our script to get trapped in some subroutine temporarily ever, mostly just in case there's a strong requirement later to add something else which should run the whole time. A main secction is a guarantee of where you can add future code, as well as what code is running the entire time. And there's no way to 'abort' a WAIT from a subroutine.


Again, this can all be taken subjectively, and you could still say a WAIT anywhere is okay in its own cases, but not needing to do that is almost certainly better.


QUOTE
What else_gotos?


The original command name for a 'jump' was actually 'GOTO'. The 'jump' name is made up by the original researchers of the SCM and never changed since, except by me, along with a thousand other corrections and improved naming conventions. The "SCR for SB" thing I linked to. It causes incompatibility with most code written using the original SB files (a major reason people don't use it - curse peoples expectancies of 'compatibility') but the later SB3 versions now have a "GTA SA SCR" mode so the two versions can be switched between more easily, which I'm pretty joyous about.

There's no reason not to use it aside from the compatibility thing if you ask me. People will say stuff like "I'm used to all the names of the current", but most of those names are wrong and cause many awkward mistakes in scripts, either by them or people who read them. It allows you to drop (most of - there are still unknown things, but a lot less) those 'XXXX:' opcodes and just stick to the actual (real) command names and it tries to restore proper naming conventions.

This also goes well with it: https://pastebin.com/j3qVN8by
It simply defines constants which are more like what R* wrote with, plus a whole load more that I felt were necessary at the time.

All in all, SCR-ish code starts looking like this: https://pastebin.com/Dhwg3KXk

But I think the best living example of SCR is in the one script I wrote for the original version of my compiler https://pastebin.com/DHxCSF7Z
With any luck, all scripts will start to be writeable like that in future.


QUOTE
Yeah, I know that feeling, well as long as you are OK with tha fact, that this topic is pretty much a dicusion between the 2 of us (which means that we are probably offtopic) I'm gonna continue in this discusion.


Well, it started off as a tutorial. And it's hard to just say a tutorial is teaching bad habits without going through all the intricacies of why or sounding like I'm just pulling a giant opinion out of where the sun don't shine tongue.gif


QUOTE (Wesser @ Jun 28 2014, 11:53 AM) *
I'm sorry to interrupt your keen argument with a short and silly sentence but... may I disagree? tongue.gif


Yes you may, though you're quite a ninja most of the time and I forget you're here until you jump out of the corner and attack us with some surprising information tongue.gif

And hey, most everything I know about it now I learned from the basis of what are now 7-8 year old tutorials and my own (mostly accidental in the beginning) snooping. Nothing else was ever available, and more and more people quit trying to document every last opcode, while I kept trying to get every last unknown on the list with only the help of my usual contacts, so I had to conclude I was the only person who cared. It started to get more attention again once IV was having its engine cracked, though. I originally learned C++ purely to extend this damn cheap scripting engine - if that isn't obsession at its highest, I don't know what is tongue.gif


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 28 2014, 02:13 PM
Post #16


The New Guy!

Posts: 9
Joined: 26-June 14



QUOTE
Again, this can all be taken subjectively, and you could still say a WAIT anywhere is okay in its own cases, but not needing to do that is almost certainly better.


Well, it seems, that we've reached an agreement (I know, that it may suprise you, but I'm also against using wait more that once in a mainloop, I just wanted to point out that there are some cases when this may be let's say acceptable (like my script that is stricly for my personal use, so i don't really care about compatibility and things as such))

OK just to wrap some things up

what about this save check code?
CODE
CONST
    MenuID         = 0@
    Tvar           = 1@
END

:CheckSave
READ_MEMORY 0xBA68A6 1 0 MenuID // ID of the last shown menu

IF Tvar == 0
THEN
    IF OR
        MenuID == 18 // save successfull
        MenuID == 19 // save successfull    
    THEN
        READ_MEMORY 0xBA68A7 1 0 Tvar   // index of the last save
        
        Tvar now contains the index of the save
        - do your stuff
        
        Tvar = 1
    END
ELSE
    IF OR
        MenuID > 19
        MenuID < 18    
    THEN
        Tvar = 0
    END
END

RETURN


This post has been edited by miki45: Jun 28 2014, 02:16 PM
Go to the top of the page
 
+Quote Post
Wesser
post Jun 28 2014, 02:55 PM
Post #17


The Assistant

Posts: 84
From: Matera, IT
Joined: 16-June 11



QUOTE (Deji @ Jun 28 2014, 02:34 PM) *
I was told I should have mentioned this... http://www.gtamodding.com/index.php?title=SCM_language - Thanks Wesser.
It's a little outdated now and had errors from the beginning (Sorry Wesser tongue.gif)...

No worries, it's been a year since I was last allowed to edit it because of GTAModding's "perennial" update. I have to rearrange these information and fill the updated version of that article archived on my HDD.

QUOTE (Deji @ Jun 28 2014, 02:34 PM) *
Yes you may, though you're quite a ninja most of the time and I forget you're here until you jump out of the corner and attack us with some surprising information tongue.gif

Yeah, you hit the nail on the head. I'm not a chatty dude (especially when I write something in foreign-language) and I think it would be hard to be so like you, tongue.gif though I read your long posts very gladly. thumbsup.gif
Go to the top of the page
 
+Quote Post
Deji
post Jun 28 2014, 02:58 PM
Post #18


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



So readable smile.gif

Another interesting thing I should have noted about an exception of WAITs in mission scripts is that they, as well as subroutines are handled a lot differently. If the player dies or gets arrested, any mission script (if the mission flag is set and the mission hasn't disabled "wasted/busted check") will have its WAIT time cancelled, and any subroutines will be returned to the highest level (like a stack unwind). The wasted_busted flag is then set, and the 'flag_player_on_mission' is unset. This kind of behaviour only occurs in mission scripts, so a scripts behaviour discreetly changes depending on this fact. I've seen people attempt to copy entire an missions code to a CLEO script, so that's quite funny, especially since CLEO has so many differences with SCM scripts as well tongue.gif

That's probably the last bit of information I can squeeze out of that branch.


--------------------
Go to the top of the page
 
+Quote Post
miki45
post Jun 28 2014, 03:09 PM
Post #19


The New Guy!

Posts: 9
Joined: 26-June 14



OK edited the first post, now it should give some at least half-right informations
Go to the top of the page
 
+Quote Post
Reply to this postStart new topic

2 User(s) are reading this topic (2 Guests and 0 Anonymous Users)
0 Members: