Stools, how to tell how long it's been since something was done?

Hi, I’m editing Fading Doors for a friend, he needs it so that a fading door can only be toggled, 5 seconds after the last toggle. I tried using timers and that didn’t work, I notice that it doesn’t loop within the code, so does the code get ran, every time something relating to the tool happens? If so how can I carry over a variable to be able to keep using … THANKS!!

The code …

function toggleTrue() --MY CODE
toggleable = true --MY CODE
end --MY CODE

if (CLIENT) then
usermessage.Hook(“FadingDoorHurrah!”, function()
GAMEMODE:AddNotify(“Fading door has been created!”, NOTIFY_GENERIC, 10);
surface.PlaySound (“ambient/water/drip” … math.random(1, 4) … “.wav”);
end);
language.Add( “Tool.fading_doors.name”, “Fading Door” );
language.Add( “Tool.fading_doors.desc”, “Makes an object a Fading Door” );
language.Add( “Tool.fading_doors.0”, “Click on an object to make it a fading door.” );
language.Add( “Undone_fading_door”, “Fading Door Undone” );

function TOOL:BuildCPanel()
	self:AddControl("Header",   {Text = "#Tool.fading_doors.name", Description = "#Tool.fading_doors.desc"});
	self:AddControl("CheckBox", {Label = "Start Faded", Command = "fading_doors_reversed"});
	self:AddControl("Numpad",   {Label = "Button", ButtonSize = "22", Command = "fading_doors_key"});
end

TOOL.LeftClick = checkTrace;

toggleable = true             --MY CODE

return;

end
umsg.PoolString(“FadingDoorHurrah!”);

local function fadeActivate(self)
if (toggleable) then ----------MY CODE
self.fadeActive = true;
self.fadeMaterial = self:GetMaterial();
self:SetMaterial(“sprites/heatwave”)
self:DrawShadow(false)
self:SetNotSolid(true)
–self:SetCollisionGroup(COLLISION_GROUP_WORLD)
local phys = self:GetPhysicsObject();
if (IsValid(phys)) then
self.fadeMoveable = phys:IsMoveable();
phys:EnableMotion(false);
end
if (WireLib) then
Wire_TriggerOutput(self, “FadeActive”, 1);
end
–[[Making a five second delay before any toggles]]-- -------MY CODE
toggleable = false -------MY CODE
timer.Create(“toggleTimer”, 1, 5, toggleTrue) -------MY CODE
else
usermessage.Hook(“FadingDoorHurrah!”, function() --MY CODE
GAMEMODE:AddNotify(“You’re toggling too fast!”, NOTIFY_ERROR, 5); --MY CODE
surface.PlaySound(“sounds/buttons/button11.wav”); --MY CODE
end); --MY CODE
end
end

local function fadeDeactivate(self)
if (toggleable) then ------MY CODE
self.fadeActive = false;
self:SetMaterial(self.fadeMaterial or “”);
self:DrawShadow(true);
self:SetNotSolid(false);
–self:SetCollisionGroup(COLLISION_GROUP_NONE);
local phys = self:GetPhysicsObject();
if (IsValid(phys)) then
phys:EnableMotion(self.fadeMoveable or false);
end
if (WireLib) then
Wire_TriggerOutput(self, “FadeActive”, 0);
end
–[[Making a five second delay before any toggles]]-- -------MY CODE
toggleable = false -------MY CODE
timer.Create(“toggleTimer”, 1, 5, toggleTrue) -------MY CODE
end
end

local function fadeToggleActive(self)
if (self.fadeActive) then
self:fadeDeactivate();
else
self:fadeActivate();
end
end

I only left what I thought may have to do with it so most is cut off, if you need the rest just ask, please help!

EDIT :: BTW, not a lua code, just new to GMOD :slight_smile:

Put the LUA tags to make it easier for people

sorry
fixed

No one has any ideas?

Save the time when something was done to a variable:


TOOL.MyLastTime = 0 -- Somewhere in the beginning of the file, default value
self.MyLastTime = CurTime() -- Somewhere in your TOOL:*() functions

And then subtract TOOL.MyLastTime from CurTime() in the place when you need to get the time since last action:



