[Tutorial] One example of using "states" in PAWN within SA:MP.
#1

So, ever since I found out that I can use state /* .. */; in PAWN, I figured this would help me a ton while scripting bigger gamemodes and don't want to use ALS hooking or y_ini to load and create textdraws, objects and so on from other files. So basically, as stated in the PAWN language documentation:
Quote:
pawn also supports multiple automatons, and each state is part of a particular automaton. The following script implements the preceding state diagram (in a single, anonymous, automaton). To differentiate plain text from comments,
both are output in a different colour.

With the example given at the PDF file, this is the PAWN code.
PHP Code:
main()
    
state plain
    
@keypressed(key) <plain> {
        
state (key == /slash
        
if (key != /)
            echo 
key
    
}
    @
keypressed(key) <slash> {
        
state (key != /plain
        state 
(key == *comment
        
        
echo /’ /* print ’/’ held back from previous state */
        
if (key != /)
            echo 
key
    
}
    @
keypressed(key) <comment> {
        echo 
key
        state 
(key == *star
    
}
    @
keypressed(key) <star> {
        echo 
key
        state 
(key != *comment
        state 
(key == /plain
    
}
    echo(
key) <plainslash>
    
printchar keyyellow
    
echo(key) <commentstar>
    
printchar keygreen
    printchar
(chcolour) {
        
setattr .foreground colour
        printf 
"%c"ch
    

Now if you learned PAWN within SA:MP, then this code will look a little bit different for you, and in-fact it won't be valid code to run in PAWNO, however in the PAWN IDE by CompuPhase, this will be runnable - being the "real" PAWN syntax. Since PAWN runs differently in SA:MP, there's a few things I've tried but will not work, for example:
PHP Code:
state (variable == status/* .. */
Will not work, we cannot define a state after a variable in the native/callback.

So how does state work in SA:MP?
There's a few things I had ideas to use this for, however I figured out it will not work. For example, I was gonna use a single callback for tens of MySQL query callbacks, but unless they're global and not ID'd (i.e. playerid'd) and aren't in threaded, the query might assume the wrong state and call the completely wrong callback state. For example..
PHP Code:
forward public @OnQueryReceived();
public 
OnGameModeInit() {
    
/* .. */
    
state QUERY_SETTINGS;
    
mysql_pquery(/*..*/"@OnQueryReceived"/* .. */);
}
public @
OnQueryReceived() <QUERY_SETTINGS> {
    
/* .. */

That code is an example of how you shouldn't use state, because this query might be ran back after 4 other queries, and then the state will be the wrong one for the wrong query.

So what can we use state's for? One callback that I use states for are OnGameModeInit in order to split up multiple use. Note that this is just one example of state's can be used and it's got a lot of other usages as well.

PHP Code:
public OnGameModeInit() <> {
    
/* .. */
    
state CREATE_OBJECTS;
    
OnGameModeInit();
    
state CREATE_TEXTDRAWS;
    
OnGameModeInit();
}
/* another file */
public OnGameModeInit() <CREATE_OBJECTS> {
    
CreateObject(/* .. */);
}
/* another file */
public OnGameModeInit() <CREATE_TEXTDRAWS> {
    
TextDrawCreate(/* .. */);

Here you can see that I used <> in the first OnGameModeInit, why? Because otherwise it would never been called, if you define one state on 1 out of 2 (or more) callbacks - the one without a state will not be called, and since OnGameModeInit are called before main(), we have no choice but to leave the state empty. Then on the second file, we use one of the states we defined in the <> callback, and this one will be called as we call OnGameModeInit as an native, it will redirect itself to that one callback only with the state. Everything else will be dismissed.

So to get an output of using states, I made an example code..
PHP Code:
#include <a_samp>
forward public @stateCheck();
main() {
    for(new 
indexindex 5index++) {
        new 
call random(3)+1;
        
printf("loop #%i was given call %i"index+1call);
        switch(
call) {
            case 
1:    state STATE_CALL_1;
            case 
2:    state STATE_CALL_2;
            case 
3:    state STATE_CALL_3;
            case 
4:    state STATE_CALL_4;
        }
        @
stateCheck();
        print(
" ");
    }
}
public @
stateCheck() <STATE_CALL_1> {
    print(
"manual state 1 called");
}
public @
stateCheck() <STATE_CALL_2> {
    print(
"manual state 2 called");
}
public @
stateCheck() <STATE_CALL_3> {
    print(
"manual state 3 called");
}
public @
stateCheck() <STATE_CALL_4> {
    print(
"manual state 4 called");

And of course, the outcome is:

Code:
loop #1 was given call 1
manual state 1 called

loop #2 was given call 2
manual state 2 called

loop #3 was given call 1
manual state 1 called

loop #4 was given call 2
manual state 2 called

loop #5 was given call 3
manual state 3 called
Hopefully this has given you an idea of how to use the keyword state within PAWN, and if you yet haven't understod - try reading the PAWN language PDF file here;
https://raw.githubusercontent.com/co.../pawn-lang.pdf
Reply
#2

Well explained. Good job.
Reply
#3

I never really used state because no one used it back then and now and the reason that it was mostly unknown to most here till now!

Well explained I'll give you that.
Reply
#4

This is great information. I have particularly never used state just like Gammix but from what I can see it could be extremely useful.
Reply
#5

Very well described, Looks unknown to me, Never seen it in in such script, Will give it a try ,
Anyway can you tell me that what's the difference in forward public @OnQueryReceived(); and forward OnQueryRecieved();
and what does this @ means? I see it in some script but couldn't identify? He's using these on many statements.
Reply
#6

Quote:
Originally Posted by FuNkYTheGreat
View Post
Very well described, Looks unknown to me, Never seen it in in such script, Will give it a try ,
Anyway can you tell me that what's the difference in forward public @OnQueryReceived(); and forward OnQueryRecieved();
and what does this @ means? I see it in some script but couldn't identify? He's using these on many statements.
@ basically defines that x are public in other words. It's just an character allowed in natives and callbacks and I missuse it for callbacks that I define for easier use if someone else would read my code. There's no performance change though.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)