• 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 Name change item

Ciosny

Member
Joined
Aug 16, 2024
Messages
116
Solutions
1
Reaction score
15
Hi,
I've seen various scripts to create an item that allows you to change your nickname... But how to exclude nicknames such as "GM" "Tutor" "Admin".....?

For TFS 1.4.2

I found one for 1.2 T.F.S but without what I'm looking for and it probably won't work on 1.4.2:
This should work for 1.0, 1.1, 1.2

local x = {
length = {['min'] = 4, ['max'] = 20},
itemid = 8189
}

function setPlayerName(cid, newName)
local player = Player(cid)
local name = db.escapeString(player:getName())
newName = db.escapeString(newName)
player:remove()
db.query('UPDATE players SET name = '.. newName ..' WHERE name = '.. name ..';')
end

function correctNameLength(str)
local value = str:len()
return x.length['min'] >= value and x.length['max'] <= value
end

function onSay(cid, words, param, channel)
local player = type(cid) == "userdata" and cid or Player(cid)

if not param or param == '' then
player:sendCancelMessage('Use: '.. words ..' <newname>')
return true
end

local position, item = player:getPosition(), ItemType(x.itemid)

if player:getItemCount(x.itemid) < 1 then
player:sendCancelMessage("You do not have enough ".. item:getName()..".")
position:sendMagicEffect(CONST_ME_POFF)
return true
end

if param:find("[^%a%s]") then
player:sendCancelMessage("This name ".. param .." is invalid")
return true
end

if not correctNameLength(param) then
player:sendCancelMessage("The new name has to be between " .. x.length['min'] .. " and " .. x.length['max'] .. " characters.")
return true
end
item:remove()
setPlayerName(player:getId(), param)
return true
end
 
This is not a problem with the "space", 😅 which I checked.

The error occurs when:You enter a nickname, e.g. -
Test1
First click "ENTER"
Second - you click on the "okey" panel


I recorded a video for you illustrating this problem:



(see also chat channel)

After typing in the nickname, you can see the cursor blinking. Then I first clicked "Enter" on the keyboard (it stopped blinking), then clicked "Okey".

After clicking "Enter", the script displays a line under the nickname

Or just a more explicit example :D See the pictures. After each letter I clicked "Enter"


ac1.webp
 

Attachments

Last edited:
I edited the script @Mateus Robeerto wrote, and managed to fix some things i found "troublesome".

works and tested on TFS 1.4.2.

This version of the script:
1. blocks numbers
2. multiple of spacebars
3. Doesnt deny players words that could contain the ForbiddenWords (for an example, if a player wants to be named Godrick then they can,
but if they use the exact word "God" then they wont be allowed to change to that name, lowercase or uppercase does not matter)
4. added multiple of other characters that shouldnt be allowed into a name
5. the "enter" lines as shown from @Wilku93 gets prevented aswell

removed and changed:
1. removed the check for players being in combat since by default the script is only allowed to be used inside of protected zone.
2. Changed it so that the player has to remove the "placeholder text" and write their new name, reason being if a player would remove the "enter your desired name" text he would be able to bypass the character blocks and forbiddenWords.

test it and let me know what you think, if there is any issue or ways for you to bug it id be happy to know ^^!


LUA:
---------------------- Mateus Robeerto's Script --------------------
---------------------- Edit by Wusse --------------------
local config = {
    ItemID = 1950,
    forbiddenWords = {
        "cm", "gm", "god", "game master", "gamemaster", "hoster", "racist",
        "tutor", "admin", "owner", "developer", "support", "moderator",
        "staff", "helper", "scripter", "host", "server", "cipsoft"
    },
    forbiddenSubstrings = {
        -- Numbers 0-9
        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
        -- Special characters
        "!", "?", ".", ",", ":", ";", "/", "\\", "|", "&", "#", "¤", "%",
        "(", ")", "=", "+", "-", "´", "`", "'", "\"", "@", "£", "$", "€",
        "{", "[", "]", "}", "*", "^", "~", "§", "©", "®", "™", "°",
        "<", ">", "×", "÷", "±", "¬", "¦", "¶", "µ", "¿", "¡", "  ",
        -- Newlines and other characters
        "\n", "\r", "\t", "\v", "\f"
    },
    length = {['min'] = 4, ['max'] = 20},
    placeholderText = "Remove this text and write your new name"
}

local function isNameForbidden(name)
    if name:find("[\n\r\t\v\f]") then
        return true, "Name contains invalid line breaks or characters."
    end
  
    for _, forbidden in ipairs(config.forbiddenSubstrings) do
        if name:find(forbidden, 1, true) then
            if tonumber(forbidden) ~= nil then
                return true, "Names cannot contain numbers."
            end
            return true, "Name contains forbidden character: " .. forbidden
        end
    end
  
    local lowerName = name:lower()
    for _, forbidden in ipairs(config.forbiddenWords) do
        if lowerName:match("%f[%a]"..forbidden:lower().."%f[%A]") then
            return true, "Name contains forbidden word: " .. forbidden
        end
    end
  
    return false
end

local function updatePlayerName(player, newName)
    local guid = player:getGuid()
    db.query("UPDATE `players` SET `name` = " .. db.escapeString(newName) .. " WHERE `id` = " .. guid .. " LIMIT 1;")
end

local function isNameLengthValid(name)
    local length = name:len()
    return length >= config.length['min'] and length <= config.length['max']
end

local function onTextEdit(player, item, text)
    player:unregisterEvent("TextEdit")
 
    if text == config.placeholderText then
        player:sendCancelMessage("You need to remove the default text and enter your new name.")
        return true
    end

    local name = text:match("^%s*(.-)%s*$")
    if not name or name == "" then
        player:sendCancelMessage("You didn't enter a name.")
        return true
    end

    local itemToCheck = player:getItemById(config.ItemID, true)
    if not itemToCheck then
        player:sendCancelMessage("The item must remain in your backpack during this process. Name change canceled.")
        return true
    end

    if not isNameLengthValid(name) then
        player:sendCancelMessage("The name must be between " .. config.length['min'] .. " and " .. config.length['max'] .. " characters.")
        return true
    end

    local isForbidden, reason = isNameForbidden(name)
    if isForbidden then
        player:sendCancelMessage(reason or "Sorry, this name is forbidden.")
        return true
    end

    local query = "SELECT `name` FROM `players` WHERE `name` = " .. db.escapeString(name) .. ";"
    local resultId = db.storeQuery(query)
    if resultId then
        result.free(resultId)
        player:sendCancelMessage("This name already exists. Please choose another one.")
        return true
    end

    updatePlayerName(player, name)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Your name has been changed to: " .. name .. ". You will be logged out in 5 seconds.")
    player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)

    itemToCheck:remove(1)

    addEvent(function(pid)
        local player = Player(pid)
        if player then
            player:remove()
        end
    end, 5000, player:getId())

    return true
end

local textEditEvent = CreatureEvent("TextEdit")
textEditEvent.onTextEdit = function(player, item, text)
    return onTextEdit(player, item, text)
end
textEditEvent:register()

local ChangeName = Action()

function ChangeName.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local tile = player:getTile()
    if not tile or not tile:hasFlag(TILESTATE_PROTECTIONZONE) then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "You can only use this item in a protection zone.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    local parent = item:getParent()
    if parent and parent:isContainer() and parent:getTopParent() == player then
        player:registerEvent("TextEdit")
        player:showTextDialog(1948, config.placeholderText, true)
    else
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "The item must be in your backpack to be used.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
    end
    return true
end

ChangeName:id(config.ItemID)
ChangeName:register()
 
Last edited:

Similar threads

Back
Top