local delay = CurTime() - self.MyLastTime
print( "It last happened " .. delay .. " secs ago" )
-- You probably want to set the self.MyLastTime here, AFTER subtracting it.


Ohk, I did this

if (os.time() - self.lastTime) >= 5 then
–allow toggle
end

but now it’s saying on that line that ‘lastTime’ is a nil value.

Where I call TOOL.lastTime

TOOL.Category = “Construction”;
TOOL.Name = “#Fading Door”;

TOOL.lastTime = 0
TOOL.ClientConVar[“key”] = “5”
TOOL.ClientConVar[“reversed”] = “0”

Where I set self.lastTime

if (CLIENT) then
usermessage.Hook(“FadingDoorHurrah!”, function()
GAMEMODE:AddNotify(“Fading door has been created!”, NOTIFY_GENERIC, 10);
surface.PlaySound (“ambient/water/drip” … math.random(1, 4) … “.wav”);
end);
language.Add( “Tool.fading_doors.name”, “Fading Door” );
language.Add( “Tool.fading_doors.desc”, “Makes an object a Fading Door” );
language.Add( “Tool.fading_doors.0”, “Click on an object to make it a fading door.” );
language.Add( “Undone_fading_door”, “Fading Door Undone” );

function TOOL:BuildCPanel()
	self:AddControl("Header",   {Text = "#Tool.fading_doors.name", Description = "#Tool.fading_doors.desc"});
	self:AddControl("CheckBox", {Label = "Start Faded", Command = "fading_doors_reversed"});
	self:AddControl("Numpad",   {Label = "Button", ButtonSize = "22", Command = "fading_doors_key"});
end

TOOL.LeftClick = checkTrace;

self.lastTime = os.time()

return;

end

Thanks for the help so far by the way!
Also, tell me if I’m right, but calling something as TOOL.something, and then calling self.something, pretty much is how you make it work for each something individually right?
Thanks again! :slight_smile:

Again, no ideas?

ou use TOOL.lastTime inside the TOOL table.

This is gunna sound terrible but where is the TOOL table, because when I put it in a function labeled TOOL:something it doesn’t work and when I put it at the top where all the other TOOL:something’s are it doesn’t work.

You should learn how metatables work in Lua then.

You can’t access the TOOL table from within itself using the TOOL, you must use self.blahblah inside a TOOL:Function()

I understand metatables a little in lua but not much, can you please just tell me where it should go for now?



--[[ Tool Related Settings ]]--
TOOL.Category = "Construction";
TOOL.Name = "#Fading Door";
TOOL.lastTime = 0
TOOL.ClientConVar["key"] = "5"
TOOL.ClientConVar["reversed"] = "0"

local function checkTrace(tr)
	return (tr.Entity and tr.Entity:IsValid() and not (tr.Entity:IsPlayer() or tr.Entity:IsNPC() or tr.Entity:IsVehicle() or tr.HitWorld));
end

if (CLIENT) then
	usermessage.Hook("FadingDoorHurrah!", function()
		GAMEMODE:AddNotify("Fading door has been created!", NOTIFY_GENERIC, 10);
		surface.PlaySound ("ambient/water/drip" .. math.random(1, 4) .. ".wav");
	end);
	language.Add( "Tool.fading_doors.name", "Fading Door" );
	language.Add( "Tool.fading_doors.desc", "Makes an object a Fading Door" );
	language.Add( "Tool.fading_doors.0", "Click on an object to make it a fading door." );
	language.Add( "Undone_fading_door", "Fading Door Undone" );
	
	function TOOL:BuildCPanel()
		self.lastTime = os.time()
		self:AddControl("Header",   {Text = "#Tool.fading_doors.name", Description = "#Tool.fading_doors.desc"});
		self:AddControl("CheckBox", {Label = "Start Faded", Command = "fading_doors_reversed"});
		self:AddControl("Numpad",   {Label = "Button", ButtonSize = "22", Command = "fading_doors_key"});
	end
	
	
	return;
end	
umsg.PoolString("FadingDoorHurrah!");

