• 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 Changename in-game

Tested?

- - - Updated - - -

You can get a no named player using this old script.
 
Ok. I tested this one, works perfect:
Lua:
local config = {
	text = "Your name has been changed successfully.",
	item = {
		Id = 1111,
		count = 1
	},
	maxTextLenght = 15,
	blacklistParam = {"account manager", "god", "cm", "gm", "tutor", "tester"},
	minWordLenght = 3,
	newMethod = false,
	delay = 2
}

function onSay(cid, words, param, channel)
	local textCancel = config.text
	if(param == '') then
		return doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Command param required.")
	elseif(getPlayerGUIDByName(param) ~= nil) then
		textCancel = "That name is already in use."
	elseif(getPlayerItemCount(cid, config.item.Id) < config.item.count) then
		textCancel = "You do not have enough premium points."
	elseif(not getTilePzInfo(getCreaturePosition(cid))) then
		textCancel = "You must be inside a protection zone to use this command."
	elseif(string.len(tostring(param)) >= config.maxTextLenght) then
		textCancel = "You can only use a maximum of " .. config.maxTextLenght .. " characters."
	elseif(string.find(param:lower(), "[^%l%s]") ~= nil) then
		textCancel = "You cannot use symbols."
	else
		for blacklist = 1, table.maxn(config.blacklistParam) do
			if(string.find(param:lower(), config.blacklistParam[blacklist]) ~= nil) then
				textCancel = "Invalid name entry."
				break
			end
		end
	end

	if(config.text ~= textCancel) then
		doPlayerSendCancel(cid, textCancel)
		return true
	end

	local paramTemp, space, oldName = '', '', getCreatureName(cid)
	for word in string.gmatch(param, "%a+") do
		if(string.len(word) < config.minWordLenght) then
			doPlayerSendCancel(cid, "Each word must have a minimum of " .. config.minWordLenght .. " characters.")
			return true
		end
 
		paramTemp = "" .. paramTemp .. "" .. space .. "" .. word .. ""
		if(space == '') then
			space = " "
		end
	end

	local guid = getPlayerGUID(cid)
	param = paramTemp
	doPlayerRemoveItem(cid, config.item.Id, config.item.count)
	if(config.newMethod == true) then
		doPlayerChangeName(guid, oldName, param)
	else
		db.executeQuery("UPDATE `players` SET `name` = " .. db.escapeString(param) .. " WHERE `id` = " .. guid .. ";")
	end

	doPlayerSendTextMessage(cid, 25, "" .. config.text .. " You will be kicked in " .. config.delay .. " seconds.")
	addEvent(function(cid, forceLogout)
		if(isPlayer(cid)) then
			doRemoveCreature(cid, forceLogout)
		end
	end, config.delay * 1000, cid, false)

	return true
end
 
Version 3.0
Code:
Changelog 3.0:
+ Added a second param: force. (/changename name[, force]).
*It will force the change of the name even if the new name is namelocked (e.g. /changename Player, true).
+ Removed some useless config values.
+ Now the script checkes wether TFS has the doPlayerChangeName function using pcall. If it doesn't (0.3.6 or lower) it will use the classic database method.
+ Added a missing namelock query.
+ Added a missing limit to a query.

Lua:
local config = {
	item = {
		Id = 1111,
		count = 0,
	},
	maxTextLenght = 15,
	blacklistParam = {"account manager", "god", "cm", "gm", "tutor", "tester"},
	minWordLenght = 3,
	delay = 2
}

