• I have some strange LUA errors
    14 replies, posted
Hello everyone, I'm trying to do something with LUA but i have a dilema: I have codded some LUA stuff but if only the server execute it, when launching the server have this error: [CODE][ERROR] lua/includes/util.lua:171: attempt to index a string value with bad key ('IsValid' is not part of the string library) 1. error - [C]:-1 2. __index - lua/includes/extensions/string.lua:310 3. IsValid - lua/includes/util.lua:171 4. unknown - gamemodes/base/gamemode/shared.lua:295[/CODE] else if client execute it, I have this error: [CODE] [ERROR] lua/includes/util.lua:171: attempt to index a string value with bad key ('IsValid' is not part of the string library) 1. error - [C]:-1 2. __index - lua/includes/extensions/string.lua:310 3. IsValid - lua/includes/util.lua:171 4. GetPlayerColor - gamemodes/base/entities/entities/gmod_hands.lua:43 5. bind - lua/matproxy/player_color.lua:28 6. unknown - lua/includes/modules/matproxy.lua:56 [/CODE] Problem is that i really don't have information where my error comes from :/ (when i remove the doors.lua file, I have no more errors so it is surely this file) Here is the code: [CODE]local meta = FindMetaTable("Entity") function door(ply) local trace = ply:GetEyeTrace().Entity return trace end function meta:IsOwnable() return true end function meta:SetOwner(duration,owner) if meta:IsOwnable() then self:SetNWInt("time" , duration) self:SetNWString("owner" , owner) end end function meta:GetTimer() if meta:IsOwnable() then return self:GetNWInt("time") end end function meta:SetBank(Owner) if meta:IsOwnable() then self:SetNWString("owner","Bank") end end function meta:GetOwner() if meta:IsOwnable() then return self:GetNWString("owner","Bank") else return "Not ownable" end end function meta:DecrTimer(val) if meta:IsOwnable() then self:SetNWInt("time",meta:GetTimer() - val) end if meta:GetTimer() < 0 then self:SetOwner("Bank") end end --[[function meta:Owned() if meta:IsOwnable() and meta:GetOwner() ~= "Bank" then true else false end end --]] --[[function tick() for k,v in pairs(Entity.GetAll()) do if v:GetOwner() != "Bank" then DecrTimer(1) end end end]]-- function own_Door( ply,cmd,args,str ) val = tonumber(str) if not val or val < 0 then ply:ChatPrint("Error with time") else door(ply):SetOwner(val,ply:GetPlayerInfo()["guid"]) ply:ChatPrint("You successfully owned a door") end end function get_owner(ply) ply:ChatPrint(door(ply):GetOwner()) end concommand.Add("own",own_Door) concommand.Add("owner",get_owner)[/CODE] if some generous guy could help me, it would be so great! (And sorry for my english, it isn't my native language)
On the server, line 295 of the base gamemode shared file (as described in your error), is OnViewModelChanged. Both offending lines are IsValid(ply), where ply is either a viewmodel owner or weapon owner, so somehow you're setting the owner of the weapon and viewmodel to a string instead of a player. [B]Why:[/B] You're overriding the entire entity metatable to add new functions to every single entity. This isn't completely a bad thing, but you have to be [I]very[/I] careful to not override any functions that [I]already exist[/I] on any other entities. So when you did function meta:SetOwner, you removed the code on clientside/serverside entities that sets the owner of weapons (the person carrying them), replacing those default functions with incompatible code. [B]Solution:[/B] Put all of your meta table overrides in a table. local meta = FindMetaTable("Entity") meta.MyModNameKaostic = {} local metasafe = meta.MyModNameKaostic and then instead of "function meta:DecrTimer(val)" you do "function metasafe:DecrTimer(val)", and if you need to reference your custom functions outside of this file you can do ent.MyModNameKaostic:DecrTimer() [B]For the same reason[/B] (not overriding other peoples code with incompatible code) you should localize any functions and variables that you only use within the file you're coding them in. If you won't need "own_Door" anywhere but in this single code file, put the word local before the word function so that it won't exist outside this file and won't override anything beyond this file. If you DO want that function in other files, make yourself a global table to hold them in with a unique name. [I]MyModNameKaostic = {} function MyModNameKaostic.own_Door()[/I] or [I]local function own_Door()[/I]
[QUOTE=bitches;48231131]and then instead of "function meta:DecrTimer(val)" you do "function metasafe:DecrTimer(val)", and if you need to reference your custom functions outside of this file you can do ent.MyModNameKaostic:DecrTimer()[/QUOTE] No. doing A.B:C() will pass B as "self" to C(), and not A as you'd want here. Proper way is A.B.C(A) or just use prefixes like ent:MyCrap_SetOwner()
Thanks a lots! I should have think of this problem :/ I will now use mymod_function() for all my function (the meta.mymod is an elegant way to deal with it, but I still have problem difficult to resolve with this) I still have a little issue with self:GetClass(), I can't manage to use it for my IsOwnable() function Im having this error: [CODE][ERROR] gamemodes/cnr/gamemode/cnr/door.lua:9: Tried to use a NULL entity! 1. GetClass - [C]:-1 2. cnr_IsOwnable - gamemodes/cnr/gamemode/cnr/door.lua:9 3. cnr_GetOwner - gamemodes/cnr/gamemode/cnr/door.lua:38 4. unknown - gamemodes/cnr/gamemode/cnr/door.lua:85 5. unknown - lua/includes/modules/concommand.lua:54 [/CODE] the code is this : [CODE] function meta:cnr_IsOwnable() local class = self:GetClass() if (class == "func_door" or class == "func_door_rotating" or class == "prop_door_rotating") then return true else return false end end[/CODE] According to [url]http://wiki.garrysmod.com/page/Entity/GetClass[/url] I don't see why it doesn't work =P and (I know it is not a reference) DarkRP use the same function exactly like I do :/ thanks for your futur help!
Try replacing the [I]local class = self:GetClass()[/I] with [lua]local class = "" --setting it to an empty string using two quotes, and doing this local variable creation outside of the 'if then else' statement below so that it can be used outside of that statement if self != NULL && IsValid(self) && self.GetClass then class = self:GetClass() end --self.GetClass refers to a variable representing the function on the entity, so this checks if it exists before we try to call it[/lua] just some error prevention, most importantly checking that the entity "exists" because gmod is weird that way
Thanks man, but it still not working, the self is always a NULL [CODE] function meta:cnr_IsOwnable() local class = "not working" --setting it to an empty string using two quotes, and doing this local variable creation outside of the 'if then else' statement below so that it can be used outside of that statement if self != NULL && IsValid(self) && self.GetClass then class = self:GetClass() end --self.GetClass refer s to a variable representing the function on the entity, so this checks if it exists before we try to call it if (class == "func_door" or class == "func_door_rotating" or class == "prop_door_rotating") then print(class) return true else print(class) return false end end [/CODE] and it always output not working :/
[QUOTE=Kaos-tic;48237889]Thanks man, but it still not working, the self is always a NULL [CODE] function meta:cnr_IsOwnable() local class = "not working" --setting it to an empty string using two quotes, and doing this local variable creation outside of the 'if then else' statement below so that it can be used outside of that statement if self != NULL && IsValid(self) && self.GetClass then class = self:GetClass() end --self.GetClass refer s to a variable representing the function on the entity, so this checks if it exists before we try to call it if (class == "func_door" or class == "func_door_rotating" or class == "prop_door_rotating") then print(class) return true else print(class) return false end end [/CODE] and it always output not working :/[/QUOTE] IsValid already checks for NULL., so you dont need this bit: "self != NULL &&". As for the error, you are probably calling the function incorrectly. You must call it like this: my_entity[b]:[/b]cnr_IsOwnable() NOT LIKE THIS: my_entity[b].[/b]cnr_IsOwnable()
add this: print(self==NULL) print(type(self)) print(self.GetClass) print(self.IsValid) what's the output?
I found my mistake, I was calling meta:cnr_IsOwnable, but i should call self:cnr_IsOwnable so i got another question: the big difference between meta and self? Because I understand that meta is a table, and self is the entity, but why and when do we need to use meta instead of self?
[QUOTE=Kaos-tic;48237992]I found my mistake, I was calling meta:cnr_IsOwnable, but i should call self:cnr_IsOwnable so i got another question: the big difference between meta and self? Because I understand that meta is a table, and self is the entity, but why and when do we need to use meta instead of self?[/QUOTE] You only use meta to add new methods/functions to all entities/players/etc. You use self for everything else. [QUOTE=bitches;48237978]add this: print(self==NULL) print(type(self)) print(self.GetClass) print(self.IsValid) what's the output?[/QUOTE] Entity.IsValid returns false if Entity is NULL.
[QUOTE=Robotboy655;48238011] Entity.IsValid returns false if Entity is NULL.[/QUOTE] he's doing overrides so you can't rule anything out [editline]18th July 2015[/editline] [QUOTE=Kaos-tic;48237992]I found my mistake, I was calling meta:cnr_IsOwnable, but i should call self:cnr_IsOwnable so i got another question: the big difference between meta and self? Because I understand that meta is a table, and self is the entity, but why and when do we need to use meta instead of self?[/QUOTE] the meta table is just a big table of default data that every new entity created will inherit a copy of anything in the meta is applied to entities upon their creation as a part of them so 'self' in a function in the metatable refers to the metatable literally, but is intended for use with the entity the function is later applied to edit the metatable to set some functions for all entities to have run your new functions on the entities themselves you don't "use meta instead of self"
Thanks for all your interresting and usefull answer! (love this forum for this and no: U NOOB GO LEARN), i'm still new, but now I understand more thing in LUA :) One last (no i'm joking, I have thousands of questions) but i need to make the timer of the doors decreasing each minutes (or hours or when I want in fact) but i'm trying with the tick() hook, but i can't make it I have try something like this: [CODE] function minute() tim = (RealTime() *66 /60) % 60 if flag == 0 then flag = 1 if tim == 0 then -- do my stuff end print (math.floor(tostring(tim))) else flag = 0 end end hook.Add( "Tick", "cnr_tick", minute )[/CODE] but it has 2 problems: -it does run every tick instead of 1 each second (flag part) (I get more than 50 times the tim variable printed) -it doesn't run when no one is online as I can get time, executing this function 1 times per hour is sufficient/needed, but 1 time per tick make the server lag/ram horribly and I can't manage to find another hook that may be used for it :/
You could use timer.Create() and make the function activate every so seconds
Do you mean you want something to happen upon the stroke of each hour, or at a regular interval of something like "every five minutes". In either case, there's no reason to worry about making it happen when players are online. [code] local HasAnnouncedHour = false timer.Create("MyUniqueTimerName",5,0,function() local minute = tonumber(os.date("%M",os.time())) if minute == 0 then if !HasAnnouncedHour then --if hasannouncedhour is false; the ! symbol inverts the true/false print("OMG IT IS A NEW HOUR NOW") HasAnnouncedHour = true end else HasAnnouncedHour = false end end) [/code] This will print an announcement hourly, on the hour, so long as the server's clock is correctly set to the minute. The HasAnnouncedHour stuff ensures that it only announces it once. This script checks every five seconds. [editline]18th July 2015[/editline] To do something simply every five minutes, just replace the timer function with only the print test or whatever else you want to happen, and change the 5 seconds to [I]60*5[/I]
Thanks man, now I understand a little more of all of this!
Sorry, you need to Log In to post a reply to this thread.