Wait for startAction to complete within a function

  • #1, by cr34m3Saturday, 08. March 2014, 18:25 11 years ago
    Ok, I promise this will be my last LUA question for a while. smile

    I’ve got a function that gets called with the execute script command. It broadly works like this:
    function ClickAction(S)
        while SomeCondition do	
            .. do some calculations to determine mySceneAction
            startAction(mySceneAction)
            .. do some other calculations
        end
    end
    


    All the calcs are fine, all the right actions start, there’s only one problem: I can’t seem to get it to wait until the completion of sequential actions. It’s like the startAction gets queued until the script has finished.

    To better illustrate the problem, I’ll use this example: I’m moving my character from A to C through B (I’ve clicked on C). I’ve got actions for Send Current Character to B and Send Current Character to C. The first iteration of the loop starts the Send Current Character to B action, the second iteration starts the Send Current Character to C action, the loop exits and the character moves from A to C.

    Is there no way to wait for an action to complete before moving on with the code in the script? I’ve tried timers and animation states, but neither work as the character isn’t doing anything until the loop exits.

    Again, any help will be appreciated.

    Newbie

    72 Posts


  • #2, by SimonSSaturday, 08. March 2014, 20:07 11 years ago
    The actions are done before drawing, it's like a pile of actions that are active that are worked through. So calling startAction only throws an action on that pile and does nothing. Calling an action in an action works differently it throws the action on the pile and executes it until it is paused, that can happen with every action part that is not immediately done, examples are "Display Text", "Send character to something", "Change Scene", "wait for animation/character/sound", such things. Then this action is paused and the old one resumes. So much to understand whats going on.
    You can't wait in Lua for anything, cause nothing is executed until you return. You can do something like checking if the action is done in your main loop, that gets complicated, haven't done that yet myself.
    You can set a condition that your action is finished, that again would need a handler in your main loop.
    Last way is you call your script at the end of the action.

    Thread Captain

    1580 Posts

  • #3, by afrlmeSaturday, 08. March 2014, 20:39 11 years ago
    I find it better to avoid the mainLoop handler when possible. Also try to refrain from using while/repeat loops in Lua. I've found that they can sometimes crash the vs player.

    If possible, I prefer to execute functions & returns via actions/animation frames, as & when I need them.

    One thing to take note of mainLoop is that the time between loops varies by x ms, on each loop. For instance I could technically create a pause/delay value inside of a Lua function by querying the getTime() function & then checking if current time is more than the initial value. But it is not accurate to the second or millisecond etc.

    Imperator

    7278 Posts

  • #4, by cr34m3Saturday, 08. March 2014, 22:29 11 years ago
    Hmmm... problem is my script determines whether an action should happen or not, and if so, which one. As per the example, you click on C, but the character first moves to B. So calling it after the action isn't really an option at present.

    Oh well, it's not a train smash -- the sequence works fine, it just feels... clunky. But thanks for the suggestions, maybe I'll come up with some other way of doing this.

    Another thing (to help me understand a bit better): Simon mentioned that nothing gets executed until you return, but the behaviour of VS to a test is not making sense to me.

    I define an action as follows: (Immediate on Left Click)
    1. Execute script 'ClickAction(S)' [this function now has a single startAction(MoveToB) and then returns (no while loop)]
    2. If SomeCondition then
    3. Call action 'MoveToC' [ideally I'd calculate this with a function, but I did a normal action call to test]
    4. End if

    Now when I click on C the character just moves directly from A to C (as per the final action call). Could someone with more knowledge than me please elaborate on when exactly actions get executed.

    Newbie

    72 Posts

  • #5, by SimonSSaturday, 08. March 2014, 23:04 11 years ago
    To make clear what happens I wrote the pile of actions next to the call:
    1. Execute script -> Current action, MoveToB
    2. Call action MoveToC -> Current action, MoveToB, MoveToC
    Now the action is finished and the rest gets worked on, first MoveToB, character destination will be set, then MoveToC, character destination gets overwritten with C.

    Thread Captain

    1580 Posts

  • #6, by afrlmeSaturday, 08. March 2014, 23:28 11 years ago
    haha oh dear, this whole topic is starting to get confusing...

    if you could share the exact script you are using/working on (with comments, so I know what's what) & then explain in detail (layman terms) exactly what you are wanting to do, then maybe I can help.

    As this thread currently stands... I'm getting a headache.

    Imperator

    7278 Posts

  • #7, by cr34m3Sunday, 09. March 2014, 08:59 10 years ago
    To make clear what happens I wrote the pile of actions next to the call:
    1. Execute script -> Current action, MoveToB
    2. Call action MoveToC -> Current action, MoveToB, MoveToC
    Now the action is finished and the rest gets worked on, first MoveToB, character destination will be set, then MoveToC, character destination gets overwritten with C.

    Ah thanks, I think I get it now. I think I'll try (as AFRLme) suggested to get the function to return something and then run the actions from the VS interface rather than LUA (to avoid this destination overwriting).

    AFRLme; I'll bash the code a bit more and revive this topic later if need be. It's 211 lines of my not-so-elegant code -- and you thing you have a headache now? grin But thanks for the offer.

    Newbie

    72 Posts

  • #8, by afrlmeSunday, 09. March 2014, 13:24 10 years ago
    the code usually makes more sense than the person trying to explain the code in words.

    211 lines? sounds a bit steep. biggest script I wrote so far was the 24hr timer script - which was around 300+ lines, if I remember correctlty, on my first try - & even that we managed to cut in half, more or less.

    Imperator

    7278 Posts

  • #9, by NigecSunday, 09. March 2014, 17:05 10 years ago
    I'm on with a C# project and everytime I look at it I find better ways to do the script, at one point I had a section of code that was very.. mechanical in its approach, way to much code in the end we got it down to 10 lines, a second set of eyes really helps sometimes wink

    Key Killer

    627 Posts

  • #10, by cr34m3Sunday, 09. March 2014, 19:12 10 years ago
    Ok, so here’s the code. I haven’t made an effort to tighten it up, so don’t be too harsh. smile

    What I’m implementing is a klotski-style sliding block puzzle. I’ve defined the 11 blocks as characters and the 4x5 board as 20 objects. Everything has been aligned to the top left corner (of characters and board spaces).

    Clicking on a block switches it to the current character. Clicking on a space executes the OnSpaceClick function with the corresponding space index, e.g. OnSpaceClick(42) for a click on the space in row 4, column 2.

    The code then gets the block info, determines what moves are required, checks if those moves are possible (pseudo collision checking) and moves a single space in an available direction. Originally there was a while loop to continue until the destination was reached or no moves were available anymore (in the selected direction), but I’ve removed it. Also note that for the startAction command I’ve defined a ‘Move current character to object’ for each of the squares.

    Now regardless of the code not being very pretty, it does work as intended. It’s the animations which are my problem. Due to the stacking of action commands (as elaborated by Simon) a double move (e.g. MoveTo51 followed by MoveTo41) effectively becomes a single move (i.e. MoveTo41). This is the reason I’ve removed the original While loop – only single spaces are moved per click now.

    Finally, I know I’ve taken some liberties in the coding where expressions are not 100% generic, but specific to our game.

    Newbie

    72 Posts

  • #11, by afrlmeSunday, 09. March 2014, 21:46 10 years ago
    Ok I think I know what you are getting at & damn... sliding puzzles; both mine & Nige's (methinks?) least favorite form of puzzle razz

    quick tip: if you want to keep scripts compact & use less lines then don't drop lines for every little thing... sometimes you can create a query or function on a single line.
    if bsizec == 1 and bsizer == 1 then
    ready = board[row(curpos)][col(curpos)+1] == 0
    elseif bsizec == 2 and bsizer == 1 then
    ready = board[row(curpos)][col(curpos)+2] == 0
    elseif bsizec == 1 and bsizer == 2 then
    ready = board[row(curpos)][col(curpos)+1] == 0 and
            board[row(curpos)+1][col(curpos)+1] == 0
    elseif bsizec == 2 and bsizer == 2 then
    ready = board[row(curpos)][col(curpos)+2] == 0 and
    board[row(curpos)+1][col(curpos)+2] == 0
    end
    

    to...
    if bsizec == 1 and bsizer == 1 then ready = board[row(curpos)][col(curpos)+1] == 0
    elseif bsizec == 2 and bsizer == 1 then ready = board[row(curpos)][col(curpos)+2] == 0
    elseif bsizec == 1 and bsizer == 2 then ready = board[row(curpos)][col(curpos)+1] == 0 and board[row(curpos)+1][col(curpos)+1] == 0
    elseif bsizec == 2 and bsizer == 2 then ready = board[row(curpos)][col(curpos)+2] == 0 and board[row(curpos)+1][col(curpos)+2] == 0 end
    

    or for example....
    if something then do something; print("something"); return something
    elseif other then....
    etc...
    

    I prefer to keep things compact but still keep them structured. It really helps keep amount of lines down; same goes for incrementing tables.
    t,= {}
    t[1] = ...
    t[2] = ...
    etc...
    
    -- to
    
    t = {something, "something_else"}
    
    -- or
    
    t = {"name" = "bob", "profession" = "builder"}
    

    just a few examples on keeping scripts small. also variables are good for storing links & getObjects into for quick access.

    Imperator

    7278 Posts