[1.12.1] Lua call with return value (help) menu

User Tag List

Results 1 to 9 of 9
  1. #1
    Lywbringer's Avatar Member
    Reputation
    11
    Join Date
    Sep 2022
    Posts
    10
    Thanks G/R
    2/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [1.12.1] Lua call with return value (help)

    This is going to be my last question, because I have almost everything that I need for my bot except the lua return...

    I tried 3 methods in total and none of them worked for me

    Method 1:

    I simply call the lua function then get a pointer to the variable and read it as a string.

    MemoryManager.cpp
    Code:
    char* MemoryManager::ReadString(uintptr_t ptr) {
        int8_t buffer[512];
        int8_t* ptr2 = (int8_t*)ptr;
    
        for (int i = 0; i < 512; i++) {
            buffer[i] = ptr2[i];
        }
    
        char buffer2[512];
        for (int i = 0; i < 512; i++) {
            buffer2[i] = (char)buffer[i];
        }
    
        return buffer2;
    }
    Functions.cpp
    Code:
    void Functions::LuaCall(const char* code) {
    	typedef void __fastcall func(const char* code, const char* unused);
    	func* function = (func*)LUA_CALL_FUN_PTR;
    	function(code, "Unused");
    }
    
    uintptr_t Functions::GetText(const char* varName) {
    	typedef uintptr_t __fastcall func(const char* varName, unsigned int nonSense, int zero);
    	func* f = (func*)0x00703bf0;
    	return f(varName, 0xFFFFFFFF, 0);
    }
    Main.cpp
    Code:
    const char* command = "a, b, c = UnitBuff(\"player\", 1)";
    Functions::LuaCall(command);
    uintptr_t address = Functions::GetText("a");
    std::cout << "address: " << address << "\n";
    std::string str = MemoryManager::ReadString(address);
    std::cout << "var a: " << str << "\n";
    It always return the same pointer no matter what I pass: 8922952

    Method 2:

    I use LuaC-API by directly inserting lua files into my project but I have zero idea on how to get the lua state of the game...

    I made sure to use the right version of Lua (here 5.0).

    1.png

    The goal is to be able to call this kind of code inside the client:

    Code:
    extern "C"{
    	#include  "Lua/lauxlib.h"
    	#include  "Lua/lua.h"
    	#include  "Lua/lualib.h"
    }
    
    lua_State* lvm_hnd = lua_open(); //But I need to get the client state...
    luaopen_base(lvm_hnd);
    luaopen_io(lvm_hnd);
    luaopen_math(lvm_hnd);
    luaopen_string(lvm_hnd);
    luaopen_table(lvm_hnd);
    
    lua_getglobal(lvm_hnd, "print");
    
    lua_pushstring(lvm_hnd, "Hello C API!");
    
    lua_call(lvm_hnd, 1, 0);
    
    lua_close(lvm_hnd);
    Method 3:

    I directly use C++ equivalent of lua functions but it always crash at address: 0x006F3414

    Code:
    void Functions::UseAction(int slot) {
    	typedef void __fastcall func(int slot);
    	func* function = (func*)0x004e7140;
    	function(slot);
    }
    The instruction 0x006F3414 corresponds to the function 0x006f3410 which is about comparing two integers, I think...

    2.png

    (It's the uVar1 in yellow)

    This is the last thing I need and I really need your help

    These ads disappear when you log in.

  2. #2
    CheatRadio's Avatar Member
    Reputation
    2
    Join Date
    Sep 2022
    Posts
    5
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In order to make this work you need a couple more things. Here is a psuedo recipe:

    1. Register a luacFunction with a name using Wow's "FramescriptRegister" function. This allows you to call that name from in game.

    2. Setup the receiving end of this function in C++ with an int return (the args returned). One technique is to have one wrapper function connected to a map to call any of your C++ by the name the function is mapped to. Another approach is register many C functions and just extend the "Invalid Function Pointer" with a write to it.

    3. Search for "GetText" on OC for usage of this function (it gets the return value).

    More complex solutions are possible where you don't need GetText, but the above is a decent start. In your examples you aren't really using lua properly I think you might just be reading the address value and not the return. I would strongly recommend reading into some writeups or examples of Lua C usage. A good idea is just to make a non-wow app that interacts with the C side and lua script side of things. This will open up new doors by understanding its intended usage.

    Here is a sorta template for what a lua C function will look like:

    Code:
    int C::GetWowDir(lua_State* L)
    {
    	auto path = std::filesystem::current_path().string();
    	lua_pushstring(L, path.c_str());
    
    	return 1;
    }
    As for the lua_State of the game, you can read the address directly or call GetContext which return the state.

    Hopefully this last bit will motivate you instead of intimidate, but your milestone could be to eventually reverse lua 5.1 to be compatible with WoW instead of having to call binary versions of all the lua functions. Doing so will eliminate like 20 functions you would need offsets for and instead only need Object Manager, Camera, InGame, and a few more things:

    Code:
            auto L = (lua_State*)Game::Invoke<int64_t>(Offsets::GetContext);
    
    	lua_register(L, "CallCpp", (lua_CFunction)Offsets::Caller);
    
    	std::cout << "Registered." << std::endl;
    Last edited by CheatRadio; 09-27-2022 at 12:27 PM.

  3. Thanks Lywbringer (1 members gave Thanks to CheatRadio for this useful post)
  4. #3
    Lywbringer's Avatar Member
    Reputation
    11
    Join Date
    Sep 2022
    Posts
    10
    Thanks G/R
    2/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you for your answer ! Unfortunately I'm really stupid and you're gonna have to explain it yet again I'm so sorry.

    I did this:

    Functions.cpp
    Code:
    lua_State* Functions::GetContext() {
    	typedef lua_State* __stdcall func();
    	func* f = (func*)0x007040D0;
    	return f();
    }
    
    void Functions::Register(lua_State* L, const char* f_name, lua_CFunction function) {
    	typedef void __stdcall func(lua_State*, const char*, lua_CFunction);
    	func* f = (func*)0x00704120;
    	return f(L, f_name, function);
    }
    Main
    Code:
    lua_State* lvm_hnd = Functions::GetContext();
    std::cout << "lvm_hnd: " << lvm_hnd << "\n";
    Functions::Register(lvm_hnd, "HelloWorld", HelloWorld);
    std::cout << "Registered." << std::endl;
    Code:
    extern "C" {
    	static int HelloWorld(lua_State* L) {
    		lua_pushstring(L, "Hello World");
    
    		return 1;
    	}
    }
    I have a Run-Time Failure, the value of ESP was not properly saved blablabla...
    Last edited by Lywbringer; 09-27-2022 at 03:38 PM.

  5. #4
    CheatRadio's Avatar Member
    Reputation
    2
    Join Date
    Sep 2022
    Posts
    5
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you don't read up on lua C or make a basic c++/lua app, things will quickly get messy. I still strongly suggest doing so you can make better sense of what you're doing.

    Does the error appear during registration or after calling "HelloWorld" from in game?

    Also, since your current workings are a "Hello World" function, you are still a ways from the big picture of working in lua harmony with the WoW client. With that in mind, you might start with a "FrameScriptExecute" style "Hello World". FrameScriptExecute is similar to lua_dostring in that you can pass any lua to the game from the C++ side. It's easy to work with in older clients, but there are protections in place in modern WoW.

    This is taken from another thread:
    Code:
    const auto wowBase = uintptr_t(GetModuleHandle(NULL));
    
    typedef int (__fastcall* framescriptExecute)(const char*, const char*, int);
    
    const auto pframescriptExecute = framescriptExecute(wowBase + 0x532280);
    pframescriptExecute("print(\"hello\")", "hello.lua", 0);

  6. #5
    Lywbringer's Avatar Member
    Reputation
    11
    Join Date
    Sep 2022
    Posts
    10
    Thanks G/R
    2/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I already have a working function to call lua in game but I need the return for functions like "a, b, c = UnitBuff("player", 1)".

    And the error is during registration, I think I have to pass a pointer of the function...

    I want to be able to control everything and if I do:
    Code:
    //Some C++ code
    Functions::CallLua("
    #My lua code
    ");
    I can't insert c++ inside the lua...
    Last edited by Lywbringer; 09-27-2022 at 04:50 PM.

  7. #6
    CheatRadio's Avatar Member
    Reputation
    2
    Join Date
    Sep 2022
    Posts
    5
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Lywbringer View Post
    I already have a working function to call lua in game but I need the return for functions like "a, b, c = UnitBuff("player", 1)".

    And the error is during registration, I think I have to pass a pointer of the function...
    If you are using external lua (not calling the game's functions) it won't work out of the box. A dozen or so changes are required to make it not crash with the client.

    As for the return value, look into "GetLocalizedText". I think you just pass it the name of the lua variable and it will return. Been a while since I've used that sort of method, so sorry for the vague info.

  8. #7
    Lywbringer's Avatar Member
    Reputation
    11
    Join Date
    Sep 2022
    Posts
    10
    Thanks G/R
    2/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sadly it's 1.12.1, there is no GetLocalizedText, only GetText() which always return the same value.

  9. #8
    air999's Avatar Contributor
    Reputation
    113
    Join Date
    Nov 2014
    Posts
    97
    Thanks G/R
    8/61
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    To get results from lua you need to use lua_pcall() and add "return" to your lua string like this:
    Code:
    "return IsQuestFlaggedCompleted({id})"
    lua_gettop() will return how much values lua function return in lua stack

    then you should iterate lua stack and use lua_type to identify value type and convert values from lua stack to data types with functions lua_toboolean, lua_tostring, lua_tonumber

    also, you should learn how to use search, 'cause lua calls discussed zillion times on forum.

    Code:
    while (lua_gettop(lua_state) >= 1)
    
    {
    
                    str_buf.str(std::string());
            str_buf << " ";
        switch (lua_type(lua_state, lua_gettop(lua_state)))
        {
        case LUA_TNUMBER:
            {
                str_buf << "script returned the number: "
                    << lua_tonumber(lua_state, lua_gettop(lua_state));
            }
            break;
        case LUA_TTABLE:
           str_buf << "script returned a table";
        break;
        case LUA_TSTRING:
            {
                std::string temp = lua_tostring(lua_state, lua_gettop(lua_state));
                str_buf << "script returned the string: "
                    << temp;
            }
            break;
        case LUA_TBOOLEAN:
            {   
                str_buf << "script returned the boolean: "
                << lua_toboolean(lua_state, lua_gettop(lua_state));
            }
            break;
            default:
        str_buf << "script returned an unknown-type value";     
    }
    Last edited by air999; 09-28-2022 at 01:49 AM. Reason: add example code

  10. #9
    Lywbringer's Avatar Member
    Reputation
    11
    Join Date
    Sep 2022
    Posts
    10
    Thanks G/R
    2/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I managed to solve my problem by changing GetText() parameters:

    Code:
    uintptr_t Functions::GetText(const char* varName) {
    	typedef uintptr_t __fastcall func(const char* varName, unsigned int nonSense, int zero);
    	func* f = (func*)0x00703bf0;
    	return f(varName, -1, 0);
    }

Similar Threads

  1. Use return value from a lua function as a PE condition
    By Filint in forum PE Support forum
    Replies: 3
    Last Post: 11-23-2014, 09:23 PM
  2. Lua injection return value.
    By LogicWin in forum WoW Bots Questions & Requests
    Replies: 1
    Last Post: 03-28-2011, 09:45 AM
  3. POC Class to Manage Lua Calls and Return Values
    By Xarg0 in forum WoW Memory Editing
    Replies: 7
    Last Post: 01-22-2010, 10:38 AM
  4. [WoW][3.0.9] A way to get return values from Lua Functions
    By ramey in forum WoW Memory Editing
    Replies: 6
    Last Post: 03-22-2009, 10:09 PM
All times are GMT -5. The time now is 10:29 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2022 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2022 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search