Home Suggestions
Welcome to the new Diaspora forums, please let us know if you see anything broken! Notice: Some users may need to reupload their avatars due to an issue during forum setup!

Timers that call E2 functions

NinjrKillrNinjrKillr Registered Posts: 175
edited March 2012 in Suggestions #1
http://www.wiremod.com/forum/developers-showcase/27376-timers-call-e2-functions.html

So yeah, I found this on the wiremod forums, and I figured it could be useful, not sure about you... You can either check it out at the link above, or I've quoted it below.
Divran wrote:
Function list
  • timer(Delay,Reps,UniqueID,FunctionID,...) - Creates a timer which calls the function every "Delay" milliseconds, and runs "Reps" number of times (0 for infinite - or until removetimer is called). The last arguments are passed into the function. The E2 will error if invalid arguments are specified.
  • removetimer(UniqueID) - Removes the timer with the specified UniqueID

Thanks to Donkie. It was his idea :)

Example use
function test(A,B,C,D,E) {print(A,B,C,D,E)}

timer(1000,1,"a","test(nnnnn)",1,2,3,4,5) #Will print 1,2,3,4,5 (once) after 1 second

function entity:applyHax( V:vector ) {
    This:applyForce( V )
}

timer(1000,0,"b","applyHax(e:v)",entity(),vec(0,0,250)) #Will make the E2 jump up once a second


Lua code which goes in wire/lua/entities/gmod_wire_expression2/core/custom/<whatever>.lua
local string_match = string.match
local string_gsub = string.gsub
local string_find = string.find
local table_concat = table.concat
local string_sub = string.sub


registerFunction("timer","nnss...","", function( self, args )
	local op1, op2, op3, op4 = args&#91;2&#93;, args&#91;3&#93;, args&#91;4&#93;, args&#91;5&#93;
	local delay, reps, uniqueid, funcname = op1&#91;1&#93;(self,op1), op2&#91;1&#93;(self,op2), op3&#91;1&#93;(self,op3), op4&#91;1&#93;(self,op4)
	
	if funcname == "timer(nnss...)" then error( "You may not call the timer function from inside a timer" ) end
	
	local func = self.funcs&#91;funcname&#93; or (wire_expression2_funcs&#91;funcname&#93; ~= nil and wire_expression2_funcs&#91;funcname&#93;&#91;3&#93; or nil)
	
	if func then
		local typeids = args&#91;#args&#93;		
		
		local func_args = string_gsub(string_match( funcname, "%((.+)%)" ) or "",":","")	
		local str_args = table_concat( typeids, "", 5 )
		
		local has_varargs = false
		local args_are_ok = false
		
		if func_args == "..." then  -- Argument types don't matter
			has_varargs = true
			args_are_ok = true
		elseif string_find( func_args, "...", 1, true ) then
			has_varargs = true
			
			func_args = string_match(func_args,"(.+)%.%.%.") -- Get the argument types that do matter
			args_are_ok = (func_args == string_sub( str_args, 1, #func_args )) -- Compare them
		else
			args_are_ok = (func_args == str_args)
		end

		if args_are_ok then
			
			local id = "Wire_Expression2_Timer_" .. self.entity:EntIndex() .. "_" .. uniqueid
			
			---- Create fake args table
			local new_typeids 
			if has_varargs then
				-- Copy the typeids (Doesn't seem to be necessary, so I commented it out, and it still works)
			
				-- Calculate how many typeids we need to skip (hacky code D:)
				local n = 0
				for i=1,#func_args do
					n = n + 1
					if func_args&#91;i&#93; == "x" then n = n - 2 end
				end
				
				new_typeids = {}
				for i=5+n,#typeids do
					new_typeids&#91;i-(4+n)&#93; = typeids&#91;i&#93;
				end
			end
			
			-- Copy the arguments
			local new_args = {}
			for i=6,#args-1 do
				-- Didn't work
				--new_args&#91;i-4&#93; = args&#91;i&#93;

				-- Didn't work either
				--new_args&#91;i-4&#93; = {}
				--for k,v in pairs( args&#91;i&#93; ) do
				--	new_args&#91;i-4&#93;&#91;k&#93; = v
				--end
				
				-- Hacky code D:
				local val = args&#91;i&#93;&#91;1&#93;( self, args&#91;i&#93; )
				new_args&#91;i-4&#93; = {function() return val end}
			end
			
			-- Set the first argument to the function itself (Not 100% sure this is correct, but it works)
			new_args&#91;1&#93; = func
			
			-- Set the new typeids
			if has_varargs then new_args&#91;#new_args+1&#93; = new_typeids end
			
			timer.Create( id, delay/1000, reps, function( self, func, args )
				if self and self.entity and self.entity:IsValid() then
					func( self, args )
				else
					timer.Remove( id )
				end
			end, self, func, new_args )
		else
			error( "Mismatching arguments to timer: " .. func_args .. " expected, got " .. str_args )
		end
	else
		error( "The specified function does not exist." )
	end
end)

e2function void removetimer( string uniqueid )
	local id = "Wire_Expression2_Timer_" .. self.entity:EntIndex() .. "_" .. uniqueid
	if timer.IsTimer( id ) then
		timer.Remove( id )
	end
end

"We fear that which we cannot see... we respect that which we cannot see... thus the blade will be wielded."

Urahara_Bleach_Signature_by_Harty73.png

Comments

  • Lambda217Lambda217 Registered, Moderator Posts: 534
    Would be more efficient than a clk() check.


    "I want you to show this world what it means to fear the sky."

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file