--[[ $Id: userfunction_detector.lua 225 2013-04-16 17:03:11Z $ Object detector, runs in background and does a callback on detection of object. --]] require "os" -- -- Implementation of new event -- USER_PLAYERCLOSE = "USER_PLAYERCLOSE" USER_PLAYERGONE = "USER_PLAYERGONE" -- -- Generic object in range, based on userfunction_precence -- Also include compatibility functions to userfunction_precence -- so dont have it installed -- function CPlayer:ObjectInRange(_range, pt_type, _name, _X, _Z) local _range = _range or 300 local _X = _X or self.X local _Z = _Z or self.Z local _objnames = {""} -- Array of id/name mix? if type(_name) == "table" then _objnames = {} for k,v in pairs(_name) do table.insert(_objnames, type(v) == "number" and GetIdName(v) or v) end end -- Id (number) if type(_name) == "number" then _objnames = {GetIdName(_name)} end -- Name (string) if type(_name) == "string" then _objnames = {_name} end -- Any type given to mob? if not pt_type then pt_type = PT_MONSTER end local found = false local res = {} local objectList = CObjectList() objectList:update() for i = 0,objectList:size() do obj = objectList:getObject(i) for k,_name in pairs(_objnames) do if( obj.Type == pt_type and obj.Name ~= self.Name and obj.Name ~= "" and (_name == "" or obj.Name == _name) ) then dist = distance(_X, _Z, obj.X, obj.Z) if( dist < _range ) then table.insert(res, obj) found = true end end end end return found, res end -- -- Named boss/mob in range -- function CPlayer:MobInRange(_name,_range,_X,_Z, pt_type) return self:ObjectInRange(_range, PT_MONSTER, _name, _X, _Z) end -- -- Any player in range -- function CPlayer:PlayerInRange(_range,_X,_Z) return self:ObjectInRange(_range, PT_PLAYER, nil, _X, _Z) end -- -- Default player detection callback -- function DefaultPlayerDetected(event) local objs = unpack(event.arg) -- Some players are close if event.name == USER_PLAYERCLOSE then cprintf(cli.red, "\n\aPlayers close:\n") for k,v in pairs(objs) do cprintf(cli.yellow, " %s <%d>\n", v.Name, distance(player.X, player.Z, v.X, v.Z)) end cprintf(cli.yellow, "\n") -- Who ever it was is gone now elseif event.name == USER_PLAYERGONE then cprintf(cli.yellow, "\nNo players around!\n") end end -- -- Setup player detection -- -- -- Detect if a player is close by, constantly monitoring -- function PlayerDetection(range, timeout, ...) local range = range or 1500 -- Client wont detect further away than than 5-600, so this is apporx infinite local timeout = timeout or 30 local players_was_close = false local last_close = 0 -- Timer function, keep small for speed local function PlayerClose(range, timeout, ...) local found, res = player:PlayerInRange(range) -- We have found some players close if found then -- Refresh detection time for timeout last_close = os.time() -- None were found last time, do callback if last_close == 0 or not players_was_close then players_was_close = true Events:throw(USER_PLAYERCLOSE, res, unpack(arg)) end -- No players close now else -- Players were found last time if last_close == 0 or players_was_close then -- Only want first check to generate event last_close = 1 -- Have we timed out yet? if os.time() - last_close > timeout then players_was_close = false Events:throw(USER_PLAYERGONE, nil, unpack(arg)) end end end end -- Define events we use Events:define(USER_PLAYERCLOSE) Events:define(USER_PLAYERGONE) -- Add default handing to events as last action Events:register(USER_PLAYERCLOSE, DefaultPlayerDetected, 499) Events:register(USER_PLAYERGONE, DefaultPlayerDetected, 499) Events:register(SYS_RESUME, function() last_close = 0 end , 101) -- Players might have sneaked up on us while sleeping -- Kick off timer registerTimer("playerDetect", secondsToTimer(1), PlayerClose, range, timeout, unpack(arg)) end