• Command That Sets A Variable For A Timer
    24 replies, posted
I have no idea where to start for this. I have several timers and I want them to be user/admin definable by a console command. Im thinking it would be something like this in console. Stage2.set "30" Running this command [B]would change this[/B] timer.Create("Stage2_"..self:EntIndex(), 10, 1, function() [B]to this[/B] timer.Create("Stage2_"..self:EntIndex(), 30, 1, function() I do not know where and what to put. Help would be appreciated for this newbie! EDIT:: It seems timer.Adjust will be involved but I am unsure how to call what the user/admin defines. If he says Stage2.set "40" How do I timer.Adjust {what the user defined}
Why are you using a string to send the number in a console command.
[QUOTE=RTM xBEASTx;29083997]Why are you using a string to send the number in a console command.[/QUOTE] The timer.create is in an entity if thats what your referring to. Everything else was just speculation on my part.
Should this console command alter Stage2_* timers already running, or just change the delay on ones that are created in the future? I think the latter should be very easy. On the server, define a global variable called Stage2Delay and create a console command stage2_delay which sets the global variable. Then in your entity you just need to change your timer.Create to use Stage2Delay rather than just 10 or 30 or whatever.
[QUOTE=MegaJohnny;29085754]Should this console command alter Stage2_* timers already running, or just change the delay on ones that are created in the future? I think the latter should be very easy. On the server, define a global variable called Stage2Delay and create a console command stage2_delay which sets the global variable. Then in your entity you just need to change your timer.Create to use Stage2Delay rather than just 10 or 30 or whatever.[/QUOTE] I'm wanting it to alter the delay of them spawned in the future. I'm quite nooby and only understood that in theory. How/where do I define global variables and for the concommand [B]concommand.Add( "stage2_delay", "function" )[/B] But how do I define the timer as a function? [B]function stage2_delay() timer.create ............ end[/B] Is that right?
I'll explain in a bit more detail. You'll need a file in lua/autorun/server to create the console command and the variable. It needs to be a global variable so that the entity can see the variable in its own code. Variables you make are global by default, so in your autorun file you only need this: [lua]Stage2Delay = 10[/lua] To create the console command, define a function with whatever code should be run when someone runs the command. Then use concommand.Add to tell it to run that function. In the autorun file you will need something like this: [lua] local function setStage2Delay(ply, cmd, args) if args[1] and tonumber(args[1]) then Stage2Delay = tonumber(args[1]) end end concommand.Add("stage2_delay", setStage2Delay) [/lua] Args is an array of the arguments the player passed to the console command. In this case we are only interested in the first one. I have an if statement there to make sure the first argument exists and that it is a valid number (it is sent as a sequence of digit characters so we need to use tonumber to convert it into an actual number). Then in your entity's code, you only need to change [lua] --this: timer.Create("Stage2_"..self:EntIndex(), 10, 1, function() --to this: timer.Create("Stage2_"..self:EntIndex(), Stage2Delay, 1, function() [/lua]
[b][url=http://wiki.garrysmod.com/?title=Timer.IsTimer]Timer.IsTimer [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] [b][url=http://wiki.garrysmod.com/?title=Timer.Create]Timer.Create [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] [b][url=http://wiki.garrysmod.com/?title=Timer.Adjust]Timer.Adjust [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]
[QUOTE=MegaJohnny;29087066]I'll explain in a bit more detail. You'll need a file in lua/autorun/server to create the console command and the variable. It needs to be a global variable so that the entity can see the variable in its own code. Variables you make are global by default, so in your autorun file you only need this: [lua]Stage2Delay = 10[/lua] To create the console command, define a function with whatever code should be run when someone runs the command. Then use concommand.Add to tell it to run that function. In the autorun file you will need something like this: [lua] local function setStage2Delay(ply, cmd, args) if args[1] and tonumber(args[1]) then Stage2Delay = tonumber(args[1]) end end concommand.Add("stage2_delay", setStage2Delay) [/lua] Args is an array of the arguments the player passed to the console command. In this case we are only interested in the first one. I have an if statement there to make sure the first argument exists and that it is a valid number (it is sent as a sequence of digit characters so we need to use tonumber to convert it into an actual number). Then in your entity's code, you only need to change [lua] --this: timer.Create("Stage2_"..self:EntIndex(), 10, 1, function() --to this: timer.Create("Stage2_"..self:EntIndex(), Stage2Delay, 1, function() [/lua][/QUOTE] Did all that, command shows up and is recognized, doesnt come up as unknown command. But timer doesnt seem to affect it, it stays at the default 10 seconds. [B]Timer Error: [entities\timer\init.lua:117] attempt to index field 'Entity' (a nil value)[/B] That line = self.Entity:SetModel("mymodel.mdl") Random model error that randomly popped up or? I've put Stage2Delay = 10 and the local function setStage2Delay in the same file in the autorun/server folder btw.
They don't strictly have to be in the same file, but you might as well, to make it easier to organise. If the delay isn't being changed by the command, it might be because the condition on the if statement is returning false, so the code inside it doesn't get run. Try adding a print("If statement says yes") inside the if block. As for the model error, using self.Entity is deprecated unless I'm mistaken. See what happens when you change it to just self:SetModel(...
[QUOTE=MegaJohnny;29106347]They don't strictly have to be in the same file, but you might as well, to make it easier to organise. If the delay isn't being changed by the command, it might be because the condition on the if statement is returning false, so the code inside it doesn't get run. Try adding a print("If statement says yes") inside the if block. As for the model error, using self.Entity is deprecated unless I'm mistaken. See what happens when you change it to just self:SetModel(...[/QUOTE] Print prints. Okay i believe it is partially working now. I will need to run some other tests. SUCCESS. I now have 7 changeable timers!!! The only problem is if the entity is destroyed before the timers are over I get this. [B]Timer Error: [@gamemodes\darkrp\entities\entities\weed_plant\init.lua:93] Tried to use a NULL entity![/B] Tried this: function ENT:OnRemove() timer.Destroy("Stage2") etc etc That doesnt work, dont wont to delete the functions as after the entity is destroyed it should be able to be spawned again and used.
[QUOTE=Proost;29106468]Print prints. Okay i believe it is partially working now. I will need to run some other tests. SUCCESS. I now have 7 changeable timers!!! The only problem is if the entity is destroyed before the timers are over I get this. [B]Timer Error: [@gamemodes\darkrp\entities\entities\weed_plant\init.lua:93] Tried to use a NULL entity![/B] Tried this: function ENT:OnRemove() timer.Destroy("Stage2") etc etc That doesnt work, dont wont to delete the functions as after the entity is destroyed it should be able to be spawned again and used.[/QUOTE] Problem is that the entity is NULL. [img]http://3.bp.blogspot.com/_Uc2suQSWMX4/TBZJVg2soKI/AAAAAAAACU8/-BG9D-LAcSQ/s1600/captain_obvious.jpg[/img]
[QUOTE=Freze;29109041]Problem is that the entity is NULL. [img_thumb]http://3.bp.blogspot.com/_Uc2suQSWMX4/TBZJVg2soKI/AAAAAAAACU8/-BG9D-LAcSQ/s1600/captain_obvious.jpg[/img_thumb][/QUOTE] Obviously, Mr Captain Sir Obvious Obvious Obvious. But how do I remove the timers on ENT:Remove timer.Destroy("Stage2") does not work.
You could just make your functions return if ValidEntity(self) returns false.
[QUOTE=MegaJohnny;29117204]You could just make your functions return if ValidEntity(self) returns false.[/QUOTE] Is this what you meant? This doesnt work :/ [code]timer.Create("Stage2_"..self:EntIndex(), Stage2Delay, 1, function() if ValidEntity(self) == false then return end self.Entity:SetModel("clock2.mdl") end) [/code]
Looks fine to me. How is it not working? Does the null entity error still appear?
[QUOTE=Proost;29116731]Obviously, Mr Captain Sir Obvious Obvious Obvious. But how do I remove the timers on ENT:Remove timer.Destroy("Stage2") does not work.[/QUOTE] timer.Destroy("Stage2")? Wasn't it timer.Destroy("Stage2" .. self:EntIndex()) you used?
I'm fairly sure what you're doing here is creating a bunch of timers in a scripted entity, for each ent. You really shouldn't do that, when ents have a built in function for timers, [b][url=wiki.garrysmod.com/?title=ENT.Think]ENT.Think [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]. Here, try something like this? (Won't work straight away but you can adapt it) [lua]local stagetimes = { 5, 10, 15 } local modelstages = { "clock1.mdl", "clock2.mdl", "clock3.mdl", "clock_final.mdl" } local MAXSTAGE = 4; ENT.StageTime = 0; function ENT:Initialize() self.dt.stage = 0; self:StageUp(); end function ENT:StageUp() self.dt.stage = self.dt.stage + 1; self.StageTime = CurTime(); self:SetModel(modelstages[self.dt.stage]); end function ENT:Think() if (self.dt.stage == MAXSTAGE) then return; elseif (self.StageTime + stagetimes[self.dt.stage] > CurTime()) then self:StageUp(); end end concommand.Add("setstagetime", function(ply, _, args) if (not ply:IsAdmin()) then ply:ChatPrint("You do not have access to this!"); return; end local stage, time = tonumber(args[1]), tonumber(args[2]); if (not stage or stage < 1 or stage >= MAXSTAGE) then ply:ChatPrint("Invalid stage specified!"); return; elseif (not time or time < 1) then ply:ChatPrint("Invalid time specified!"); return; end stage = math.floor(stage); stagetimes[stage] = time; end);[/lua]
[QUOTE=Freze;29131523]timer.Destroy("Stage2")? Wasn't it timer.Destroy("Stage2" .. self:EntIndex()) you used?[/QUOTE] Neither of those timer.destroys work :/ I now have this random other error. [B][entities\entities\clock\init.lua:67] bad argument #2 to '?' (Vector expected, got number)[/B] Line 67 = local SpawnPos = self.Entity:GetPos() I didnt even edit near that line? [QUOTE=Lexic;29135961]I'm fairly sure what you're doing here is creating a bunch of timers in a scripted entity, for each ent. You really shouldn't do that, when ents have a built in function for timers, [b][url=wiki.garrysmod.com/?title=ENT.Think]ENT.Think [img_thumb]http://wiki.garrysmod.com/favicon.ico[/img_thumb][/url][/b]. Here, try something like this? (Won't work straight away but you can adapt it) [lua]local stagetimes = { 5, 10, 15 } local modelstages = { "clock1.mdl", "clock2.mdl", "clock3.mdl", "clock_final.mdl" } local MAXSTAGE = 4; ENT.StageTime = 0; function ENT:Initialize() self.dt.stage = 0; self:StageUp(); end function ENT:StageUp() self.dt.stage = self.dt.stage + 1; self.StageTime = CurTime(); self:SetModel(modelstages[self.dt.stage]); end function ENT:Think() if (self.dt.stage == MAXSTAGE) then return; elseif (self.StageTime + stagetimes[self.dt.stage] > CurTime()) then self:StageUp(); end end concommand.Add("setstagetime", function(ply, _, args) if (not ply:IsAdmin()) then ply:ChatPrint("You do not have access to this!"); return; end local stage, time = tonumber(args[1]), tonumber(args[2]); if (not stage or stage < 1 or stage >= MAXSTAGE) then ply:ChatPrint("Invalid stage specified!"); return; elseif (not time or time < 1) then ply:ChatPrint("Invalid time specified!"); return; end stage = math.floor(stage); stagetimes[stage] = time; end);[/lua][/QUOTE] I've made 8 different stages manually because I am using a derma menu aswell and have already coded that. Plus im just grasping this whole concept and yours doesnt make any sense to me as of yet :/
[QUOTE=Proost;29140118]I've made 8 different stages manually because I am using a derma menu aswell and have already coded that. Plus im just grasping this whole concept and yours doesnt make any sense to me as of yet :/[/QUOTE] Would comments help? Here. [lua]local stagetimes = { -- This table defines how long each stage will take. 5, -- The first stage takes 5 seconds 10, -- The second stage takes 10 seconds 15 -- The third stage takes 15 seconds } -- Add and change values as appropriate. local modelstages = { -- This table defines the models the entity should use for each stage "clock1.mdl", -- Stage one is clock1.mdl "clock2.mdl", -- And so on "clock3.mdl", "clock_final.mdl" -- This is the last model, for when the entity has completed all stages and won't level up any more } -- Again, add and change as appropriate. local MAXSTAGE = #modelstages; -- This is just a quick reference as to what stage number is the last -- This isn't strictly necessary but I like to define my entity's variables beforehand ENT.Stage = 0; -- They are set to 0 to indicate that they are uninitialized. ENT.StageTime = 0; -- Initilization hook. Simply add the contents to your hook. function ENT:Initialize() self:StageUp(); -- This makes the entity go up a stage. Since it's currently stage 0, this puts it to stage 1, the first stage. end -- This function contains everything that must be done every time the entity goes up a stage. function ENT:StageUp() self.Stage = self.Stage + 1; -- Increase the stage by 1 self.StageTime = CurTime(); -- Note that the last time it went up a stage was right now self:SetModel(modelstages[self.Stage]); -- Change the model to the correct one for this stage. -- You probably have something else that should be done here, if so, add it in. end -- This function controls the timer. function ENT:Think() if (self.Stage == MAXSTAGE) then -- If the entity is at the maximum stage return; -- Then nothing more needs to be done. elseif (self.StageTime + stagetimes[self.Stage] < CurTime()) then -- This checks if the time when the last stage happened, plus the time the current stage takes is in the past. -- That may sound a little abstract, but the added complexity means that if the stage length is changed using -- the console command, the changes will affect all running timers. -- So, if the entity is on stage 2, and 7 seconds have passed, and you change stage 2's length to 5, it will -- instantly go up to stage 3, since 5 < 7. However, if you were to change to to 15, it would stay the same, -- as 15 > 7, just like 10 > 7. This also allows just one timer to be used for each entity, which will be auto -- removed when the entity is removed. Neat. self:StageUp(); -- It's time for a stage up end end -- This lets you set the stage time -- `setstagetime 2 10` would set the time of stage 2 to 10 seconds. concommand.Add("setstagetime", function(ply, _, args) if (not ply:IsAdmin()) then -- Check if they're an admin first ply:ChatPrint("You do not have access to this!"); return; end -- Get the stage they want to set local stage, time = tonumber(args[1]), tonumber(args[2]); -- Make sure that they've given us a valid stage if (not stage or stage < 1 or stage >= MAXSTAGE) then ply:ChatPrint("Invalid stage specified!"); return; -- Make sure they've given us a valid time elseif (not time or time < 1) then ply:ChatPrint("Invalid time specified!"); end -- Make sure the stage isn't something like 2.3 stage = math.floor(stage); -- Change the stage time. stagetimes[stage] = time; end);[/lua] There are very few times when you should use timers in a scripted entity, and this is not one of them. Hope that helps :smile:
[QUOTE=Lexic;29144509]Would comments help? Here. [lua]local stagetimes = { -- This table defines how long each stage will take. 5, -- The first stage takes 5 seconds 10, -- The second stage takes 10 seconds 15 -- The third stage takes 15 seconds } -- Add and change values as appropriate. local modelstages = { -- This table defines the models the entity should use for each stage "clock1.mdl", -- Stage one is clock1.mdl "clock2.mdl", -- And so on "clock3.mdl", "clock_final.mdl" -- This is the last model, for when the entity has completed all stages and won't level up any more } -- Again, add and change as appropriate. local MAXSTAGE = #modelstages; -- This is just a quick reference as to what stage number is the last -- This isn't strictly necessary but I like to define my entity's variables beforehand ENT.Stage = 0; -- They are set to 0 to indicate that they are uninitialized. ENT.StageTime = 0; -- Initilization hook. Simply add the contents to your hook. function ENT:Initialize() self:StageUp(); -- This makes the entity go up a stage. Since it's currently stage 0, this puts it to stage 1, the first stage. end -- This function contains everything that must be done every time the entity goes up a stage. function ENT:StageUp() self.Stage = self.Stage + 1; -- Increase the stage by 1 self.StageTime = CurTime(); -- Note that the last time it went up a stage was right now self:SetModel(modelstages[self.Stage]); -- Change the model to the correct one for this stage. -- You probably have something else that should be done here, if so, add it in. end -- This function controls the timer. function ENT:Think() if (self.Stage == MAXSTAGE) then -- If the entity is at the maximum stage return; -- Then nothing more needs to be done. elseif (self.StageTime + stagetimes[self.Stage] < CurTime()) then -- This checks if the time when the last stage happened, plus the time the current stage takes is in the past. -- That may sound a little abstract, but the added complexity means that if the stage length is changed using -- the console command, the changes will affect all running timers. -- So, if the entity is on stage 2, and 7 seconds have passed, and you change stage 2's length to 5, it will -- instantly go up to stage 3, since 5 < 7. However, if you were to change to to 15, it would stay the same, -- as 15 > 7, just like 10 > 7. This also allows just one timer to be used for each entity, which will be auto -- removed when the entity is removed. Neat. self:StageUp(); -- It's time for a stage up end end -- This lets you set the stage time -- `setstagetime 2 10` would set the time of stage 2 to 10 seconds. concommand.Add("setstagetime", function(ply, _, args) if (not ply:IsAdmin()) then -- Check if they're an admin first ply:ChatPrint("You do not have access to this!"); return; end -- Get the stage they want to set local stage, time = tonumber(args[1]), tonumber(args[2]); -- Make sure that they've given us a valid stage if (not stage or stage < 1 or stage >= MAXSTAGE) then ply:ChatPrint("Invalid stage specified!"); return; -- Make sure they've given us a valid time elseif (not time or time < 1) then ply:ChatPrint("Invalid time specified!"); end -- Make sure the stage isn't something like 2.3 stage = math.floor(stage); -- Change the stage time. stagetimes[stage] = time; end);[/lua] There are very few times when you should use timers in a scripted entity, and this is not one of them. Hope that helps :smile:[/QUOTE] That helps immensly. I mingled it with my code and it works except for 1 error -.- [B][entities\entities\clock\init.lua:83][/B] attempt to perform arithmetic on field '?' (a nil value) Line 83 = [B]elseif (self.StageTime + stagetimes[self.Stage] < CurTime()) then[/B] I believe this is because I dont wish to start the stages when the entity is initialized. I have another function ENT:Touch and that starts the stage process. How would I get on ent:Initialize() STOP ENT:Think and on ENT:Touch to START ENT:Think? Other than that all the timers work!
Ooh, interestingly tricky. Let me have a think about it. You must have a first stage that is set during initialization though.
[QUOTE=Lexic;29145584]Ooh, interestingly tricky. Let me have a think about it. You must have a first stage that is set during initialization though.[/QUOTE] Ah that might be the problem aswell. ENT:StageUp() in initialize. Do I need to set a model for the entity aswell or is it uneeded on initialize as the ENT:StageUp() function does that. What If I did: [lua]local stagetimes = { -- This table defines how long each stage will take. 0, -- Does not progress to the next stage until ENT:StageUp is run? 10, -- The second stage takes 10 seconds 15 -- The third stage takes 15 seconds }[/lua] Except that adds an extra stage, and a console command.
[lua]local stagetimes = { -- This table defines how long each stage will take. 5, -- The first stage takes 5 seconds 10, -- The second stage takes 10 seconds 15 -- The third stage takes 15 seconds } -- Add and change values as appropriate. local modelstages = { -- This table defines the models the entity should use for each stage "clock1.mdl", -- Stage one is clock1.mdl "clock2.mdl", -- And so on "clock3.mdl", "clock_final.mdl" -- This is the last model, for when the entity has completed all stages and won't level up any more } -- Again, add and change as appropriate. local MAXSTAGE = #modelstages; -- This is just a quick reference as to what stage number is the last -- This isn't strictly necessary but I like to define my entity's variables beforehand ENT.Stage = 0; -- They are set to 0 to indicate that they are uninitialized. ENT.StageTime = 0; -- Initilization hook. Simply add the contents to your hook. function ENT:Initialize() self:StageUp(); -- This makes the entity go up a stage. Since it's currently stage 0, this puts it to stage 1, the first stage. end -- This function contains everything that must be done every time the entity goes up a stage. function ENT:StageUp() self.Stage = self.Stage + 1; -- Increase the stage by 1 self.StageTime = 0; -- Reset the amount of time it has been on this stage self:SetModel(modelstages[self.Stage]); -- Change the model to the correct one for this stage. -- You probably have something else that should be done here, if so, add it in. end ENT.BeingTouched = false; function ENT:BeginTouch(...) -- Do whatever it is you do self.BeingTouched = true; end function ENT:EndTouch(...) -- Again self.BeingTouched = false; end -- This function controls the timer. function ENT:Think() if (not self.BeingTouched) then -- We do not level up without touchy touchy return; -- So begone elseif (self.Stage == MAXSTAGE) then -- If the entity is at the maximum stage return; -- Then nothing more needs to be done. end self.StageTime = self.StageTime + FrameTime(); -- Add the time since the last think to the time. -- NOTE: This will not add the time since the last add, but the time since the last Think. It is a very small number. elseif (self.StageTime > stagetimes[self.Stage]) then -- OK! Rather different this time. -- ENT:Think() is run about 60 times a second. (Sometimes more, sometimes less, but ignore that for now) -- Every time it's run while being touched, 1/60 is added to self.StageTime. When that number is greater -- than the time it takes to do a stage, ie 5, it has been touched for 5 seconds, though not necessarily -- continuously. Again, this will react appropriately (And after 1/60th of a second) to stage changes. -- As I said, it doesn't matter how often it thinks, if it thinks 10 times a second or 100, -- after a second StageTime will have gone up by 1, because we're adding 1/fps each time, and it balances. self:StageUp(); -- It's time for a stage up end end -- This lets you set the stage time -- `setstagetime 2 10` would set the time of stage 2 to 10 seconds. concommand.Add("setstagetime", function(ply, _, args) if (not ply:IsAdmin()) then -- Check if they're an admin first ply:ChatPrint("You do not have access to this!"); return; end -- Get the stage they want to set local stage, time = tonumber(args[1]), tonumber(args[2]); -- Make sure that they've given us a valid stage if (not stage or stage < 1 or stage >= MAXSTAGE) then ply:ChatPrint("Invalid stage specified!"); return; -- Make sure they've given us a valid time elseif (not time or time < 1) then ply:ChatPrint("Invalid time specified!"); end -- Make sure the stage isn't something like 2.3 stage = math.floor(stage); -- Change the stage time. stagetimes[stage] = time; end);[/lua] Et viola. It will only count time while being touched for stage gains. You do not need to set a model in Initialize, or create a fake stage. It will start at level one and progress up to level 8 while being poked.
[QUOTE=Lexic;29145670][lua]local stagetimes = { -- This table defines how long each stage will take. 5, -- The first stage takes 5 seconds 10, -- The second stage takes 10 seconds 15 -- The third stage takes 15 seconds } -- Add and change values as appropriate. local modelstages = { -- This table defines the models the entity should use for each stage "clock1.mdl", -- Stage one is clock1.mdl "clock2.mdl", -- And so on "clock3.mdl", "clock_final.mdl" -- This is the last model, for when the entity has completed all stages and won't level up any more } -- Again, add and change as appropriate. local MAXSTAGE = #modelstages; -- This is just a quick reference as to what stage number is the last -- This isn't strictly necessary but I like to define my entity's variables beforehand ENT.Stage = 0; -- They are set to 0 to indicate that they are uninitialized. ENT.StageTime = 0; -- Initilization hook. Simply add the contents to your hook. function ENT:Initialize() self:StageUp(); -- This makes the entity go up a stage. Since it's currently stage 0, this puts it to stage 1, the first stage. end -- This function contains everything that must be done every time the entity goes up a stage. function ENT:StageUp() self.Stage = self.Stage + 1; -- Increase the stage by 1 self.StageTime = 0; -- Reset the amount of time it has been on this stage self:SetModel(modelstages[self.Stage]); -- Change the model to the correct one for this stage. -- You probably have something else that should be done here, if so, add it in. end ENT.BeingTouched = false; function ENT:BeginTouch(...) -- Do whatever it is you do self.BeingTouched = true; end function ENT:EndTouch(...) -- Again self.BeingTouched = false; end -- This function controls the timer. function ENT:Think() if (not self.BeingTouched) then -- We do not level up without touchy touchy return; -- So begone elseif (self.Stage == MAXSTAGE) then -- If the entity is at the maximum stage return; -- Then nothing more needs to be done. end self.StageTime = self.StageTime + FrameTime(); -- Add the time since the last think to the time. -- NOTE: This will not add the time since the last add, but the time since the last Think. It is a very small number. elseif (self.StageTime > stagetimes[self.Stage]) then -- OK! Rather different this time. -- ENT:Think() is run about 60 times a second. (Sometimes more, sometimes less, but ignore that for now) -- Every time it's run while being touched, 1/60 is added to self.StageTime. When that number is greater -- than the time it takes to do a stage, ie 5, it has been touched for 5 seconds, though not necessarily -- continuously. Again, this will react appropriately (And after 1/60th of a second) to stage changes. -- As I said, it doesn't matter how often it thinks, if it thinks 10 times a second or 100, -- after a second StageTime will have gone up by 1, because we're adding 1/fps each time, and it balances. self:StageUp(); -- It's time for a stage up end end -- This lets you set the stage time -- `setstagetime 2 10` would set the time of stage 2 to 10 seconds. concommand.Add("setstagetime", function(ply, _, args) if (not ply:IsAdmin()) then -- Check if they're an admin first ply:ChatPrint("You do not have access to this!"); return; end -- Get the stage they want to set local stage, time = tonumber(args[1]), tonumber(args[2]); -- Make sure that they've given us a valid stage if (not stage or stage < 1 or stage >= MAXSTAGE) then ply:ChatPrint("Invalid stage specified!"); return; -- Make sure they've given us a valid time elseif (not time or time < 1) then ply:ChatPrint("Invalid time specified!"); end -- Make sure the stage isn't something like 2.3 stage = math.floor(stage); -- Change the stage time. stagetimes[stage] = time; end);[/lua] Et viola. It will only count time while being touched for stage gains. You do not need to set a model in Initialize, or create a fake stage. It will start at level one and progress up to level 8 while being poked.[/QUOTE] Ahh sorry to make you code all that regarding endtouch and misinform you. ENT:Touch runs once and there is no endtouch. But thank you anyway i will test that and edit it. Also my derma slider does not work with the setstage commands. NumSlider2:SetConVar( "setstagetime 1" ) It thinks i am trying to set "setstagetime" to 1. Tried to intergrate that, didnt work, entity wont spawn now. FFFFFUUU-
dun dun dun dun [lua]local stagetimes = { -- This table defines how long each stage will take. 5, -- The first stage takes 5 seconds 10, -- The second stage takes 10 seconds 15 -- The third stage takes 15 seconds } -- Add and change values as appropriate. local modelstages = { -- This table defines the models the entity should use for each stage "clock1.mdl", -- Stage one is clock1.mdl "clock2.mdl", -- And so on "clock3.mdl", "clock_final.mdl" -- This is the last model, for when the entity has completed all stages and won't level up any more } -- Again, add and change as appropriate. local MAXSTAGE = #modelstages; -- This is just a quick reference as to what stage number is the last -- This isn't strictly necessary but I like to define my entity's variables beforehand ENT.Stage = 0; -- They are set to 0 to indicate that they are uninitialized. ENT.StageTime = 0; -- Initilization hook. Simply add the contents to your hook. function ENT:Initialize() self:StageUp(); -- This makes the entity go up a stage. Since it's currently stage 0, this puts it to stage 1, the first stage. end -- This function contains everything that must be done every time the entity goes up a stage. function ENT:StageUp() self.Stage = self.Stage + 1; -- Increase the stage by 1 self.StageTime = 0; -- Disable the stage counter self:SetModel(modelstages[self.Stage]); -- Change the model to the correct one for this stage. -- You probably have something else that should be done here, if so, add it in. end function ENT:Touch(...) -- bla if (self.StageTime == 0) then self.StageTime = CurTime() -- Start the level up end end -- This function controls the timer. function ENT:Think() if (self.StageTime == 0) then -- If the stage timer has yet to be initialized return; -- Wait until the entity is poked elseif (self.Stage == MAXSTAGE) then -- If the entity is at the maximum stage return; -- Then nothing more needs to be done. elseif (self.StageTime + stagetimes[self.Stage] < CurTime()) then -- This checks if the time when the last stage happened, plus the time the current stage takes is in the past. -- That may sound a little abstract, but the added complexity means that if the stage length is changed using -- the console command, the changes will affect all running timers. -- So, if the entity is on stage 2, and 7 seconds have passed, and you change stage 2's length to 5, it will -- instantly go up to stage 3, since 5 < 7. However, if you were to change to to 15, it would stay the same, -- as 15 > 7, just like 10 > 7. This also allows just one timer to be used for each entity, which will be auto -- removed when the entity is removed. Neat. self:StageUp(); -- It's time for a stage up end end -- Creates a concommand for each stage for i = 1, MAXSTAGE do concommand.Add("setstagetime_" .. i, function(ply, _, args) if (not ply:IsAdmin()) then -- Check if they're an admin first ply:ChatPrint("You do not have access to this!"); return; end local time = tonumber(args[1]) if (not time or time < 1) then ply:ChatPrint("Invalid time specified!"); end stagetimes[i] = time; end); end[/lua] :science:
Sorry, you need to Log In to post a reply to this thread.