• 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!

NPC Reset System

Holy shit man! Something definitely changed something haha, and I think it changed the thing we wanted it to :p

I tested it with the same character and it went to the "you will be logged out in 3 seconds" screen.
Then when I go to log back into that same character it says "The user name or password is incorrect" haha (all other characters on the same account work) So my theory is that it actually did work. Its just now my account can't recognise that character name to make the login happen :p

I don't know if there is a way to make this work, this seems to be quite the roadblock :p

Anyways, even if its not all figured out I commend you Itutorial for giving it your best shot :D
If anyone has any tips or thoughts let me know!
Thank you very much,
Tys
 
Correction.

It does work. The problem I was having was only because I hadn't fully left my account. (the character display was still up). When I logged in today my character, with the altered name was on the list and able to log in.

However, there is a slight problem! When getting reset for the second time, The name change from the first alteration is still present.
For example,
John resets into John I,
John I resets into John I II
John I II resets into John I II III.....

Is there a way to store the suffix and alter only that?

Thanks
-Tys
 
I'd like to know the fix for the suffix part aswell! :) Great script.
 
Thanx @Codex NG but i dont think im good enough with scripting to tell the database to substract I and add II and so on.. xD I'll be trying to do so tho..
 
You have to either store the original name (and prevent others from creating characters with that name) or do some string manipulation to remove the numeral in the end.

Storing the original name is the safest way but if you want the string manipulation thing you can do like this:
Code:
function renam(name, resetnum)
    local resetsNum = {
    [1] = "I", [2] = "II", [3] = "III", [4] = "IV", [5] = "V",
    [6] = "VI", [7] = "VII", [8] = "VIII", [9] = "IX", [10] = "X",
    [11] = "XI", [12] = "XII", [13] = "XIII", [14] = "XIV", [15] = "XV",
    [16] = "XVI", [17] = "XVII", [18] = "XVIII", [19] = "XIX", [20] = "XX",
    [21] = "XXI", [22] = "XXII", [23] = "XXIII", [24] = "XXIV", [25] = "XXV",
    [26] = "XXVI", [27] = "XXVII", [28] = "XXVIII", [29] = "XXIX",[30] = "XXX"
    }

    local i, j = 1, #name
    if not resetsNum[resetnum] then
        print("No value for resetnum " .. resetnum)
        return name
    end

    for i = 1, #resetsNum do
        if name:find("%s" .. resetsNum[i] .. "$") then
            local a, b = name:find("%s" .. resetsNum[i] .. "$")
            j = a - 1
            break
        end
    end

    return name:sub(i, j) .. " " .. resetsNum[resetnum]
end

function addReset(cid)
    --1 - 30--
    player = Player(cid)
    resets = getResets(cid)
    hp = player:getMaxHealth()
    resethp = hp*(config.percent/100)
    player:setMaxHealth(resethp)
    mana = player:getMaxMana()
    resetmana = mana*(config.percent/100)
    player:setMaxMana(resetmana)
    playerid = player:getGuid()
    player:setStorageValue(378378, resets+1)
    newName = renam(player:getName(), resets+1)
    player:remove()
    description = resets+1
    db.query("UPDATE `players` SET `level`="..config.newlevel..",`experience`= 0 WHERE `players`.`id`= ".. playerid ..";")
    db.query("UPDATE `players` SET `name` = '"..newName.."' WHERE `players`.`id`= ".. playerid ..";")
    return true
end

Keep in mind this WILL bug if anyone creates a character with the old name of some character and get some resets too. Example:

My name is Mkalo and I got 1 reset then it is Mkalo I.
The name Mkalo is not in the database anymore so anyone can create a character with this name again, if this person get 1 reset as well it will bug.

It will pop an error in the console because the column name is unique, the player wont get his new name (only in the second reset because its different).

Thats why I said to do the other way.

Edit: Hacky way
If you really don't want to change your website's character creation you can do this in a hacky way, you just have to store the oldname from everyone in the server and then check for it on the very first login of each player and delete the player if its in the list of oldnames stored.
Hacky, but no website change needed.
 
Last edited:
Im thankfull for your explanation and effort @MatheusMkalo !!

I've been thinking, and what about setting the I, II... as some kind of tittle instead changing the name? or maybe adding a description to the character like "You see Mkalo. He's an Elder Druid. Resets: 1". Would that be easier and less buggy?
Dont know where to start on that, those are just some ideas that came to mind.. :)
 
You can manipulate the Player:eek:nLook event.
https://github.com/otland/forgottenserver/blob/master/data/events/scripts/player.lua#L5-L56

Just add this under local description = ...
Code:
    local description = "You see " .. thing:getDescription(distance)
    if thing:isPlayer() then
        local resets = math.max(0, thing:getStorageValue(378378))
        description = description .. "\nResets: " .. resets .. "."
    end

You could even manipulate it to show the name like "Mkalo IV" on look without actually changing the name of the player.
 
Thats what i was talking about.. Just "add" on look how many resets he has. No need for name changes and for what you showed me, it seems far easier!

