I am working on a game in which you can sail with boats. My script works but I wonder if I am doing it right?
What I'm trying to do is that as soon as you spawn a boot the name of the boot is the userID + the name of the ship.
This works fine thanks to one guy on this forum (Much Love)!
So now I wanted to write a script inside the seat as soon as another player or the player himself sits on the chair changes the name of the boat to that player name + boat name. This works, but now I have managed to get the name of the player and not his id. I prefer the ID of the player. How do you do that?
Because I get the player name instead of his id. I had to make another check to see if the boat does not already exist. Now 1 player can get 2 boats because player.Name and player.UserID do not match.
So my question is how do I get the userID instead of its name from the script below so that a player can take over the boat but not get 2 boats in the end?
I'm sorry for my bad coding i'm new to this :) Thanks for helping out!
Script inside of seat:
local Seat = script.Parent
local debounceCheck = false
local ChangeBoatName = script.Parent.Parent
local boatname = "ShipOnePerson"
Seat.Changed:Connect(function(player)
if Seat.Occupant ~= nil then
if Seat.Occupant.Parent.Name ~= "PlayerNameHere" then
local PlayerToNewBoat = game.Players:FindFirstChild(Seat.Occupant.Parent.Name)
local Character = PlayerToNewBoat.Character or PlayerToNewBoat.CharacterAdded:Wait()
if not debounceCheck then
-- Is it Occupant?
debounceCheck = true
-- Mark it as Occupant, so that other handlers don't execute
if ChangeBoatName then
local plruserid = Seat.Occupant.Parent.Name
local SetNameToBoat = plruserid..boatname
local NewBoat = ChangeBoatName
NewBoat.Name = SetNameToBoat
NewBoat.Parent = game.Workspace
print(NewBoat)
end
end
else
debounceCheck = false
-- Mark it as not Occupant, so other handlers can execute again
end
else
debounceCheck = false
-- Mark it as not Occupant, so other handlers can execute again
end
end)
My second question is how can I make sure that as soon as you press the button RegenButton it first checks if there is already a boat in that place and if so how do I make sure that you cannot spawn?
Below is the code that is in the button regenbutton
local cd = workspace.Regenbutton:WaitForChild('ClickDetector')
local boat = game:GetService('ServerStorage'):WaitForChild('ShipOnePerson')
local button = workspace:WaitForChild('Regenbutton')
local debounce = false
local boatname = "ShipOnePerson"
cd.MouseHoverEnter:Connect(function()
button.Transparency = 0.5
end)
cd.MouseHoverLeave:Connect(function()
button.Transparency = 0
end)
cd.MouseClick:Connect(function(player)
local plruserid = player.UserId
local SetNameToBoat = plruserid..boatname
local plrextraboat = player.Name..boatname
print(SetNameToBoat)
local oldboat = workspace:FindFirstChild(SetNameToBoat)
local oldboat2 = workspace:FindFirstChild(plrextraboat)
if not debounce then
if oldboat then
oldboat:destroy()
end
if oldboat2 then
oldboat2:destroy()
end
debounce = true
local NewBoat = boat:Clone()
NewBoat.Name = SetNameToBoat
NewBoat.Parent = game.Workspace
wait(5)
debounce = false
end
end)
So my question is how do I get the userID instead of its name
Instead of Player.Name use Player.UserId
My second question is how can I make sure that as soon as you press the button RegenButton it first checks if there is already a boat in that place and if so how do I make sure that you cannot spawn?
You could use Instance.GetChildren to get a list of all children, then iterate over that list in a loop. Check wether any of those children is a boat Instance.IsA and if so, check whether it is in the spawn location.
Related
while true do
wait(1)
local randomnumber = math.random(18,150)
local x = math.random(1,50)
local Pointgiver = game.ReplicatedStorage.Points:Clone()
Pointgiver.Parent = game.Workspace
Pointgiver.Position = Vector3.new(randomnumber,0.5,x)
Pointgiver.Transparency = 0
end
local pointgiver = game.Workspace:WaitForChild("Points")
pointgiver.ClickDetector.Mousetouch:Connect(function()
pointgiver:Destroy()
end)
as you see, im using a waitforchild function which waits for a part to spawn and doesnt give errors thats like "There is no part named "Points" "
but it wont destroy it, sorry if that didnt make sense
ClickDetector has no function named Mousetouch, instead, you should be using MouseClick which fires whenever the player clicks the respective Part. Also your code which listens for the ClickDetector.MouseClick is after the while loop and as such, it will never run as you keep calling the while loop repeatedly, and never break out of it.
while true do
task.wait(1)
local randomnumber = math.random(18,150)
local x = math.random(1,50)
local Pointgiver = game.ReplicatedStorage.Points:Clone()
Pointgiver.Position = Vector3.new(randomnumber,0.5,x)
Pointgiver.Transparency = 0
PointGiver.ClickDetector.MouseClick:Connect(function()
PointGiver:Destroy()
end)
Pointgiver.Parent = game.Workspace
end
My goal here is to send the player object and the object name through to the client script to display the object name on a text label.
When I run this, it prints nil and nil. I want player.Name and name as you will see in the second code sample. Another error I get is "attempt to concatenate nil with string" from the client script.
Here is my server-side code:
script.onTouch.OnInvoke = function(button, sellObj, sellObjValue, buyObj, buyObjValue, afterWave, isLoadedPart)
if isLoadedPart == true then
local info = script.Parent.Parent.info
local player = info.player.Value
local owner = info.owner.Value
local savedItems = info.savedItems.Value
local builds = script.Parent.Parent.activeBuilds
if afterWave > info.activeWave.Value then
info.activeWave.Value = afterWave
end
button.Parent = savedItems.buttons
button.jobDone.Value = true
if sellObj ~= nil then
sellObj.Parent = savedItems.builds
end
if buyObj ~= nil then
buyObj.Parent = builds
end
local td = require(script.Parent.tycoonDictionary)
if not table.find(td.boughtButtons, button.objectId.Value) then
table.insert(td.boughtButtons, button.objectId.Value)
end
local ui = game.ReplicatedStorage:FindFirstChild('onPartLoad')
if ui then
ui:FireClient(player, 'buyObj.Name')
print('yes')
else
print('no')
end
else
local info = script.Parent.Parent.info
local player = info.player.Value
local owner = info.owner.Value
local money = info.player.Value.leaderstats.Money
local savedItems = info.savedItems.Value
local builds = script.Parent.Parent.activeBuilds
if money.Value >= buyObjValue or money.Value == buyObjValue then
if afterWave > info.activeWave.Value then
info.activeWave.Value = afterWave
end
button.Parent = savedItems.buttons
button.jobDone.Value = true
if sellObj ~= nil then
sellObj.Parent = savedItems.builds
money.Value += sellObjValue
end
if buyObj ~= nil then
buyObj.Parent = builds
money.Value -= buyObjValue
end
local td = require(script.Parent.tycoonDictionary)
if not table.find(td.boughtButtons, button.objectId.Value) then
table.insert(td.boughtButtons, button.objectId.Value)
warn(td.boughtButtons)
end
else
player.PlayerGui.inGame.error.label.invokeScript.errorInvoke:Invoke("Insufficient Funds")
end
end
script.Parent.waveChecker.afterRun:Invoke()
end
And here is my client-side code:
game.ReplicatedStorage.onPartLoad.OnClientEvent:Connect(function(player, name)
print(player.Name, name)
print(script.Parent.Text)
script.Parent.Text = name .. 'is loaded.'
print(script.Parent.Text)
end)
Here I will tell you a little about this game. It is a tycoon that saves data using a table with all button Ids in it. When it loads, it gets the button associated with the id and fires the server code for every button. If the button is a load button, it fires the client with the player and the buyObj.Name.
Is there just a little mistake or can I not send arguments to the client at all? Any help will be appreciated!
The OnInvoke callback's first argument is always the player that fired it, so you should change line 1 of the first script to:
script.onTouch.OnInvoke = function(playerFired, button, sellObj, sellObjValue, buyObj, buyObjValue, afterWave, isLoadedPart)
And :FireClient() requires a player argument as its first argument, so you should change
ui:FireClient(player, 'buyObj.Name')
to
ui:FireClient(playerFired, player, 'buyObj.Name')
Here is the solution I came up with;
First, I read through some Roblox documentation to find that the first argument I had to send when using :FireClient was the player, and because I already had the player there, it was just sending the function to that player. Now, I had 2 choices, I could send the player twice, or delete the player variable from the script. I chose the second one.
Here is what the :FireClient line in the server script looks like now:
game.ReplicatedStorage:WaitForChild('onPartLoad'):FireClient(player, buyObj.Name)
And here is what the client function script looks like now:
game.ReplicatedStorage.onPartLoad.OnClientEvent:Connect(function(name)
if name ~= 'starterFoundation' then
script.Parent.Text = name .. ' is loaded.'
end
end)
Thank you #TypeChecked for helping me realize this!
script.Parent.MouseButton1Click:connect(function()
local RS = game:GetService("ReplicatedStorage")
local item = RS:WaitForChild("Pencil")
local price = 350
local player = game.Players.LocalPlayer
local stats = player:WaitForChild("leaderstats")
if stats.Strength.Value>=price then
stats.Strength.Value = stats.Strength.Value - price
local cloned = item:Clone()
cloned.Parent = player.Backpack
cloned.Parent = player.StarterGear
end
end)
I am trying to make a shop and it comes up with "attempt to index nil with 'WaitForChild'" on line 6:
local stats = player:WaitForChild("leaderstats")
I copied it exactly how the video had it and the video had no problem and apparently player has no value even though we set it up just one line above
It means that you are indexing a nil value, which means that player value is nil, which means that game.Players.LocalPlayer on the previous like returns nil. Why that is you need to figure out, as there is not much to go by.
The example shows that it should be local player = game:GetService("Players").LocalPlayer, so you may want to try that.
How should I make this code work? The Judoon character must regenerate, (respawn) when I click on the wall but only when he is dead.[![Regenerate][1]][1] When I click on the wall, my Judoon character has to respawn but only when he is dead.
Also how can I introduce Regen Button, the script, be separate from the Judoon model, but it should work. If you put the script Regen into Workspace, separate from the Judoon folder, it will not work.
local box = script.Parent
local debounce = false
-- DO NOT GROUP THIS WITH YOUR MODEL!
local everything = {Judoon}
local names = {Judoon}
local children = game.Workspace:children()
for i=1,#children do
if (children[i].Name == "Judoon") then -- Replace the name with your models's name.
table.insert(everything, children[i]:clone())
table.insert(names, children[i].Name)
end
end
function regen()
for i=1,#everything do
game.Workspace:findFirstChild(names[i]):remove() -- Dont mess with this stuff.
new_thing = everything[i]:clone()
new_thing.Parent = game.Workspace
new_thing:makeJoints()
end
end
function onClicked()
if Judoon:FindFirstChild("Judoon"):GetState() == Enum.HumanoidStateType.Dead then
regen()
end
end
wait(15)-- This is how long it takes untill the regen button will work again.
script.Parent.BrickColor = BrickColor.new(104)
debounce = false
end
script.Parent.ClickDetector.MouseClick:connect(onClicked)
--This regen button was made by andymewborn,hope you like(d) it!
[1]: https://i.stack.imgur.com/HhLo3.png
You can do something like this, if the humanoid is dead then regenerate.
function onClicked()
if Judoon:FindFirstChild("Judoon"):GetState() == Enum.HumanoidStateType.Dead then
regen()
end
end
New edit:
--[[
1. Put this script inside the button
2. Rename the modelname
3. The model must be a child of Workspace
--]]
button = script.Parent
modelname = "Pk" -- Model name
model = game.Workspace:FindFirstChild(modelname)
backup = model:Clone()
function Regen()
local Old =game.Workspace:FindFirstChild(modelname)
Old:Destroy()
local New = backup:Clone()
model = New -- new changes made here
New.Parent = workspace
New:MakeJoints()
end
function onClicked()
if button.BrickColor == BrickColor.new("Bright violet") then
if model:FindFirstChild("Humanoid") ~= nil then
if model.Humanoid:GetState() == Enum.HumanoidStateType.Dead then
Regen()
print("removed and added")
end
end
button.Regen:Play()
button.BrickColor = BrickColor.new("Really black")
wait(3)
button.BrickColor = BrickColor.new("Bright violet")
end
end
button.ClickDetector.MouseClick:Connect(onClicked)
I am using WorldToScreenPoint and GetPartsObscuringTarget. What I am trying to fix is that a player must detect parts of player on a different team. For example, there is a player on a team alone trying to find other players by detecting one of their humanoid parts. The script only detect parts inside the Workspace.
I've tried using Player.CharacterAdded:Wait() and a nested loop to go through players if they are on the same team or not. This didn't worked. I've been trying to fix this for the past 2 weeks.
local Player = game.Players.LocalPlayer
local Character = workspace:FindFirstChild(Player.Name)
game:GetService("RunService").Heartbeat:Connect(function()
for _, object in pairs(Character:GetDescendants()) do
if object:IsA("Part") or object:IsA("MeshPart") then
if not object:IsDescendantOf(game.Players.LocalPlayer.Character) then
local object2,visible = workspace.CurrentCamera:WorldToScreenPoint(object.Position)
if visible == true then
local pos1 = workspace.CurrentCamera.CFrame.Position
local pos2 = object.Position
local castPoints = {pos1,pos2}
local ignoreList = {game.Players.LocalPlayer.Character, object}
local obstructs = workspace.CurrentCamera:GetPartsObscuringTarget(castPoints,ignoreList)
if obstructs[1] then
return
elseif not obstructs[1] then
print(object.Name.." has been detected!")
end
elseif visible ~= true then
print("You are now incognito.")
return
end
end
end
end
end)