AStopher
AStopher

Reputation: 4561

In Lua, a variable is unexpectedly nil

I have programmed a 'punishbox' (to punish a player for rulebreaking) for my Crysis Wars server mod but for some reason I keep getting this error:

[Warning] [Lua Error] scripts/functions.lua:340: attempt to perform arithmetic on global 'tme' (a nil value)

But the thing is, tme is actually a number value between 0 and 15. The below code basically sets up the 'punishbox' and checks if it's still valid for the player or not. As you can see, tme is actually a value (if it was not, the code would not run at all). Am I doing something wrong here?

As this is a specific situation, I can't find that much on the internet. tme is referenced from time, which is forwarded to the function by a chat command and is definitely a number.

Also, is there any simpler way of doing this?

Code:

function XPunishPlayer(Name, time, reason)
    if (time > 5) then
        System.LogAlways("[SYSTEM] Punished by administrator: "..Name:GetName().."");
    end
    if (not Msg) then
        local tme = math.floor(time*60);
        Msg = true;
        XMessageChatToPlayer(Name, "[!punish] You were punished for "..time.." minutes:    "..reason.."");
        g_gameRules.game:RenamePlayer(Name.id, "[PUNISH]"..Name:GetName().."");
        XMessageChatToPlayer(Name, "[!punish] You can use !pm to dispute this punishment.");
        g_gameRules:KillPlayer(Name);
    end
    Script.SetTimer( 1000,function()
        local tme = tme+1;
        XPunishPlayer(Name, time, reason);
        Name.actor:SetNanoSuitEnergy(0);
        local punish = math.floor(timeleft-1);
        g_gameRules.onClient:ClStepWorking(g_gameRules.game:GetChannelId(Name.id), tme);
        if (tme == math.floor(time*60)) then
            g_gameRules.onClient:ClStepWorking(g_gameRules.game:GetChannelId(Name.id), false);
            XMessageChatToPlayer(Name, "[!punish] Released from the punishbox.");
            XMessageInfoToAll("Unpunished "..Name:GetName()..", was punished for "..time.."     minutes: "..reason.." (Server Administration)");
            return;
        end
    end);
end

Upvotes: 3

Views: 1142

Answers (1)

dualed
dualed

Reputation: 10512

Your tme is defined in an if block, in Lua every block creates its own closure, and so the value of tme is local to that block.

You can either make it a global variable by simply removing the local keyword (this is usually not a good idea) or define it before the block like this:

function XPunishPlayer(Name, time, reason)
    if (time > 5) then
        System.LogAlways("[SYSTEM] Punished by administrator: "..Name:GetName().."");
    end
    local tme;
    if (not Msg) then
        tme = math.floor(time*60);
        [...]
    end
    Script.SetTimer( 1000,function()
        tme = tme-1;
        [...]
    end);
end

I am also quite sure the second local tme inside your SetTimer would have given you another headache...

Upvotes: 2

Related Questions