Any insight?
 
Code:
    local description = "You see " .. thing:getDescription(distance)
    if thing:isPlayer() then
        local resets = math.max(0, thing:getStorageValue(378378))
        local title = math.min(resets, 30) -- -- Change 30 if you place more than 30 titles in the table
        local resetsNum = {
            [1] = "I", [2] = "II", [3] = "III", [4] = "IV", [5] = "V",
            [6] = "VI", [7] = "VII", [8] = "VIII", [9] = "IX", [10] = "X",
            [11] = "XI", [12] = "XII", [13] = "XIII", [14] = "XIV", [15] = "XV",
            [16] = "XVI", [17] = "XVII", [18] = "XVIII", [19] = "XIX", [20] = "XX",
            [21] = "XXI", [22] = "XXII", [23] = "XXIII", [24] = "XXIV", [25] = "XXV",
            [26] = "XXVI", [27] = "XXVII", [28] = "XXVIII", [29] = "XXIX",[30] = "XXX"
        }
        if resetsNum[resets] then
            description = description:gsub(thing:getName(), thing:getName() .. " " .. resetsNum[title], 1)
        end
     
        description = description .. "\nResets: " .. resets .. "."
    end

This will stop in XXX but the "Resets: n" will keep getting bigger.
 
Last edited:
Wow! @MatheusMkalo !! I was just testing where to set it.. :p i had something like "you see resets:1. Mkalo. You are a druid."

You just saved me many testing! im really thankfull for your help!
 
The reset name works awesome! Thanks so much!