function onSay(cid, words, param, channel)
	local textCancel, t = config.text, string.explode(param, ",")
	if(param == '') then
		return doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Command param required.")
	elseif((getPlayerGUIDByName(t[1]) ~= nil) and (not getBooleanFromString(t[2]))) then
		textCancel = "That name is already in use."
	elseif(getPlayerItemCount(cid, config.item.Id) < config.item.count) then
		textCancel = "You do not fulfill the requirements."
	elseif(not getTilePzInfo(getCreaturePosition(cid))) then
		textCancel = "You must be inside a protection zone to use this command."
	elseif(string.len(tostring(t[1])) >= config.maxTextLenght) then
		textCancel = "You can only use a maximum of " .. config.maxTextLenght .. " characters."
	elseif(string.find(t[1]:lower(), "[^%l%s]") ~= nil) then
		textCancel = "You cannot use symbols."
	else
		for blacklist = 1, table.maxn(config.blacklistParam) do
			if(string.find(t[1]:lower(), config.blacklistParam[blacklist]) ~= nil) then
				textCancel = "Invalid name entry."
				break
			end
		end
	end

	if(config.text ~= textCancel) then
		doPlayerSendCancel(cid, textCancel)
		return true
	end

	local paramTemp, space, oldName = '', '', getCreatureName(cid)
	for word in string.gmatch(t[1], "%a+") do
		if(string.len(word) < config.minWordLenght) then
			doPlayerSendCancel(cid, "Each word must have a minimum of " .. config.minWordLenght .. " characters.")
			return true
		end

		paramTemp = "" .. paramTemp .. "" .. space .. "" .. word .. ""
		if(space == '') then
			space = " "
		end
	end

	local guid = getPlayerGUID(cid)
	t[1] = paramTemp
	doPlayerRemoveItem(cid, config.item.Id, config.item.count)
	if(pcall(doPlayerChangeName, guid, oldName, t[1]) == false) then
		db.executeQuery("INSERT INTO `player_namelocks` (`player_id`, `name`, `new_name`, `date`) VALUES (" .. guid .. ", " .. db.escapeString(oldName) .. ", " .. db.escapeString(t[1]) .. ", " .. os.time() .. ");")
		db.executeQuery("UPDATE `players` SET `name` = " .. db.escapeString(t[1]) .. " WHERE `id` = " .. guid .. " LIMIT 1;")
	end

	doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Your name has been changed successfully. You will be kicked in " .. config.delay .. " seconds.")
	addEvent(function(cid, forceLogout)
		if(isPlayer(cid)) then
			doRemoveCreature(cid, forceLogout)
		end
	end, config.delay * 1000, cid, false)

	return true
end
 
Add a kick player event so they are forced to relog.

- - - Updated - - -

Add a kick player event so they are forced to relog.
 
?
It already does that. By default it's 2 seconds before the player is kicked, you can change it in "delay".
 
ysql_real_query(): UPDATE `players` SET `name` = 'Loki' WHERE `id` = 21602 LIMIT 1; - MYSQL ERROR: Duplicate entry 'Loki-0' for key 'name' (1062)
Dont checks if the name is already taken

- - - Updated - - -

Edit:
DOnt works only in multiworld

- - - Updated - - -

For multiworld this one works:
Code:
local config = {
	item = {
		Id = 1111,
		count = 0,
	},
	maxTextLenght = 15,
	blacklistParam = {"account manager", "god", "cm", "gm", "tutor", "tester"},
	minWordLenght = 3,
	delay = 2
}
 
function onSay(cid, words, param, channel)
	local textCancel, t = config.text, string.explode(param, ",")
	if(param == '') then
		return doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Command param required.")
	elseif(db.getResult("SELECT `name` FROM `players` WHERE `name` = " .. db.escapeString(param) .. ";"):getID() ~= -1) then
	textCancel = "That name is already in use."
	elseif(getPlayerItemCount(cid, config.item.Id) < config.item.count) then
		textCancel = "You do not fulfill the requirements."
	elseif(not getTilePzInfo(getCreaturePosition(cid))) then
		textCancel = "You must be inside a protection zone to use this command."
	elseif(string.len(tostring(t[1])) >= config.maxTextLenght) then
		textCancel = "You can only use a maximum of " .. config.maxTextLenght .. " characters."
	elseif(string.find(t[1]:lower(), "[^%l%s]") ~= nil) then
		textCancel = "You cannot use symbols."
	else
		for blacklist = 1, table.maxn(config.blacklistParam) do
			if(string.find(t[1]:lower(), config.blacklistParam[blacklist]) ~= nil) then
				textCancel = "Invalid name entry."
				break
			end
		end
	end
 
	if(config.text ~= textCancel) then
		doPlayerSendCancel(cid, textCancel)
		return true
	end
 
	local paramTemp, space, oldName = '', '', getCreatureName(cid)
	for word in string.gmatch(t[1], "%a+") do
		if(string.len(word) < config.minWordLenght) then
			doPlayerSendCancel(cid, "Each word must have a minimum of " .. config.minWordLenght .. " characters.")
			return true
		end
 
		paramTemp = "" .. paramTemp .. "" .. space .. "" .. word .. ""
		if(space == '') then
			space = " "
		end
	end
 
	local guid = getPlayerGUID(cid)
	t[1] = paramTemp
	doPlayerRemoveItem(cid, config.item.Id, config.item.count)
	if(pcall(doPlayerChangeName, guid, oldName, t[1]) == false) then
		db.executeQuery("INSERT INTO `player_namelocks` (`player_id`, `name`, `new_name`, `date`) VALUES (" .. guid .. ", " .. db.escapeString(oldName) .. ", " .. db.escapeString(t[1]) .. ", " .. os.time() .. ");")
		db.executeQuery("UPDATE `players` SET `name` = " .. db.escapeString(t[1]) .. " WHERE `id` = " .. guid .. " LIMIT 1;")
	end
 
	doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Your name has been changed successfully. You will be kicked in " .. config.delay .. " seconds.")
	addEvent(function(cid, forceLogout)
		if(isPlayer(cid)) then
			doRemoveCreature(cid, forceLogout)
		end
	end, config.delay * 1000, cid, false)
 
	return true
