Static Vars and Callback Functions (DRIVING ME NUTS!)

I’ve been working on this for the past two days after work and I can’t figure out what lua does for static variables.

My basic code structure is like this:

connection:SetCallback(...)
// get and parse rotation data through udp packets <this works
end

local function StationaryAimingCreateMove (cmd)
// do stuff with view angles
end

hook.Add ("CreateMove", "SACM", StationaryAimingCreateMove)

I want to be able to access the parsed data in the callback function from the StationaryAimingCreateMove function.
in C programming (blessed be thy name), you'd use a global static var and be done in 30 seconds. I can't for the life of me figure out how to get it working in lua.

Well, I don’t know what kind of data you are storing with the callback, but you would do something like:



data = { }
local function Callback( ... )
  --magic
  data.angle = blah
end

local function CreateMove( cmd )
  cmd:SetViewAngles( data.angle or vector_origin:Angle( ) )
end

hook.Add( "CreateMove", "SACM", CreateMove )


I don’t know what kind of data you get from your callback, but that’s pretty much how you would go about it.

Nevermind, i had two things named data.

data.angle is returning a nil value but I can clearly print the values inside of the callback function!!

Show your code or we can’t help you.

Sure, here it is:



require("oosocks")
connection = OOSock(IPPROTO_UDP);
datam = { }

connection:SetCallback(function(socket, callType, callId, err, data, peer, peerPort)
    if(callType == SCKCALL_BIND && err == SCKERR_OK) then
        print("Bound.");
        connection:ReceiveDatagram();
    end
     
    if(callType == SCKCALL_REC_DATAGRAM && err == SCKERR_OK) then
        //print("Got '" .. data .. "'  from  " .. peer .. ":" .. tostring(peerPort));
		print(data); // sanity check
		Sep = string.Explode(";", data)

			datam.r=Sep[1]
			datam.p=Sep[2]
			datam.y=Sep[3]

        --socket:Close()
		connection:ReceiveDatagram();
    end
     
    if(err != SCKERR_OK) then
        --socket:Close()
    end
end);

connection:Bind("", 5001);


[...]

local function StationaryAimingCreateMove (cmd)
	if WeaponUsesStationaryAiming() then
		LocalPlayer():GetActiveWeapon():Thinkie()
		
		LocalPlayer():AddRecoil(cmd)
		
		if WeaponStationaryAimingOn() then
			if not lockedViewAng then
				lockedViewAng = cmd:GetViewAngles()
				lockedViewAngOffset = Angle (0,0,0)
			end
			
			--sensitivity
			local angles = cmd:GetViewAngles()
			if lastRealViewAng then
				SimilarizeAngles (lastRealViewAng, angles)
				local diff = angles - lastRealViewAng
				diff = diff * (LocalPlayer():GetActiveWeapon().MouseSensitivity or 1)
				angles = lastRealViewAng + diff
			end
			
			lastRealViewAng = angles
			SimilarizeAngles (lockedViewAng, angles)
				
				print(datam.r)
				print(datam.p)
				print(datam.y)

			cmd:SetViewAngles (angles)
		elseif lockedViewAng then
			--cmd:SetViewAngles (lockedViewAng)
			--lockedViewAng = false
			--lastRealViewAng = false
			local angles = cmd:GetViewAngles()
			
			if lastRealViewAng then
				SimilarizeAngles (lastRealViewAng, angles)
				local diff = angles - lastRealViewAng
				--diff = diff * (LocalPlayer():GetActiveWeapon().MouseSensitivity or 1)
				lockedViewAng = lockedViewAng + diff
			end
			
			if not returnJourney then
				SimilarizeAngles (lockedViewAng, angles)
				returnJourney = lockedViewAng - angles
				returnJourney = returnJourney * (1/LocalPlayer():GetActiveWeapon().DegreeOfZoom)
			end
			
			if LocalPlayer():GetActiveWeapon().DegreeOfZoom > 0 then
				angles = angles + (returnJourney * (FrameTime() / LocalPlayer():GetActiveWeapon().ZoomTime))
				cmd:SetViewAngles (angles)
				lastRealViewAng = angles
			else
				lockedViewAng = false
				lastRealViewAng = false
				returnJourney = false
			end
		end
		LocalPlayer():SetFOV (LocalPlayer():GetActiveWeapon().FOVToSet or nil)
	else
		if lockedViewAng then
			lockedViewAng = false
			lastRealViewAng = false
			LocalPlayer():SetFOV (nil)
		end
	end
end

hook.Add ("CreateMove", "SACM", StationaryAimingCreateMove)



specifically, I’m getting nil values for datam.r datam.p and datam.y

Any clue??

You could do this:

datam = Angle( 0, 0, 0 )

Since you are using the p y r fields already that will adjust the values on the angle object itself, and it will be usable in your angle math in the second function.

Could you expand on that a bit? I did what I think you meant but I am returning all 1’s when the secondary aiming create move is called and the actual real-time data when it’s not. Sorry for being a noob at this.



datam = Angle(0,0,0) // not in any function ie in the globals area in the top

connection:SetCallback(function(socket, callType, callId, err, data, peer, peerPort)
        //[...]
	Sep = string.Explode(";", data)
	datam.r=Sep[1]
	datam.p=Sep[2]
	datam.y=Sep[3]
        //[...]
end);


// then in a later function:
local function StationaryAimingCreateMove (cmd)
	print(datam.r)
	print(datam.p)
	print(datam.y)
end



Ok, I figured this out for anybody else who might encounter this issue in the future.

Callback functions (or Interrupt Service Routines) cannot save to global functions (or arrays) so they have to call another function and pass the data it wants to save so that the function can write to the global static variable. I’m not sure why this is, and the reason for doing it in such a manner is beyond me.



gData = {}
function savedata(data)
	gData[1]=data[1]
	gData[2]=data[2]
	gData[3]=data[3]
end

-- inside of the callback:

connection:SetCallback(function(socket, callType, callId, err, data, peer, peerPort)
    if(callType == SCKCALL_BIND && err == SCKERR_OK) then
        print("Bound.");
        connection:ReceiveDatagram();
    end
    if(callType == SCKCALL_REC_DATAGRAM && err == SCKERR_OK) then
		Sep = string.Explode(",", data)
        data = {}
        data[1]=Sep[1]
	data[2]=Sep[2]
	data[3]=Sep[3]
        savedata(data)
		connection:ReceiveDatagram();
    end
end);



Sorry that I am late, …
actually -snip-

I have to test this when I’ve installed GMod :frowning: