• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TalkAction OtHire 7.72 simple account manager [LUA]

Old-Server

Active Member
Joined
Mar 19, 2018
Messages
33
Solutions
1
Reaction score
30
Hi, I made a simple account manager to simplify server-testing for people without any AAC installed.
a95ec3ec592b83a82b54cdddbdafa34a.png


Requirements:
- OtHire or any similiar distro.
- Account managers with names: Account Manager [0], Account Manager [1], and so on.
- Some island where the account managers may spawn at a protected zone.

To do / weaknesses:
- You may get interrupted by someone else who tries to log in at the same time.
- No ip check.
- No timer on how long you may be logged in at one character.
- Account managers are just like a normal player.

How to use;
Lua:
!create accnumber,password,charname,vocation

talkactions.xml
Lua:
    <talkaction words="!create"  access="0" filter="first word" script="acc_manager.lua"/>

Functions.lua

Lua:
function getColumnNames(table_name)
local arr = {}
    local dbres = db.getResult("SHOW COLUMNS FROM `".. table_name .."")
        if dbres:getID() ~= -1 then
            repeat
                local name = dbres:getDataString("Field")
                table.insert(arr,name)
            until not dbres:next()
        end
    return arr
end


acc_manager.lua
Lua:
local columns_p = getColumnNames("players")
local columns_a = getColumnNames("accounts")

local cfg = {
    accnumber_limit = 6,
    pw_limit = 10,
    playername_limit = 15,
    vocations = {"Sorcerer","Druid","Paladin","Knight"}
}

local options = {
    capital_char_name = false
}

local errMsg = {
"Account name is empty",
"Password is empty",
"Char name is empty",
"Vocation is empty"
}


local function retMessage(cid,effect,msg)
    doSendMagicEffect(getThingPos(cid),effect)
    return doPlayerSendTextMessage(cid,20,msg)
end

local function checkArrayValidity(arr,cid)
        for i = 1, #arr do
                if arr[i] == "" then
                    retMessage(cid,CONST_ME_POFF,errMsg[i])
                    return false
                end
        end
    return true
end

local function createSendStringToDb(tablename,checkagainst,findType)
    local str = "INSERT INTO `".. tablename .."`("
           
        for i = 1, #checkagainst do
            str = str .. ( ( i>1 ) and "," or "") .. "`" .. checkagainst[i] .. "`"
            end
           
        str = str .. ") VALUES ("
           
            for j = 1, #checkagainst do
                local _type = findType[checkagainst[j]]
                str = str .. ( ( j>1 ) and "," or "" ) .. (_type ~= nil and "".. [["]] .. _type .. [["]] .."" or '0')
            end
            str = str .. ")"
            return str
end


function onSay(cid, words, param)   
    if getPlayerAccess(cid) < 3 and not getCreatureName(cid):match("Account Manager %[") then
   
        retMessage(cid,CONST_ME_POFF,"You have to be logged on an Account Manager (1/1) in order to create a character.")
        return false
    end
   
    local t = split(param,",")
        if t == nil or #t < 4 then
            retMessage(cid,CONST_ME_POFF,"Sorry, not enough options specified: || !create accnumber,password,charname,vocation ||")
            return false
        end
   
       
    if not checkArrayValidity(t,cid) then
        return false
    end

        if not t[1]:match("%D") and t[1]:len() <= cfg.accnumber_limit then
            if not t[2]:match("%W") and t[2]:len() <= cfg.pw_limit then
                if not t[3]:match("%A") and t[3]:len() <= cfg.playername_limit then
                    if not t[4]:match("%A") then
                        local index = 0
                        for i = 1, #cfg.vocations do
                            if t[4]:lower():match(cfg.vocations[i]:lower()) then
                                index = i
                                break
                            end
                        end
                            if index ~= 0 then
                                local query = db.getResult("SELECT IFNULL((SELECT p.name FROM players p WHERE p.name=".. [["]] .. t[3] .. [["]] .."), 0) as data UNION ALL SELECT IFNULL((SELECT a.id FROM accounts a WHERE a.id=".. t[1] .."), 0)")
                                    if query:getID() == -1 then
                                        retMessage(cid,CONST_ME_POFF,"Query error somewhy?")
                                        return false
                                    else
                                        repeat
                                            if tonumber(query:getDataString("data")) ~= 0 then
                                            retMessage(cid,CONST_ME_POFF,"Character or Account number is already in use.")
                                            return false
                                            end
                                        until not query:next()   
                                                    local _getLastPid = db.getResult("SELECT id FROM players ORDER BY id DESC LIMIT 1;")
                                                        if _getLastPid:getID() == -1 then
                                                                retMessage(cid,CONST_ME_POFF,"No players exists, or some other error.")
                                                                return false
                                                        end
                                                            local findType = {
                                                                ["id"] = t[1],
                                                                ["account_id"] = t[1],
                                                                ["password"] = t[2],
                                                                ["name"] = t[3],
                                                                ["vocation"] = getVocationIdByName(t[4]),
                                                                ["level"] = 8,
                                                                ["magic"] = 0,
                                                                ["mana"] = 35,
                                                                ["health"] = 180,
                                                                ["healthmax"] = 180,
                                                                ["manamax"] = 35,
                                                                ["cap"] = 100,
                                                                ["posx"] = 7207,
                                                                ["posy"] = 13636,
                                                                ["posz"] = 7,
                                                                ["townid"] = 1,
                                                                ["save"] = 1
                                                                -- add more if needed
                                                             }
                                                            db.query(createSendStringToDb("accounts",columns_a,findType))
                                                            findType["id"] = _getLastPid:getDataInt("id")+1
                                                            db.query(createSendStringToDb("players",columns_p,findType))
                                                            doSendMagicEffect(getThingPos(cid),CONST_ME_TELEPORT)
                                    end
                            end
                            else
                                retMessage(cid,CONST_ME_POFF,"Sorry, this is an invalid vocation.")
                    end
                        else
                            retMessage(cid,CONST_ME_POFF,"The character name may only contain [A-Z] letters and be "..cfg.playername_limit .." letters long.")
                end
                    else
                        retMessage(cid,CONST_ME_POFF,"The password may only contain a maximum of ".. cfg.pw_limit .." letters/numbers. [A-Z 0-9]")
            end
                else
                    retMessage(cid,CONST_ME_POFF,"The account number may only contain a maximum of ".. cfg.accnumber_limit .." numbers")
        end           
    return false
end

Also a small question?
When and why are you supposed to query:free() ? I never understood this part, if someone wishes to let me know feel free to explain.
 
Forgot to add:

Functions.lua
Lua:
function getVocationIdByName(tmpVoc)
    local Vocations = {"Sorcerer","Druid","Paladin","Knight","Master Sorcerer","Elder Druid","Royal Paladin","Elite Knight"}
    for i = 1, #Vocations do
        if Vocations[i] == tmpVoc then
            return i
        end
    end
    return 0
end
 
Hi, I made a simple account manager to simplify server-testing for people without any AAC installed.
a95ec3ec592b83a82b54cdddbdafa34a.png


Requirements:
- OtHire or any similiar distro.
- Account managers with names: Account Manager [0], Account Manager [1], and so on.
- Some island where the account managers may spawn at a protected zone.

To do / weaknesses:
- You may get interrupted by someone else who tries to log in at the same time.
- No ip check.
- No timer on how long you may be logged in at one character.
- Account managers are just like a normal player.

How to use;
Lua:
!create accnumber,password,charname,vocation

talkactions.xml
Lua:
    <talkaction words="!create"  access="0" filter="first word" script="acc_manager.lua"/>

Functions.lua

Lua:
function getColumnNames(table_name)
local arr = {}
    local dbres = db.getResult("SHOW COLUMNS FROM `".. table_name .."")
        if dbres:getID() ~= -1 then
            repeat
                local name = dbres:getDataString("Field")
                table.insert(arr,name)
            until not dbres:next()
        end
    return arr
end


acc_manager.lua
Lua:
local columns_p = getColumnNames("players")
local columns_a = getColumnNames("accounts")

local cfg = {
    accnumber_limit = 6,
    pw_limit = 10,
    playername_limit = 15,
    vocations = {"Sorcerer","Druid","Paladin","Knight"}
}

local options = {
    capital_char_name = false
}

local errMsg = {
"Account name is empty",
"Password is empty",
"Char name is empty",
"Vocation is empty"
}


local function retMessage(cid,effect,msg)
    doSendMagicEffect(getThingPos(cid),effect)
    return doPlayerSendTextMessage(cid,20,msg)
end

local function checkArrayValidity(arr,cid)
        for i = 1, #arr do
                if arr[i] == "" then
                    retMessage(cid,CONST_ME_POFF,errMsg[i])
                    return false
                end
        end
    return true
end

local function createSendStringToDb(tablename,checkagainst,findType)
    local str = "INSERT INTO `".. tablename .."`("
          
        for i = 1, #checkagainst do
            str = str .. ( ( i>1 ) and "," or "") .. "`" .. checkagainst[i] .. "`"
            end
          
        str = str .. ") VALUES ("
          
            for j = 1, #checkagainst do
                local _type = findType[checkagainst[j]]
                str = str .. ( ( j>1 ) and "," or "" ) .. (_type ~= nil and "".. [["]] .. _type .. [["]] .."" or '0')
            end
            str = str .. ")"
            return str
end


function onSay(cid, words, param)  
    if getPlayerAccess(cid) < 3 and not getCreatureName(cid):match("Account Manager %[") then
  
        retMessage(cid,CONST_ME_POFF,"You have to be logged on an Account Manager (1/1) in order to create a character.")
        return false
    end
  
    local t = split(param,",")
        if t == nil or #t < 4 then
            retMessage(cid,CONST_ME_POFF,"Sorry, not enough options specified: || !create accnumber,password,charname,vocation ||")
            return false
        end
  
      
    if not checkArrayValidity(t,cid) then
        return false
    end

        if not t[1]:match("%D") and t[1]:len() <= cfg.accnumber_limit then
            if not t[2]:match("%W") and t[2]:len() <= cfg.pw_limit then
                if not t[3]:match("%A") and t[3]:len() <= cfg.playername_limit then
                    if not t[4]:match("%A") then
                        local index = 0
                        for i = 1, #cfg.vocations do
                            if t[4]:lower():match(cfg.vocations[i]:lower()) then
                                index = i
                                break
                            end
                        end
                            if index ~= 0 then
                                local query = db.getResult("SELECT IFNULL((SELECT p.name FROM players p WHERE p.name=".. [["]] .. t[3] .. [["]] .."), 0) as data UNION ALL SELECT IFNULL((SELECT a.id FROM accounts a WHERE a.id=".. t[1] .."), 0)")
                                    if query:getID() == -1 then
                                        retMessage(cid,CONST_ME_POFF,"Query error somewhy?")
                                        return false
                                    else
                                        repeat
                                            if tonumber(query:getDataString("data")) ~= 0 then
                                            retMessage(cid,CONST_ME_POFF,"Character or Account number is already in use.")
                                            return false
                                            end
                                        until not query:next()  
                                                    local _getLastPid = db.getResult("SELECT id FROM players ORDER BY id DESC LIMIT 1;")
                                                        if _getLastPid:getID() == -1 then
                                                                retMessage(cid,CONST_ME_POFF,"No players exists, or some other error.")
                                                                return false
                                                        end
                                                            local findType = {
                                                                ["id"] = t[1],
                                                                ["account_id"] = t[1],
                                                                ["password"] = t[2],
                                                                ["name"] = t[3],
                                                                ["vocation"] = getVocationIdByName(t[4]),
                                                                ["level"] = 8,
                                                                ["magic"] = 0,
                                                                ["mana"] = 35,
                                                                ["health"] = 180,
                                                                ["healthmax"] = 180,
                                                                ["manamax"] = 35,
                                                                ["cap"] = 100,
                                                                ["posx"] = 7207,
                                                                ["posy"] = 13636,
                                                                ["posz"] = 7,
                                                                ["townid"] = 1,
                                                                ["save"] = 1
                                                                -- add more if needed
                                                             }
                                                            db.query(createSendStringToDb("accounts",columns_a,findType))
                                                            findType["id"] = _getLastPid:getDataInt("id")+1
                                                            db.query(createSendStringToDb("players",columns_p,findType))
                                                            doSendMagicEffect(getThingPos(cid),CONST_ME_TELEPORT)
                                    end
                            end
                            else
                                retMessage(cid,CONST_ME_POFF,"Sorry, this is an invalid vocation.")
                    end
                        else
                            retMessage(cid,CONST_ME_POFF,"The character name may only contain [A-Z] letters and be "..cfg.playername_limit .." letters long.")
                end
                    else
                        retMessage(cid,CONST_ME_POFF,"The password may only contain a maximum of ".. cfg.pw_limit .." letters/numbers. [A-Z 0-9]")
            end
                else
                    retMessage(cid,CONST_ME_POFF,"The account number may only contain a maximum of ".. cfg.accnumber_limit .." numbers")
        end          
    return false
end

Also a small question?
When and why are you supposed to query:free() ? I never understood this part, if someone wishes to let me know feel free to explain.
awesome men btw will you be able to make capture the flag event for othire? or lms etc
 
When and why are you supposed to query:free() ? I never understood this part, if someone wishes to let me know feel free to explain.
you use it to reduce memory leak whenever you have a successful query.
queries are stored as pointers in a std::map until you manually free them with result.free(query) or query:free()
 
awesome men btw will you be able to make capture the flag event for othire? or lms etc
maybe, but i think othire doesnt have onstatchange, so you will actually have to "die" and not get teleported to temple
 
Back
Top