[WoW][3.0.9] A way to get return values from Lua Functions menu

User Tag List

Results 1 to 7 of 7
  1. #1
    ramey's Avatar Member
    Reputation
    45
    Join Date
    Jan 2008
    Posts
    320
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [WoW][3.0.9] A way to get return values from Lua Functions

    Well, it is a pretty simple way of getting return values, and there certainly are better ways.

    But however, this is a quick way to do it.

    As you should know, using Lua_DoString the return values are popped off the stack before you can parse them, and this is due to a setting that wow uses when calling lua_pcall.

    However, if you call it inside a registered function, the return values aren't popped off the stack until outside the function.

    So, you can do is register your own Lua_CFunction and execute your Lua functions in it and then pass the return values to a vector. (Don't forget to patch the invalid pointer check.)

    Something like this:

    Code:
    //wherever you want
    std::vector<const char*> vResults;
    
    //from lua sdk
    typedef int ( __cdecl * Lua_CFunction )( void * pState );
    
    //our own function
    int OurFunction( void * L )
    {
         //clear the vector if its not empty
         if ( !vResults.empty() )
            vResults.clear();
    
         //get count of returns on stack
         int n = lua_gettop(L);
    
         //loop to retreive these
         for (int i = 1;i<=n; i++)
            {
                  //using lua_tostring to get the result
                  const char * pszResult = Lua_tostring(L, i, NULL);
                  //make sure its valid
                   if (pszResult && pszResult[0])
                  {
                      //add result to vector
                      vResults.push_back( pszResult );
                   }
            }
    
    //returning 0 args
    return 0;
    
    }
    
    //register our function
    Lua_Register( "OurFunction", OurFunction );
    
    //get return values like this:
    Lua_DoString("OurFunction(GetTotalAchievementPoints())","OurFunction(GetTotalAchievementPoints())", NULL);
    
    //converting from const char * to int correctly( quick c style )
    int iAchievementPoints = atoi(vResults[0]);
    I just put in some quick comments! I don't think they matter too much, it is all simple enough.

    I hope this helps someone out, if you have any problems feel free to ask.

    Thanks to Bobbysing for helping me out countless times!

    :wave:

    These ads disappear when you log in.

  2. #2
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1356
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You should write a DoString wrapper and make one of the params a std::vector<std::string>& rather than using a global variables. Its not thread safe and will get messy quickly.

    Also, your function doesn't account for when bools return false so you'll be missing certain values.

    If ToString returns a null string its because WoW has called PushNil on a boolean false. In that case you want to push back "nil" as a string or "0" depending on whether you want it to be output like WoW ouputs it or to make more 'sense' and pair with the '1' returned by boolean trues.

    Plus, an even better way is to make your callback take TWO params. The code to be executed, and a pointer to a class. Define a base class that has virtual functions for adding results etc, then inherit from that and provide implementations for returning a vector, a string, getting a single value, etc etc. Then just call execute with (
    this,Code()) or whatever.

    Might take a while to get working properly, but its well worth it. Makes your LUA based code about a million times easier to understand and maintain.

  3. #3
    ramey's Avatar Member
    Reputation
    45
    Join Date
    Jan 2008
    Posts
    320
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You are completely right Cypher, I wanted something simple and easy to implement as I could not get my own dostring working, calling pcall so it doesn't pop values off etc.

    Great suggestions again, thanks.
    Last edited by ramey; 03-22-2009 at 03:15 PM.

  4. #4
    malingshu's Avatar Member
    Reputation
    17
    Join Date
    Dec 2008
    Posts
    49
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thank Q. helped a lot

  5. #5
    SKU's Avatar Contributor
    Reputation
    306
    Join Date
    May 2007
    Posts
    565
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Doing this via injected DLL = easymode!

    Nah just kidding, well done.

  6. #6
    jjaa's Avatar Contributor
    Reputation
    245
    Join Date
    Dec 2006
    Posts
    562
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice work, although i must say that using a vector will properly end up being annoying and messy when getting multiple return values. Surely it would be better to just make a function that gets the return value at X index.

    Like:


    Code:
    std::string getLua(std::string lua, unsigned int Index = 1)
    {
        std::string Command = (boost::format("OurFunction(%1%)") % lua).str();
    
        globalIndex = Index;
    
        MyDoString(Command.c_str()); //Call our lua func
    
        return globalLuaRet; //an std::string holding our return value
    
    }


    i just made that up then but i hope you get the idea.

    Either way its a great method, Thanks Cypher and ISXWoW!

  7. #7
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1356
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by jjaa View Post
    Nice work, although i must say that using a vector will properly end up being annoying and messy when getting multiple return values. Surely it would be better to just make a function that gets the return value at X index.

    Like:


    Code:
    std::string getLua(std::string lua, unsigned int Index = 1)
    {
        std::string Command = (boost::format("OurFunction(%1%)") % lua).str();
    
        globalIndex = Index;
    
        MyDoString(Command.c_str()); //Call our lua func
    
        return globalLuaRet; //an std::string holding our return value
    
    }


    i just made that up then but i hope you get the idea.

    Either way its a great method, Thanks Cypher and ISXWoW!
    That's the entire point of my second suggestion.

    Pass the function a base class pointer and write a derived class for all the possible formats you could want. Also, if you want multiple return values (as is often the case) then getting them one by one will then become the 'annoying and messy' one.

    Inheritance + virtual functions > you.

    P.S. GlobalLuaRet? Argh. THREAD SAFETY MOTHER****ER!

Similar Threads

  1. Best way to get Z value via X Y
    By SwInY in forum WoW Memory Editing
    Replies: 14
    Last Post: 12-21-2011, 11:02 AM
  2. Assembler Injection -> Getting return value?
    By streppel in forum WoW Memory Editing
    Replies: 11
    Last Post: 06-05-2011, 07:27 AM
  3. Easy way to get free WoW game time!
    By dumby in forum World of Warcraft Guides
    Replies: 16
    Last Post: 01-15-2008, 07:17 PM
All times are GMT -5. The time now is 08:53 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2023 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2023 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search