end

- - - Updated - - -

Also you can create players thats names starts with lower case
 
When I use the command shows me
Code:
Your name has been changed successfully. You will be kicked in 2 seconds.
And i relog with this same name and the Server says
Code:
OTSYS_SQLITE3_PREPARE(): SQLITE ERROR: near "LIMIT": syntax error (UPDATE "players" SET "name" = 'Test' WHERE "id" = 3 LIMIT 1;)

I'm using TFS 0.3.6, Chanename 3.0 and I have the config set to sqlite.
Can someone help me? ^_^
 
Last edited:
I'm working on the bugfixes. I just need to finish the sqlite bug and I'll be done.

Just a question:
Would you guys prefer to have a namelock control in the config, as a param or should I remove it completely?

What I mean is:
Right now the script has a second param: "force". If it's "true" it will change the player's name even if the new name is namelocked.
I really don't see a point to preserve that param since players are just probably gonna force the changename anyways.
The same goes for the config value. I'm thinking everyone will just leave it "true", so I don't know...

EDIT:
Done.
Version 4.0
Code:
Changelog (v4.0):

Optimized the code.
Removed the "force" parameter for the namelock check and replaced it with a config value (left the string.explode for future features such as changing the name of other players).
Now the script supports multiworld.
Used a workaround to fix the LIMIT bug in sqlite.
New config values:
- kick: Kicks the player after the name change.
-- enabled: To enable or disable the player kick.
-- delay: The delay value for the player kick event. Now it can be freely configured.
- forceLogout: Kick players without restrictions. It isn't needed in most cases but added a config value anyways (this is why it's not enabled by default).
- namelockCheck: To check if the new name is namelocked.
- vowelsCheck: To check if there are vowels in the new name.
- minWordLenght: The minimum lenght for each word of the new name.
- maxWordLenght: The maximum lenght for each word of the new name.
- maxWords: The maximum amount of words that the new name can have.
New checks:
- The script now detects if the server is running on "mysql" or "sqlite" and adapts the queries depending on the result.
- If the words are not in an appropiated format they are automatically fixed (e.g. rAtSeR -> Ratser).
-- The first letter of the first word will always be uppercase. In the rest of words, the first letter won't be changed.
-- The other letters of each word will be lowercase.
Lua:
local config = {
	item = {Id = 1111, count = 0},
	paramBlacklist = {"account manager", "god", "tutor", "tester"},
	kick = {enabled = true, delay = 2 * 1000},
	forceLogout = false,
	namelockCheck = true,
	vowelsCheck = true,
	maxTextLenght = 29,
	minWordLenght = 2,
	maxWordLenght = 14,
	maxWords = 3
}

config.kick.enabled = getBooleanFromString(config.kick.enabled)
config.forceLogout = getBooleanFromString(config.forceLogout)
config.namelockCheck = getBooleanFromString(config.namelockCheck)
config.vowelsCheck = getBooleanFromString(config.vowelsCheck)

