Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How do you set player ownership?

Asked by 8 years ago

I'm having a tough time properly setting variables such as money, and part ownership, to specific players. I know how to get the UserId of a player touching a block. I've managed to make a single-player tycoon by setting ownership of a door and then checking UserId of different parts when players touch them. My problem is that this only works with one plot, I'm having trouble cloning parts and connecting them to only a single player without using global variables. For instance, when I touch a door a button spawns that, when touched, either tells you you don't own it, or buys a dropper. This works fine if I only have one door, and one plot of droppers. If i add a second door or plot they link in with the first set through the global variable I've set. If I set it as just a local variable, there's no way to get the button to recognize an owner as far as I know. If someone would nudge me in the right direction I would greatly appreciate it.

0
you can always have object variables assigned to specific parts. So that when you touch a door, you can verify it using the object variable assigned to the brick. scottmike0 40 — 8y

1 answer

Log in to vote
0
Answered by
tkcmdr 341 Moderation Voter
8 years ago
Edited 8 years ago

Hey syntaxjedi,

Wonderful question! I appreciate your effort to understand things in good enough detail to see this problem. It is for this reason that I would love to give you an explanation:

Scripts in ROBLOX obviously can't share data with each other directly, so people often circumvent this by using _G or things like IntValues and NumberValues. These ways work, but there are two problems with these approaches:

  1. They're messy: these methods involve exposing data to all scripts, not just the ones that actually need the data. This opens the door for encapsulation problems, which I will explain in a moment...

  2. They're insecure: anyone who has the ability to see your game's hierarchy -- usually by way of external programs, like exploits, -- will be able to quickly find these exposed values and will be free to change them!

Now, encapsulation is a practice that involves restricting access for variables only where they are intended to be accessed. Here's an example:

Points      = 10

...

function AddPoints()
    newPoints = Points + 50

    ...
end

DoStuff()

...

print(newPoints) --> 60

Oh no! Variable newPoints is accessible outside AddPoints! This may be immediately noticeable in a small script, but in a large script, you may forget that it already exists, and use it again, which can lead to very big problems down the line that will take lots of time to resolve.

What can we do? Use the local keyword. Local is something called an access modifier. It limits where a variable can be accessed. Using local, we can restrict newPoints to AddPoints, preventing unintentional behavior further down the road. Observe:

local Points        = 10

...

local function AddPoints()
    local newPoints = Points + 50

    ...
end

DoStuff()

...

print(newPoints) --> nil

Wonderful! This doesn't just apply to variables in scripts, though. You might end up using _G or IntValues and ObjectValues to share data among scripts, which will cause the same problem!

Now, you may be wondering why I took the time to explain encapsulation, since it doesn't exactly answer your question. You may even already know what local is, and probably have a working knowledge of encapsulation.

I went through all this to solidify in your mind what you've deduced and ultimately lead you to ask this wonderful question. IntValues and _G suffer from these same encapsulation problems, and overcoming these problems by using loads of different names or spreading them out in weird schemes only adds to confusion and messiness. *There has to be a better way,* you wonder.

And you're right.

BEHOLD: BindableFunctions!

BindableFunctions are a way for two scripts to talk to each other. A script can call another script's BindableFunction and find out if that script's tycoon has the same owner! How do we use them, though? Here's how:

  1. Make a BindableFunction, and put it in the model that contains all the tycoons; name it PlayerOwnsTycoon.

  2. Make a script in ServerScriptService that, when PlayerOwnsTycoon is invoked, checks each tycoon's owner and returns true if a player already owns a tycoon. Write like so:

local Tycoons       = path.To.Tycoon.FolderOrModel;
local OwnsTycoon    = Tycoons:WaitForChild("PlayerOwnsTycoon")

function OwnsTycoon.OnInvoke(player)
    for i, tycoon in ipairs(Tycoons:GetChildren()) do
        local owner = tycoon.GetOwner:Invoke()

        if (owner == player) then
            return true
        end
    end
end
  1. Inside the door script, write the following:
local Owner     = nil
local Door      = path.To.Door
local GetOwner  = path.To.GetOwner
local OwnsTycoon    = path.To.OwnsTycoon

-- Returns the owner of the tycoon, or nil if there is none.
local function GetOwner.OnInvoke()
    return Owner
end

-- Set the owner if other is a character part, AND if the player does not already own a tycoon
local function OnTouched(other)
    local player = game.Players:GetPlayerFromCharacter(other.Parent)

    -- When we invoke OwnsTycoon, the script we made earlier will look through each tycoon, and return true if the player already has a tycoon. By using not, we're saying: "Hey, if this is true, then don't set the owner!"
    if (player and not OwnsTycoon:Invoke(player)) then
        Owner = player;
    end
end

Door.Touched:Connect(OnTouched)

By now, you have the basis for:

  1. Setting the owner of a tycoon, and...
  2. Verifying if the player doesn't already have a tycoon before setting the Owner.

This method is much more secure than using ObjectValues, and it will be rather robust as well. What's more, you can use BindableFunctions to share things like points, tycoon progress, etc... anything you like!

Here are links to various similar objects that will help you make custom events too, or even allow local and server scripts to talk to each other:


BindableEvents


RemoteFunctions


RemoteEvents


If you can learn to use all these effectively, you'll be well on your way to creating very efficient and manageable games!

Have a nice day, syntaxjedi, and best of luck with your tycoon project!

Warm regards,

tkcmdr

Edit: Improved formatting

0
Thanks so much, this is exactly what I was looking for! It's the only thing I needed to complete my game! syntaxjedi 22 — 8y
0
actually, i'm having trouble getting this to work. What exactly am I amending to "local OwnsTycoon = path.To.OwnsTycoon"? Am I supposed to put the function in there? When I do I get the error, "OwnsTycoon is not a valid member of Script." I'm having a little trouble understanding how these scripts work together I guess. syntaxjedi 22 — 8y
0
Glad I helped! I hope you have similar success with your future games. Don't forget to mark this as the answer to your question. Have a nice day! c; tkcmdr 341 — 8y
0
OwnsTycoon should be equal to the RemoteFunction OwnsTycoon, which is supposedly directly under the model containing all Tycoons. You must replace 'path.To.OwnsTycoon' with the path to the Tycoon container's OwnsTycoon RemoteFunction. tkcmdr 341 — 8y
View all comments (9 more)
0
*BindableFunction tkcmdr 341 — 8y
0
This needs way more clarification. It's not working in the slightest, I'm more confused now than when I originally asked the question. syntaxjedi 22 — 8y
0
See if you use object values and use fe it does not affect the server if the person changes it locally. So even if they wete to change all objs it only affects their client scottmike0 40 — 8y
0
i'm more confused as to why, and how, this script works syntaxjedi 22 — 8y
0
If this is too complicated for you to understand, then you should really study the Lua manual and the ROBLOX API. I cover thet in this forum post: tkcmdr 341 — 8y
0
*them tkcmdr 341 — 8y
0
I eventually got it to work, my problem ended up not being that I was misunderstanding the code, but that I was getting the hierarchy wrong. I thought I was implementing it wrong or just not understanding. It turned out I was just putting the function in the wrong spot which was causing all kinds of problems. syntaxjedi 22 — 8y
0
Alright! Glad you managed to fix it yourself. Good job, syntaxjedi! I appreciate your perseverance and ingenuity. Good luck with your project, bud. Have a good one. c; tkcmdr 341 — 8y
Ad

Answer this question