Another question. Should this not reset the capacity of a player?
Code:
--[[Script made 100% by Nogard, Night Wolf and Linus.
   You can feel free to edit anything you want, but don't remove the credits]]

config = {

    minlevel = 0, --- Level needed to reset?
    price = 25000, --- cost per reset
    newlevel = 1, --- Level after reset
    priceByReset = 25000, --- price increse per reset
    percent = 70, ---- Percentage of life / mana you will have to reset (in relation to its former total life )
    maxresets = 30, ---- Maximum resets
    levelbyreset = 10 --- Amount of levels added to min level for reset per reset.

}


function getResets(uid)
    resets = getPlayerStorageValue(uid, 378378)
        if resets < 0 then
            resets = 0
        end
    return resets
end

function renam(name, resetnum)
    local resetsNum = {
    [1] = "I", [2] = "II", [3] = "III", [4] = "IV", [5] = "V",
    [6] = "VI", [7] = "VII", [8] = "VIII", [9] = "IX", [10] = "X",
    [11] = "XI", [12] = "XII", [13] = "XIII", [14] = "XIV", [15] = "XV",
    [16] = "XVI", [17] = "XVII", [18] = "XVIII", [19] = "XIX", [20] = "XX",
    [21] = "XXI", [22] = "XXII", [23] = "XXIII", [24] = "XXIV", [25] = "XXV",
    [26] = "XXVI", [27] = "XXVII", [28] = "XXVIII", [29] = "XXIX",[30] = "XXX"
    }

    local i, j = 1, #name
    if not resetsNum[resetnum] then
        print("No value for resetnum " .. resetnum)
        return name
    end

    for i = 1, #resetsNum do
        if name:find("%s" .. resetsNum[i] .. "$") then
            local a, b = name:find("%s" .. resetsNum[i] .. "$")
            j = a - 1
            break
        end
    end

    return name:sub(i, j) .. " " .. resetsNum[resetnum]
end

function addReset(cid)
    --1 - 30--
    player = Player(cid)
    resets = getResets(cid)
    hp = player:getMaxHealth()
    resethp = hp*(config.percent/100)
    player:setMaxHealth(resethp)
    mana = player:getMaxMana()
    resetmana = mana*(config.percent/100)
    player:setMaxMana(resetmana)
    cap = player:getMaxMana()
    resetcap = cap*(config.percent/100)
    player:setMaxCap(resetcap)
    playerid = player:getGuid()
    player:setStorageValue(378378, resets+1)
    newName = renam(player:getName(), resets+1)
    player:remove()
    description = resets+1
    db.query("UPDATE `players` SET `level`="..config.newlevel..",`experience`= 0 WHERE `players`.`id`= ".. playerid ..";")
    db.query("UPDATE `players` SET `name` = '"..newName.."' WHERE `players`.`id`= ".. playerid ..";")
    return true
end


EDIT:
Sorry, Forgot the error :p

Code:
Lua Script Error: [Main Interface]
in a timer event called from:
(Unknown scriptfile)
data/npc/lib/otto.lua:64: attempt to call method 'setMaxCap' (a nil value)
stack traceback:
        [C]: in function 'setMaxCap'
        data/npc/lib/otto.lua:64: in function 'addReset'
        data/npc/scripts/otto.lua:36: in function <data/npc/scripts/otto.lua:34>


Thanks!
 
Last edited:
You can configure whether the price increase to each reset, if you want the level to reset increase and if vc wants life reset along (and as % of current life will be life after reset).


Tested in tfs 1.1 Version to 10.77


Go to data/npc/lib/ make npc_resets.lua :

Code:
--[[Script made 100% by Nogard, Night Wolf and Linus.
   You can feel free to edit anything you want, but don't remove the credits]]

config = {

    minlevel = 150, --- Level inical para resetar
    price = 10000, --- Preço inicial para resetar
    newlevel = 20, --- Level após reset
    priceByReset = 0, --- Preço acrescentado por reset
    percent = 30, ---- Porcentagem da vida/mana que você terá ao resetar (em relação à sua antiga vida total)
    maxresets = 50, ---- Maximo de resets
    levelbyreset = 0 --- Quanto de level vai precisar a mais no próximo reset

}

function getResets(uid)
    resets = getPlayerStorageValue(uid, 378378)
        if resets < 0 then
            resets = 0
        end
    return resets
end

function addReset(cid)
    player = Player(cid)
    resets = getResets(cid)
    hp = player:getMaxHealth()
    resethp = hp*(config.percent/100)
    player:setMaxHealth(resethp)
    mana = player:getMaxMana()
    resetmana = mana*(config.percent/100)
    player:setMaxMana(resetmana)
    playerid = player:getGuid()
    player:setStorageValue(378378, resets+1)
    player:remove()
    description = resets+1
    db.query("UPDATE `players` SET `description` = ' [Reset: "..description.."]' WHERE `players`.`id`= ".. playerid .."")
    db.query("UPDATE `players` SET `level`="..config.newlevel..",`experience`= 0 WHERE `players`.`id`= ".. playerid .."")
    return true
end

You can edit stirring here, the script above :
Code:
config = {

    minlevel = 150, --- Level inical para resetar
    price = 10000, --- Preço inicial para resetar
    newlevel = 20, --- Level após reset
    priceByReset = 0, --- Preço acrescentado por reset
    percent = 30, ---- Porcentagem da vida/mana que você terá ao resetar (em relação à sua antiga vida total)
    maxresets = 50, ---- Maximo de resets
    levelbyreset = 0 --- Quanto de level vai precisar a mais no próximo reset

}
go to data/npc/ make reseter.XML :

Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Reseter" script="reseter.lua">
    <health now="1000" max="1000"/>
    <look type="133" head="95" body="86" legs="86" feet="38" addons="3"/>
        <parameters>
            <parameter key="message_greet" value="Hello |PLAYERNAME|.I've been waiting for you to come.. Say 'reset' or 'quantity'" />
            <parameter key="message_farewell" value="Cya folk." />
            <parameter key="message_walkaway" value="How Rude!" />
        </parameters>
</npc>



go to data/npc/scripts make reseter.lua :

Code:
dofile('data/npc/lib/npc_resets.lua')

local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end
function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end
function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end
function onThink()                  npcHandler:onThink()                  end

function creatureSayCallback(cid, type, msg)

    if not npcHandler:isFocused(cid) then
        return false
    end

    local player = Player(cid)

    local newPrice = config.price + (getResets(cid) * config.priceByReset)
    local newminlevel = config.minlevel + (getResets(cid) * config.levelbyreset)

    if msgcontains(msg, 'reset') then
        if getResets(cid) < config.maxresets then
            npcHandler:say('You want to reset your character? It will cost '..newPrice..' gp\'s!', cid)
            npcHandler.topic[cid] = 1
        else
            npcHandler:say('You already reached the maximum reset level!', cid)
        end
    elseif msgcontains(msg, 'yes') and npcHandler.topic[cid] == 1 then
        if player:getLevel() > newminlevel then
            if player:removeMoney(newPrice) then
                addEvent(function()
                    if isPlayer(cid) then
                        addReset(cid)
                    end
                end, 3000)
                local number = getResets(cid)+1
                local msg ="---[Reset: "..number.."]-- You have reseted!  You'll be disconnected in 3 seconds."
                player:popupFYI(msg)
                npcHandler.topic[cid] = 0
                npcHandler:releaseFocus(cid)
            else
                npcHandler:say('Its necessary to have at least '..newPrice..' gp\'s for reseting!', cid)
                npcHandler.topic[cid] = 0
            end
        else
            npcHandler:say('The minimum level for reseting is '..newminlevel..'!', cid)
            npcHandler.topic[cid] = 0
        end
    elseif(msgcontains(msg, 'no')) and isInArray({1}, talkState[talkUser]) == TRUE then
        npcHandler.topic[cid] = 0
        npcHandler:releaseFocus(cid)
        npcHandler:say('Ok.', cid)
    elseif msgcontains(msg, 'quantity') then
        npcHandler:say('You have a total of '..getResets(cid)..' reset(s).', cid)
        npcHandler.topic[cid] = 0
    end
    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())


Img :

sI81vfCpT.png
Is there a way to replace the gp value with some other item? type to reset the npc asks for a scarab coin.
 
Is it possible to allow players to receive skills according to their vocation? example vocation 1 and 2 receive +10 magic level,
vocation 3 receives +15 skill dist, and vocation 4 receives +15 from all skills
 
Back
Top