local function fadeActivate(self)
	if (os.time() - self.lastTime) >= 5 then
		self.fadeActive = true;
		self.fadeMaterial = self:GetMaterial();
		self:SetMaterial("sprites/heatwave")
		self:DrawShadow(false)
		self:SetNotSolid(true)
		--self:SetCollisionGroup(COLLISION_GROUP_WORLD)
		local phys = self:GetPhysicsObject();
		if (IsValid(phys)) then
			self.fadeMoveable = phys:IsMoveable();
			phys:EnableMotion(false);
		end
		if (WireLib) then
			Wire_TriggerOutput(self,  "FadeActive",  1);
		end
		self.lastTime = os.time()
	else
		usermessage.Hook("Too Fast", function()
		GAMEMODE:AddNotify("You're toggling too fast!", NOTIFY_ERROR, 5);
		surface.PlaySound("sounds/buttons/button11.wav");
		end);
	end
end

local function fadeDeactivate(self)
	if (os.time() - self.lastTime) >= 5 then
		self.fadeActive = false;
		self:SetMaterial(self.fadeMaterial or "");
		self:DrawShadow(true);
		self:SetNotSolid(false);
		--self:SetCollisionGroup(COLLISION_GROUP_NONE);
		local phys = self:GetPhysicsObject();
		if (IsValid(phys)) then
			phys:EnableMotion(self.fadeMoveable or false);
		end
		if (WireLib) then
			Wire_TriggerOutput(self,  "FadeActive",  0);
		end
		self.lastTime = os.time()
	else
		usermessage.Hook("Too Fast", function()
		GAMEMODE:AddNotify("You're toggling too fast!", NOTIFY_ERROR, 5);
		surface.PlaySound("sounds/buttons/button11.wav");
		end);
	end
end

local function fadeToggleActive(self)
	if (self.fadeActive) then
		self:fadeDeactivate();
	else
		self:fadeActivate();
	end
end

local function onUp(ply, ent)
	if (not (ent:IsValid() and ent.fadeToggleActive and not ent.fadeToggle)) then
		return;
	end
	ent:fadeToggleActive();
end
numpad.Register("Fading Doors onUp", onUp);

local function onDown(ply, ent)
	if (not (ent:IsValid() and ent.fadeToggleActive)) then
		return;
	end
	ent:fadeToggleActive();
end
numpad.Register("Fading Doors onDown", onDown);

-- Fuck you wire.
local function getWireInputs(ent)
	local inputs = ent.Inputs;
	local names, types, descs = {}, {}, {};
	if (inputs) then
		local num;
		for _, data in pairs(inputs) do
			num = data.Num;
			names[num] = data.Name;
			types[num] = data.Type;
			descs[num] = data.Desc;
		end
	end
	return names, types, descs;
end
local function doWireInputs(ent)
	local inputs = ent.Inputs;
	if (not inputs) then
		Wire_CreateInputs(ent, {"Fade"});
		return;
	end
	local names, types, descs = {}, {}, {};
	local num;
	for _, data in pairs(inputs) do
		num = data.Num;
		names[num] = data.Name;
		types[num] = data.Type;
		descs[num] = data.Desc;
	end
	table.insert(names, "Fade");
	WireLib.AdjustSpecialInputs(ent, names, types, descs);
end

local function doWireOutputs(ent)
	local outputs = ent.Outputs;
	if (not outputs) then
		Wire_CreateOutputs(ent, {"FadeActive"});
		return;
	end
	local names, types, descs = {}, {}, {};
	local num;
	for _, data in pairs(outputs) do
		num = data.Num;
		names[num] = data.Name;
		types[num] = data.Type;
		descs[num] = data.Desc;
	end
	table.insert(names, "FadeActive");
	WireLib.AdjustSpecialOutputs(ent, names, types, descs);
end

local function TriggerInput(self, name, value, ...)
	if (name == "Fade") then
		if (value == 0) then
			if (self.fadePrevWireOn) then
				self.fadePrevWireOn = false;
				if (not self.fadeToggle) then
					self:fadeToggleActive();
				end
			end
		else
			if (not self.fadePrevWireOn) then
				self.fadePrevWireOn = true;
				self:fadeToggleActive();
			end
		end
	elseif (self.fadeTriggerInput) then
		return self:fadeTriggerInput(name, value, ...);
	end
