Having this error when I run my gamemode.
[ERROR]
gamemodes/rp/gamemode/cl_init.lua:910: attempt to index field 'Config' (a nil value)
1. unknown - gamemodes/rp/gamemode/cl_init.lua:910
config is a table, with index's such as config["Run Speed"] and the entire table is set globally equal to GM.Config in the sh_config.lua file. Why is config not being registered as a value? Must I include the config file into the cl_init file? and if so, how? Using the include()?
function GM:Think()
if ( self.Config["Local Voice"] ) then **--Referred line(910)**
for k, v in pairs( player.GetAll() ) do
if ( hook.Call("PlayerCanVoice",GAMEMODE, v) ) then
if ( v:IsMuted() ) then v:SetMuted(); end
else
if ( !v:IsMuted() ) then v:SetMuted(); end
end
end
end
-- Call the base class function.
return self.BaseClass:Think();
end
Edit -- config table in sh_config.lua.
local config = {};
-- Command
config["Command Prefix"] = "/"; -- The prefix that is used for chat commands.
config["Maximum Notes"] = 2; -- Maximum notes per player
config["Advert Cost"] = 60; -- The money that it costs to advertise.
config["Advert Timeout"] = 150 -- How many seconds between adverts
config["OOC Timeout"] = 60 -- How many seconds between OOC messages
config["Item Timer"] = 7 -- How many seconds between item uses
config["Item Timer (S)"] = 20 -- How many seconds between specific item uses
config["Note Fade Speed"] = 12 -- How many minutes before nots disappear
-- Voice
config["Local Voice"] = true; -- Players can only hear a player's voice if they are near them. This is the index being called which is creating an error.
config["Talk Radius"] = 256; -- The radius of each player that
--other players have to be in to hear them talk (units).
-- Player Stuff
config["Walk Speed"] = 150; -- The speed that players walk at.
config["Run Speed"] = 275; -- The speed that players run at.
GM.Config = config;
I have includecs("sh_config.lua"); in sh_init.lua. include("sh_config.lua") and AddCSLuaFile("sh_config.lua") in init.lua. and include("sh_config.lua"); in cl_init.lua.
Im still getting this stupid error though. Can someone explain what the difference between including and Addcs'ing a file does. How do I make sh_config's variables global in other files? Or in other words how do I make the desired file(cl_init) read through the code in sh_config.lua and I can use code from it in the client side init?
You need to include sh_config.lua at the top of cl_init.lua.
include("path/to/file.lua")
Be sure to do AddCSLuaFile("path/to/lua.lua") in the init.lua file as well. You will also need to do include("path/to/file.lua") in init.lua as well. (That's only required for shared files, though)
Also I am pretty sure the scope of your config table would be limited to sh_config.lua so you should remove local from your variable declaration.
*sh_config* is a shared file - Meaning it'll have to be included both clientside, and serverside.
In init.lua - In top of the other includes. Put include("sh_config.lua")
Also in init.lua, put AddCSLuaFile("sh_config.lua") - This will make sure the file is downloaded by the client, and executed clientside.
In cl_init.lua - put include("sh_config.lua"). Also around the other includes. This should work as expected.
Seeing how this is a Config file, I assume it should be included first, or almost first. It may contain vital settings, for the rest of the script load.
Also - Often a shared.lua is included, to be equal to a shared_init file. This may be your case. If it is, you should add one include("sh_config.lua") with the includes, in shared.lua, and AddCSLuaFile("sh_config.lua") in a if CLIENT then-block
Related
I started with Roblox a few months ago and my only semi-related prior experience is in web development, so you're dealing with a noob here.
I'm having trouble awarding my game's currency to the players of the winning team of a round. Every other aspect of my currency seems to work fine - it displays, can update, saves with datastores etc.
This in-game currency is set up in the same manner as leaderstats (but not as a leaderstats) - it's created under the player at runtime (if that's the proper way of saying it) via a script in SSS.
The function I'm having issues with doesn't seem to do anything, and I've tried about 20 different variations, some of which were radically different from this. The one below is the last one I tried before giving up to seek help here.
function goldToWinningTeam()
local winningTeam = TeamManager:GetWinningTeam()
for i, Player in pairs(Players:GetPlayers()) do
if player.TeamColor == winningTeam.TeamColor then
player.currency.Gold.Value += 100
else
player.currency.Gold.Value += 50
end
end
end
This doesn't produce any output errors or interfere with other game logic as far as I can tell.
At the moment, for testing, the function above is in my main game script (a regular script). Its proper/ideal location, upon getting it to work, is also something I'd appreciate some feedback on. I was thinking either in my TeamManager or PlayerManager module scripts, or possibly my GameCurrecy script, which is a regular script in SSS.
Below are the TeamManager function(s) called from above. I've tried using either. Both work as expected for their intended purpose of displaying a victor at round end. I figured they would also work in this use case.
function TeamManager:GetWinningTeam()
local highestScore = 0
local winningTeam = nil
for _, team in ipairs(Teams:GetTeams()) do
if TeamScores[team] > highestScore then
highestScore = TeamScores[team]
winningTeam = team
end
end
return winningTeam
end
-- Below works identically for displaying victor
function TeamManager:HasTeamWon()
for _, team in ipairs(Teams:GetTeams()) do
if TeamScores[team] >= Configurations.DESTROYS_TO_WIN then
return team
end
end
return false
end
Again, I'm very new to this and it's only a hobby, please forgive any obvious ignorances.
I have a Lua function where I build a table of value and attempt to add it to a global table with a named key.
The key name is pulled from the function arguments. Basically, it's a filename, and I'm pairing it up with data about the file.
Unfortunately, the global table always comes back nil. Here's my code: (let me know if you need to see more)
(Commented parts are other attempts, although many attempts have been deleted already)
Animator = Class{}
function Animator:init(atlasfile, stringatlasfriendlyname, totalanimationstates, numberofframesperstate, booleanstatictilesize)
-- Define the Animator's operation mode. Either static tile size or variable.
if booleanstatictilesize ~= false then
self.isTileSizeStatic = true
else
self.isTileSizeStatic = false
end
-- Define the total animation states (walking left, walking right, up down, etc.)
-- And then the total frames per state.
self.numAnimationStates = totalanimationstates or 1
self.numAnimationFrames = numberofframesperstate or 2
-- Assign the actual atlas file and give it a programmer-friendly name.
self.atlasname = stringatlasfriendlyname or removeFileExtension(atlasfile, 'animation')
generateAnimationQuads(atlasfile, self.atlasname, self.numAnimationStates, self.numAnimationFrames)
end
function generateAnimationQuads(atlasfile, atlasfriendlyname, states, frames)
spriteWidthDivider = atlasfile:getWidth() / frames
spriteHeightDivider = atlasfile:getHeight() / states
animationQuadArray = generateQuads(atlasfile, spriteWidthDivider, spriteHeightDivider)
animationSetValues = {atlasarray = animationQuadArray, width = spriteWidthDivider, height = spriteHeightDivider}
--gAnimationSets[#gAnimationSets+1] = atlasfriendlyname
gAnimationSets[atlasfriendlyname] = animationSetValues
--table.insert(gAnimationSets, atlasfriendlyname)
end
Note: when using print(atlasfriendlyname) and print(animationSetValues), neither are empty or nil. They both contain values.
For some reason, the line(s) that assign the key pair to gAnimationSets does not work.
gAnimationSets is defined a single time at the top of the program in main.lua, using
gAnimationSets = {}
Animator class is called during the init() function of a character class called Bug. And the Bug class is initialized in the init() function of StartState, which extends from BaseState, which simply defines dummy init(), enter(), update() etc. functions.
StartState is invoked in main.lua using the StateMachine class, where it is passed into StateMachine as a value of a global table declared in main.lua.
gAnimationSets is declared after the table of states and before invoking the state.
This is using the Love2D engine.
Sorry that I came here for help, I've been picking away at this for hours.
Edit: more testing.
Trying to print the animationQuadArray at the index gTextures['buganimation'] always returns nil. Huh?
Here's gTextures in Main.lua
gTextures = {
['background'] = love.graphics.newImage('graphics/background.png'),
['main'] = love.graphics.newImage('graphics/breakout.png'),
['arrows'] = love.graphics.newImage('graphics/arrows.png'),
['hearts'] = love.graphics.newImage('graphics/hearts.png'),
['particle'] = love.graphics.newImage('graphics/particle.png'),
['buganimation'] = love.graphics.newImage('graphics/buganimation.png')
}
Attempting to return gTextures['buganimation'] returns a file value as normal. It's not empty.
My brain is so fried right now I can't even remember why I came to edit this. I can't remember.
Global table in Main.lua, all other functions can't access it.
print(gTextures['buganimation']) works inside the function in question. So gTextures is absolutely accessible.
Table isn't empty. AnimationSetValues is not empty.
I'm adding second answer because both are correct in context.
I ended up switching IDE's to VS Code and now the original one works.
I was originally using Eclipse LDT with a Love2D interpreter and in that environment, my original answer is correct, but in VS Code, the original is also correct.
So Dimitry was right, they are equivalent, but something about my actual Eclipse setup was not allowing that syntax to work.
I switched to VS Code after I had another strange syntax problem with the interpreter where goto syntax was not recognized and gave a persistent error. The interpreter thought goto was the name of a variable.
So I switched, and now both things are fixed. I guess I just won't use LDT for now.
Solution: Lua syntax. Brain Fry Syndrome
I wrote:
animationSetValues = {atlasarray = animationQuadArray, width = spriteWidthDivider, height = spriteHeightDivider}
Should be:
animationSetValues = {['atlasfile']=atlasfile, ['atlasarray']=animationQuadArray, ['width']=spriteWidthDivider, ['height']=spriteHeightDivider}
Edit: I'm fully aware of how to use answers. This was posted here to reserve my spot for an answer so I could edit it later when I returned back home, which is exactly what I'm doing right now. I'll keep the old post for archival purposes.
Original:
I solved it. I apologize for not posting the solution right now. My brain is melted into gravy.
I will post it tomorrow. Just wanted to "answer" saying no need to help. Solved it.
Solution is basically, "oh it's just one of those Lua things". Wonderful. I'm having so much fun with this language - you can tell by my blank expression.
From the language without line endings or brackets, but forced print parentheses... ugh. I'm going back to C# when this class is done.
This code is for a modding engine, Unitale base on Unity Written in Lua
So I am trying to use a Boolean Variable in my script poseur.lua, so when certain conditions are met so I can pass it to the other script encounter.lua, where a engine Predefined functions is being uses to make actions happens base on the occurring moment.
I tried to read the engine documentation multiple times, follow the exact syntax of Lua's fonction like GetVar(), SetVar(), SetGobal(),GetGlobal().
Searching and google thing about the Language, post on the subreddit and Game Exchange and tried to solve it by myself for hours... I just can't do it and I can't understand why ?
I will show parts of my codes for each.
poseur:
-- A basic monster script skeleton you can copy and modify for your own creations.
comments = {"Smells like the work\rof an enemy stand.",
"Nidhogg_Warrior is posing like his\rlife depends on it.",
"Nidhogg_Warrior's limbs shouldn't\rbe moving in this way."}
commands = {"GREET", "JUMP", "FLIRT", "CRINGE"}
EndDialougue = {" ! ! !","ouiii"}
sprite = "poseur" --Always PNG. Extension is added automatically.
name = "Nidhogg_Warrior"
hp = 99
atk = 1
def = 1
check = "The Nidhogg_Warrior is\rsearching for the Nidhogg"
dialogbubble = "rightlarge" -- See documentation for what bubbles you have available.
canspare = false
cancheck = true
GreetCounter = 5
Berserk = false
encounter:
-- A basic encounter script skeleton you can copy and modify for your own creations.
encountertext = "Nidhogg_Warrior is\rrunning frantically"
nextwaves = {"bullettest_chaserorb"}
wavetimer = 5.0
arenasize = {155, 130}
music = "musAncientGuardian"
enemies = {"poseur"}
require("Monsters.poseur")
enemypositions = {{0, 0}}
-- A custom list with attacks to choose from.
-- Actual selection happens in EnemyDialogueEnding().
-- Put here in case you want to use it.
possible_attacks = {"bullettest_bouncy", "bullettest_chaserorb", "bullettest_touhou"}
function EncounterStarting()
-- If you want to change the game state immediately, this is the place.
Player.lv = 20
Player.hp = 99
Player.name = "Teemies"
poseur.GetVar("Berserk")
end
Thank you for reading.
The answer to my problem was to use SetGobal(), GetGobal().
For some reasons my previous attempt to simply use SetGobal()Resulted in nil value despite writing it like that SetGobal("Berserk",true) gave me a nill value error, as soon as I launch the game.
But I still used them wrong. First I needed to put it SetGobal() at the end of the condition instead of at the start of the the poseur.lua script because the change of value... for some reasons was being overwritten by it first installment.
And to test the variable in the function in my encounter.lua, I needed to write it like that
function EnemyDialogueStarting()
-- Good location for setting monster dialogue depending on how the battle is going.
if GetGlobal("Jimmies") == true then
TEEEST()
end
end
Also any tips an suggestions are still welcome !
Well firstly, in lua simple values like bool and number are copied on assignment:
global={}
a=2
global.a=a--this is a copy
a=4--this change won't affect value in table
print(global.a)--2
print(a)--4
Secondly,
SetGobal and the other mentioned functions are not part of lua language, they must be related to your engine. Probably, they use word 'Global' not as lua 'global' but in a sense defined by engine.
Depending on the engine specifics these functions might as well do a deep copy of any variable they're given (or might as well not work with complicated objects).
-- This is some of the code made by Roblox themselves:
-- Setup table that we will return to scripts that require the ModuleScript.
local PlayerStatManager = {}
-- Table to hold all of the player information for the current session.
local sessionData = {}
-- Function the other scripts in our game can call to change a player's stats. This
-- function is stored in the returned table so external scripts can use it.
function PlayerStatManager:ChangeStat(player, statName, changeValue)
sessionData[player][statName] = sessionData[player][statName] + changeValue
end
-- Function to add player to the sessionData table.
local function setupPlayerData(player)
sessionData[player] = {Money = 0, Experience = 0}
end
-- Bind setupPlayerData to PlayerAdded to call it when player joins.
game.Players.PlayerAdded:connect(setupPlayerData)
-- Return the PlayerStatManager table to external scripts can access it.
return PlayerStatManager
--------------------------------------------------------------------------------
-- Require ModuleScript so we can change player stats
local PlayerStatManager = require(game.ServerStorage.PlayerStatManager)
-- After player joins we'll periodically give the player money and experience
game.Players.PlayerAdded:connect(function(player)
while wait(2) do
PlayerStatManager:ChangeStat(player, 'Money', 5)
PlayerStatManager:ChangeStat(player, 'Experience', 1)
end
end)
When I run these two script, it run perfectly, adding the print(sessionData[player][statName]) inside the ChangeStat function, but when I removed the game.Players.PlayerAdded:connect(setupPlayerData) part in the module script, it stopped working. I though module script does not execute code without it being called, and if that was the case, shouldn't the game.Players.PlayerAdded:connect(setupPlayerData) part be delay and not function since player's already added, therefore it not firing?
require executes the required code.
If that was not the case you would not be able to get a table through require, as your return PlayerStatManager statement would not be executed.
As a consequence removing
-- Bind setupPlayerData to PlayerAdded to call it when player joins.
game.Players.PlayerAdded:connect(setupPlayerData)
will cause an added player not to be initialized properly. This basically says: when a new player is added, call setupPlayerData.
Where setupPlayerData says: give a new set of stats to player
As you removed that line no player has stats. If you don't have stats you can't increase their values...
So obviously you did not understand what the code did befor you changed it. Therefor you cannot understand why your changes cause problems.
If you change a system you don't understand you can be lucky, but in most cases you will utterly fail.
It is my understanding that in Lua 5.2 that environments are stored in upvalues named _ENV. This has made it really confusing for me to modify the environment of a chunk before running it, but after loading it.
I would like to load a file with some functions and use the chunk to inject those functions into various environments. Example:
chunk = loadfile( "file" )
-- Inject chunk's definitions
chunk._ENV = someTable -- imaginary syntax
chunk( )
chunk._ENV = someOtherTable
chunk( )
Is this possible from within Lua? The only examples I can find of modifying this upvalue are with the C api (another example from C api), but I am trying to do this from within Lua. Is this possible?
Edit: I'm unsure of accepting answers using the debug library. The docs state that the functions may be slow. I'm doing this for efficiency so that entire chunks don't have to be parsed from strings (or a file, even worse) just to inject variable definitions into various environments.
Edit: Looks like this is impossible: Recreating setfenv() in Lua 5.2
Edit: I suppose the best way for me to do this is to bind a C function that can modify the environment. Though this is a much more annoying way of going about it.
Edit: I believe a more natural way to do this would be to load all chunks into separate environments. These can be "inherited" by any other environment by setting a metatable that refers to a global copy of a chunk. This does not require any upvalue modification post-load, but still allows for multiple environments with those function definitions.
The simplest way to allow a chunk to be run in different environments is to make this explicit and have it receive an environment. Adding this line at the top of the chunk achieves this:
_ENV=...
Now you can call chunk(env1) and later chunk(env2) at your pleasure.
There, no debug magic with upvalues.
Although it will be clear if your chunk contains that line, you can add it at load time, by writing a suitable reader function that first sends that line and then the contents of the file.
I do not understand why you want to avoid using the debug library, while you are happy to use a C function (neither is possible in a sandbox.)
It can be done using debug.upvaluejoin:
function newEnvForChunk(chunk, index)
local newEnv = {}
local function source() return newEnv end
debug.upvaluejoin(chunk, 1, source, 1)
if index then setmetatable(newEnv, {__index=index}) end
return newEnv
end
Now load any chunk like this:
local myChunk = load "print(x)"
It will initially inherit the enclosing _ENV. Now give it a new one:
local newEnv = newEnvForChunk(myChunk, _ENV)
and insert a value for 'x':
newEnv.x = 99
Now when you run the chunk, it should see the value for x:
myChunk()
=> 99
If you don't want to modify your chunk (per LHF's great answer) here are two alternatives:
Set up a blank environment, then dynamically change its environment to yours
function compile(code)
local meta = {}
local env = setmetatable({},meta)
return {meta=meta, f=load('return '..code, nil, nil, env)}
end
function eval(block, scope)
block.meta.__index=scope
return block.f()
end
local block = compile('a + b * c')
print(eval(block, {a=1, b=2, c=3})) --> 7
print(eval(block, {a=2, b=3, c=4})) --> 14
Set up a blank environment, and re-set its values with your own each time
function compile(code)
local env = {}
return {env=env, f=load('return '..code, nil, nil, env)}
end
function eval(block, scope)
for k,_ in pairs(block.env) do block.env[k]=nil end
for k,v in pairs(scope) do block.env[k]=v end
return block.f()
end
local block = compile('a + b * c')
print(eval(block, {a=1, b=2, c=3})) --> 7
print(eval(block, {a=2, b=3, c=4})) --> 14
Note that if micro-optimizations matter, the first option is about 2✕ as slow as the _ENV=... answer, while the second options is about 8–9✕ as slow.