function onSay(cid, words, param, channel)
	local t = string.explode(param, ",")
	local len, firstWord, wordCount, textCancel, limit = string.len(tostring(t[1])), true, 0, '', ";"
	if(getConfigValue('sqlType') == 'mysql') then
		limit = db.updateLimiter()
	end

	if(param == '') then
		return doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Command param required.")
	elseif(getPlayerGUIDByName(t[1], true) ~= nil) then
		textCancel = "That name is already in use."
	elseif(getPlayerItemCount(cid, config.item.Id) < config.item.count) then
		textCancel = "You do not fulfill the requirements."
	elseif(not getTilePzInfo(getCreaturePosition(cid))) then
		textCancel = "You must be inside a protection zone to use this command."
	elseif(len > config.maxTextLenght) then
		textCancel = "A name must have at least " .. config.minWordLenght .. " but no more than " .. config.maxTextLenght .. " letters!"
	elseif(config.namelockCheck and db.getResult("SELECT * FROM `player_namelocks` WHERE `name` = " .. db.escapeString(t[1]) .. "" .. limit .. ""):getID() ~= 1) then
		textCancel = "That name is namelocked."
	elseif(string.find(t[1]:lower(), "[^%l%s]") ~= nil) then
		textCancel = "This name contains invalid letters. Please use only A-Z, a-z and space!"
	else
		paramTemp = ''
		for word in string.gmatch(t[1], "%a+") do
			len, wordCount = string.len(word), wordCount + 1
			if(isInArray(config.paramBlacklist, paramTemp:lower())) then
				textCancel = "Invalid name entry."
				break
			elseif(len < config.minWordLenght) then
				textCancel = "This name contains a word with only " .. len .. " letter" .. (len > 1 and "s" or '') .. ". Please use more than " .. len .. " letter" .. (len > 2 and "s" or '') .. " for each word!"
				break
			elseif(len > config.maxWordLenght) then
				textCancel = "This name contains a word that is too long. Please use no more than " .. config.maxWordLenght .. " letters for each word!"
				break
			elseif(wordCount > config.maxWords) then
				textCancel = "This name contains more than 3 words. Please choose another name!"
				break
			elseif(config.vowelsCheck and string.find(word:lower(), "[aeiouy]") == nil) then
				textCancel = "This name contains a word without vowels. Please choose another name!"
				break
			else
				wordTemp = ''
				for i = 1, len do
					letter = string.sub(word, i, i)
					if(i == 1) then
						if(getBooleanFromString(firstWord) and string.find(letter, "%l")) then
							letter = string.upper(letter)
						end
					else
						if(string.find(letter, "%u")) then
							letter = string.lower(letter)
						end
					end

					firstWord = false
					wordTemp = "" .. wordTemp .. "" .. letter .. ""
				end
			end

			paramTemp = "" .. paramTemp .. "" .. (paramTemp ~= '' and " " or '') .. "" .. wordTemp .. ""
		end
	end

	if(textCancel ~= '') then
		doPlayerSendCancel(cid, textCancel)
		return true
	end

	local oldName, guid = getCreatureName(cid), getPlayerGUID(cid)
	t[1] = paramTemp
	doPlayerRemoveItem(cid, config.item.Id, config.item.count)
	if(pcall(doPlayerChangeName, guid, oldName, t[1]) ~= true) then
		db.executeQuery("INSERT INTO `player_namelocks` (`player_id`, `name`, `new_name`, `date`) VALUES (" .. guid .. ", " .. db.escapeString(oldName) .. ", " .. db.escapeString(t[1]) .. ", " .. os.time() .. ");")
		db.executeQuery("UPDATE `players` SET `name` = " .. db.escapeString(t[1]) .. " WHERE `id` = " .. guid .. "" .. limit .. "")
	end

	doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Your name has been changed successfully." .. (config.kick.enabled and " You will be kicked in " .. config.kick.delay / 1000 .. " seconds." or " Re-enter the game to see the changes.") .. "")
	if(config.kick.enabled) then
		addEvent(function(cid, forceLogout)
			if(isPlayer(cid)) then
				doRemoveCreature(cid, forceLogout)
			end
		end, config.kick.delay, cid, config.forceLogout)
	end

	return true
end
 
Last edited:
Back
Top