Hi all i´m making a script to talk with npcs but i have a problem, i need to cut in some Dialogs the sentences {Player Name} and change it for the actual player´s name and it doesn´t work, so that´s my code.
I´m using string for the dialogs.
local DialogArray = { ["Gretting"] = "Hi {Player Name} I´m jake" -- Dialog } function Talk() local PlayerFound = string.find(DialogArray[1], "{Player Name}") -- Searchs on the string {Player Name} if PlayerFound then local ChangedText = string.sub(PlayerFound, #PlayerFound) -- It try to cut the Word {Player Name} DialogArray[1] = ChangedText print(ChangedText) end end
When i try to print that appears:
ServerScriptService.Script:6: bad argument #1 to 'find' (string expected, got nil)
19:12:12.655 - Stack Begin
19:12:12.656 - Script 'ServerScriptService.Script', Line 6 - global Talk
19:12:12.656 - Script 'ServerScriptService.Script', Line 15
19:12:12.657 - Stack End
This is what I'm trying to print:
Hi imago15 I´m jake"
Please Help me i need this Urgent, I'm sorry if it seems Badly written is because I do not use string well Thanks.
1: the DialogArray
is a dictionary, not an array. Which means that its indexes/keys aren't integers.
2:the length syntax #
returns the length of an array, not a dictionary, for dictionaries, it always returns 0.
3:that isn't the use of the sub function, thats the use of the gsub function
most patterns in lua are the percentage symbol followed by a single letter, for example %a
for letters, %d
for digits, and %w
for alphanumeric symbols (numbers + letters).
one of the ways to utilize patterns is the string.format function. An example of which is :
local Str = "Please excuse my dear aunt %w" print(string.format(Str,"Sally"))--"Please excuse my dear aunt Sally"
You can probably see where it is going at this point.
in the example of the string.format function, i just used %w
without anything else. Beware that this isn't enough for functions like gmatch and gsub. just using something like %w
would only return 1 iteration. For it to return multiple iterations for those functions, you would have to do something along the lines of %w+
With that said:
local PlayerName = "imago15" local Dialogs = { ["Greeting"] = "Hi %w I´m jake" -- Dialog } function Talk() local ChangedText = string.format(Dialogs.Greeting,PlayerName) DialogArray.Greeting = ChangedText end
However, if you are using patterns like %w elsewhere, you could still use you original method of substitution
local PlayerName = "imago15" local Dialogs = { ["Greeting"] = "Hi {PlayerName} I´m jake" -- Dialog } function Talk() if Dialogs.Greeting:lower():find("{playername}") then--case insensitive local ChangedText = Dialogs.Greeting:gsub("{playername}",PlayerName) DialogArray.Greeting = ChangedText end end
You may have noticed that I used some of the functions in the string library as method, that being functions with a :
instead of a .
. Those are generally used for convenience as the string being modified doesn't have to be defined as a parameter.
But generally, str:format()
and string.format(str)
are the same thing
string.find
returns two values if the pattern was found in the string: the start of the pattern, and the end of the pattern. You can these two values(you should also know that the greeting there doesn't have an index of one, it's index is 'Greeting'.
local tbl = { 'hi'; -- has an index of 1 'roblox'; -- has an index of 2 ['rlua'] = 'roblox lua'; value is 'roblox lua', but its index is 'rlua' }
-- code break
local DialogArray = { ["Gretting"] = "Hi {Player Name} I´m jake" -- Dialog } function Talk() local s, e = string.find(DialogArray['Greeting'], "{Player Name}") if PlayerFound then local ChangedText = string.sub(DialogArray['Greeting'], s, e) DialogArray['Greeting'] = ChangedText end end
So I'm going to suggest at least two ways to circumvent this first, if you're not against using a LocalScript (which is most likely preferred for this since you want the Dialog to be player dependent) then you could do the following:
local player = game.Players.LocalPlayer local DialogArray = { ["Greeting"] = ("Hi "..player.Name..", I'm Jake"), ["Next"] = ("Next") } function Talk() print(DialogArray["Greeting"]) end Talk()
On a Server Script, you could edit the table like so:
local DialogArray = {} game.Players.PlayerAdded:Connect(function(player) DialogArray = { ["Greeting"] = ("Hi "..player.Name..", I'm Jake"), ["Next"] = ("Next") } local function Talk() print(DialogArray["Greeting"]) end Talk() end)
The PlayerAdded event could be substituted for a .Touched
or .Changed
Event or other similar event if you preferred to alter the Dialog that way (as long as they are able to produce the player's name).
If you place the local Talk function outside the PlayerAdded function in this example, adding a wait time will ensure that the new value for dialog is read (but this would affect the entire server and only be altered once)
This would remove the need for the string-based changes.
In addition, the use of the ["Greeting"]
defines the key of that value, which would otherwise be DialogArray[1] (as you attempted to write within your script) if the key had not been pre-defined.
Regarding String Changes, the above Answer covers this.