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

Attempt to call a nil value? I defined the function though! [Solved]

Asked by 9 years ago

I have a script the output says attempt to call a nil value, even though the function is the same! Why is it doing this and how can I prevent this from happening in future times? here is the script

    math.random (1,2)
    local Tool = script.Parent
    wait(2)
    if math.random == 1 then
    function onActivated()
    local rc = script.Parent.Parent.Parent.Parent.Lighting.A:Clone()
    rc.Parent = script.Parent.Parent
    end
    end

    if math.random == 2 then
    function onActivated()
    local rc = script.Parent.Parent.Parent.Parent.Lighting.B:Clone()
    rc.Parent = script.Parent.Parent
    end
    end
    Tool.Activated:connect(onActivated)

Please help!!! Thank you!!!

0
What on earth. I just submitted an answer and it didn't go through. DigitalVeer 1473 — 9y
0
XD can you re-post it please? XD yogipanda123 120 — 9y
0
I did. :P DigitalVeer 1473 — 9y

2 answers

Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

There are a few problems with this.

Begin by tabbing your code correctly


You are defining onActivated twice.

It's usually bad o define functions inside if or for or while. In this case, that is causing a problem, especially because

Your two if statements AREN'T such that if one happens, the other doesn't:

  • The first one may succeed and the second fail (use A)
  • The second may succeed and the first may fail (use B)
  • Both may succeed (first use A, then obliterate that and use B)
  • Neither may succeed (the cause of your error).

You defined Tool but barely use it! That will shorten your code a lot. But the lowercase tool would be preferable in ROBLOX's naming system (and the remainder of your names).

At the same time, it makes no sense at all to refer to Lighting like that. Use game.Lighting. Besides that, you should use ReplicatedStorage for storing objects, not the Lighting.

So ABSOLUTELY first, we need to use else instead of having two ifs:

math.random(1, 2);
local tool = script.Parent;
wait(2);
if math.random == 1 then
    function onActivated()
        local rc = tool.Parent.Parent.Parent.Lighting.A:Clone();
        rc.Parent = tool.Parent;
    end
else
    function onActivated()
        local rc = tool.Parent.Parent.Parent.Lighting.B:Clone();
        rc.Parent = tool.Parent;
    end
end
Tool.Activated:connect(onActivated);

This will prevent the error. However, it's still wrong.

math.random is a function. It won't ever be 1. You have to call it, like you did on the first line. But the call on the first line doesn't do anything since you didn't use the value it returned.

You should instead say

local tool = script.Parent
wait(2);
if math.random(2) == 1 then -- same as with (1, 2)
    function onActivated()
        local rc = tool.Parent.Parent.Parent.Lighting.A:Clone();
        rc.Parent = tool.Parent;
    end
else
    function onActivated()
        local rc = tool.Parent.Parent.Parent.Lighting.B:Clone();
        rc.Parent = tool.Parent;
    end
end
Tool.Activated:connect(onActivated);

As I said earlier, though, you shouldn't be defining the function twice.

You should define it once.

If you meant that, it will decide when created either A or B to use forever, then you would want to do this:

local tool = script.Parent
local rc
if math.random(2) == 1 then
    rc = game.Lighting.A -- Use ReplicatedStorage instead, though.
else
    rc = game.Lighting.B
end

function onActivated()
    rc:Clone().Parent = tool.Parent;
end
Tool.Activated:connect(onActivated);

If you instead wanted to make it random each time the tool is activated, you would move the if into the function:

local tool = script.Parent


function onActivated()
    if math.random(2) == 1 then
        game.Lighting.A:Clone().Parent = tool.Parent
        -- Use ReplicatedStorage instead, though.
    else
        game.Lighting.B:Clone().Parent = tool.Parent
    end
end
Tool.Activated:connect(onActivated);
0
Sorry i can't give you a point, I am in the negetives... again yogipanda123 120 — 9y
Ad
Log in to vote
1
Answered by 9 years ago

Variables

Variables must be declared and initiated in a 'foo=bar' type of format. Just saying 'math.random(1,2) is not correct. You must bind it to a variable name.

For example, you can do:

local ran = math.random(1,2)
if ran == 1 then 
print("It's 1!")
else
print("It's 2!")
end

Functions

In basic terms, functions are pre-written chunks of code that can be called to adapt to new or constant arguments. When functions are declared, THEY ARE NOT RUN. Functions must be called in order for them to run.

Let's look at an example:

function printHi()
print("Hi!")
end

The following code above won't print anything even though the function has been declared because it hasn't called the function yet.

Now, let's call it:

function printHi()
print("Hi!")
end

printHi()
--Outputs "Hi!"

Not only this; You can not have two functions with the same name. If you tried calling one, the compiler would be pretty upset with you for declaring two with the same name.

Lighting

Don't use Lighting to store objects. Put them in Server Storage or Replicated Storage. It is more paradigm-like and there are certain advantages to it along with organization and structural neatness.

Fix

Alright, now using what we've learned, let's fix your script:

local Tool = script.Parent

function chooseA()
local rc = script.Parent.Parent.Parent.Parent.Lighting.A:Clone()
rc.Parent = script.Parent.Parent
end

function chooseB()
local rc = script.Parent.Parent.Parent.Parent.Lighting.B:Clone()
rc.Parent = script.Parent.Parent
end

function onActivated()
local ran = math.random(1,2)
if ran == 1 then
chooseA()
else
chooseB()
end

Tool.Activated:connect(onActivated)

Answer this question