end

local function PreEntityCopy(self)
	local info = WireLib.BuildDupeInfo(self)
	if (info) then
		duplicator.StoreEntityModifier(self, "WireDupeInfo", info);
	end
	if (self.fadePreEntityCopy) then
		self:fadePreEntityCopy();
	end
end

local function PostEntityPaste(self, ply, ent, ents)
	if (self.EntityMods and self.EntityMods.WireDupeInfo) then
		WireLib.ApplyDupeInfo(ply, self, self.EntityMods.WireDupeInfo, function(id) return ents[id]; end);
	end
	if (self.fadePostEntityPaste) then
		self:fadePostEntityPaste(ply, ent, ents);
	end
end
	

local function onRemove(self)
	numpad.Remove(self.fadeUpNum);
	numpad.Remove(self.fadeDownNum);
end

-- Fer Duplicator
local function dooEet(ply, ent, stuff)
	if (ent.isFadingDoor) then
		ent:fadeDeactivate();
		onRemove(ent)
	else
		ent.isFadingDoor = true;
		ent.fadeActivate = fadeActivate;
		ent.fadeDeactivate = fadeDeactivate;
		ent.fadeToggleActive = fadeToggleActive;
		ent:CallOnRemove("Fading Doors", onRemove);
		if (WireLib) then
			doWireInputs(ent);
			doWireOutputs(ent);
			ent.fadeTriggerInput = ent.fadeTriggerInput or ent.TriggerInput;
			ent.TriggerInput = TriggerInput;
			if (not ent.IsWire) then -- Dupe Support
				ent.fadePreEntityCopy = ent.PreEntityCopy;
				ent.PreEntityCopy = PreEntityCopy;
				ent.fadePostEntityPaste = ent.PostEntityPaste;
				ent.PostEntityPaste = PostEntityPaste;
			end				
		end
	end
	ent.fadeUpNum = numpad.OnUp(ply, stuff.key, "Fading Doors onUp", ent);
	ent.fadeDownNum = numpad.OnDown(ply, stuff.key, "Fading Doors onDown", ent);
	ent.fadeToggle = stuff.toggle;
	if (stuff.reversed) then
		ent:fadeActivate();
	end
	duplicator.StoreEntityModifier(ent, "Fading Door", stuff);
	return true;
end

duplicator.RegisterEntityModifier("Fading Door", dooEet);

if (not FadingDoor) then
	local function legacy(ply, ent, data)
		return dooEet(ply, ent, {
			key      = data.Key;
			toggle   = true;
			reversed = data.Inverse;
		});
	end
	duplicator.RegisterEntityModifier("FadingDoor", legacy);
end

local function doUndo(undoData, ent)
	if (IsValid(ent)) then
		onRemove(ent);
		ent:fadeDeactivate();
		ent.isFadingDoor = false;
		if (WireLib) then
			ent.TriggerInput = ent.fadeTriggerInput;
			if (ent.Inputs) then
				Wire_Link_Clear(ent, "Fade");
				ent.Inputs['Fade'] = nil;
				WireLib._SetInputs(ent);
			end if (ent.Outputs) then
				local port = ent.Outputs['FadeActive']
				if (port) then
					for i,inp in ipairs(port.Connected) do -- From WireLib.lua: -- fix by Syranide: unlinks wires of removed outputs
						if (inp.Entity:IsValid()) then
							Wire_Link_Clear(inp.Entity, inp.Name)
						end
					end
				end
				ent.Outputs['FadeActive'] = nil;
				WireLib._SetOutputs(ent);
			end
		end
	end
end

function TOOL:LeftClick(tr)
	if (not checkTrace(tr)) then
		return false;
	end
	local ent = tr.Entity;
	local ply = self:GetOwner();
	dooEet(ply, ent, {
		key      = self:GetClientNumber("key");
		toggle   = true;
		reversed = self:GetClientNumber("reversed") == 1;
	});
	undo.Create("fading_door");
		undo.AddFunction(doUndo, ent);
		undo.SetPlayer(ply);
	undo.Finish();
	
	SendUserMessage("FadingDoorHurrah!", ply);
	return true
	
end

Thanks either way!