-- LUA Script - precede every function and global member with lowercase name of script + '_main' -- Default script - does nothing. -- Add this to always active entity - only one is needed local Q = require "scriptbank\\quatlib" local deg = math.deg local rad = math.rad local sin = math.sin local cos = math.cos local atan = math.atan2 local tan = math.tan local pi = math.pi local abs = math.abs local modf = math.modf local sqrt = math.sqrt local pickUpDistance = 150 local pickUppableEntity = {Ent = nil} local function Rotate3D (x, y, z, xrot, yrot, zrot) function RotatePoint2D (x, y, Ang) -- Ang in radians local Sa, Ca = sin(Ang), cos(Ang) return x*Ca - y*Sa, x*Sa + y*Ca end local NX, NY, NZ = x, y, z -- X NZ, NY = RotatePoint2D (NZ, NY, -xrot) -- Y NX, NZ = RotatePoint2D (NX, NZ, -yrot) -- Z NY, NX = RotatePoint2D (NY, NX, -zrot) return NX, NY, NZ end local function WrapAng(Ang) local RAng = Ang while RAng >= 360 do RAng = RAng - 360 end while RAng < 0 do RAng = RAng + 360 end return RAng end function ray_collision_test_init(e) pickUppableEntity.Ent = nil end local function GetObjectSize(p) p.l, p.h, p.w = 0, 0, 0 local Ent = g_Entity[p.Ent] local x, y, z = Ent.x, Ent.y, Ent.z local ax, ay, az = rad(Ent.anglex), rad(WrapAng(Ent.angley)), rad(Ent.anglez) local xwi, yli, zwi = Rotate3D(1, 0, 0, ax, ay, az) local xli, yli, zli = Rotate3D(0, 0, 1, ax, ay, az) -- find height of object local height = y + 1 local ignore = 0 local newx, newz = x + xwi, z + zwi while IntersectAll(newx, height, newz, x, height, z, ignore) ~= p.Obj do newx, newz = newx + xwi, newz + zwi end while IntersectAll(newx, height, newz, x, height, z, ignore) == p.Obj do height = height + 10 end while IntersectAll(newx, height, newz, x, height, z, ignore) ~= p.Obj do height = height - 1 end p.h = height - y + 1 local newy = y + height + 2 local stX, stZ = newx, newz -- measure 'width' local foundEdge = false local fObj = 0 while not foundEdge do fObj = IntersectAll(newx, newy, newz, newx, y, newz, ignore) if fObj == p.Obj then foundEdge = true elseif fObj ~= nil and fObj ~= 0 then ignore = fObj else newx, newz = newx - xwi, newz - zwi end end foundEdge = false ignore = 0 while not foundEdge do fObj = IntersectAll(newx, newy, newz, newx, y, newz, ignore) if fObj ~= p.Obj then if fObj == nil or fObj == 0 then foundEdge = true else ignore = fObj end else newx, newz = newx - (xwi * 10), newz - (zwi * 10) end end foundEdge = false ignore = 0 while not foundEdge do fObj = IntersectAll(newx, newy, newz, newx, y, newz, ignore) if fObj == p.Obj then foundEdge = true elseif fObj ~= nil and fObj ~= 0 then ignore = fObj else newx, newz = newx + xwi, newz + zwi end end local xd, zd = newx - stX, newz - stZ p.w = sqrt(xd*xd+zd*zd) -- measure 'length' newx, newz = x, z foundEdge = false ignore = 0 while not foundEdge do fObj = IntersectAll(newx, newy, newz, newx, y, newz, ignore) if fObj ~= p.Obj then if fObj == nil or fObj == 0 then foundEdge = true else ignore = fObj end else newx, newz = newx - (xli * 10), newz - (zli * 10) end end foundEdge = false ignore = 0 while not foundEdge do fObj = IntersectAll(newx, newy, newz, newx, y, newz, ignore) if fObj == p.Obj then foundEdge = true elseif fObj ~= nil and fObj ~= 0 then ignore = fObj else newx, newz = newx + xli, newz + zli end end xd, zd = newx - x, newz - z p.l = (sqrt(xd*xd+zd*zd) + 1) * 2 end local function PrintDetails(p) if p.l > p.w then PromptLocal(p.Ent, p.Ent .. ", len=" .. p.l .. " width=" .. p.w .. " height=" .. p.h) else PromptLocal(p.Ent, p.Ent .. ", len=" .. p.w .. " width=" .. p.l .. " height=" .. p.h) end end function ray_collision_test_main(e) if pickUppableEntity.Ent ~= nil then PrintDetails(pickUppableEntity) end -- Only check every 10th second if not scheduler(e) then return end local x, y, z = g_PlayerPosX, g_PlayerPosY + 35, g_PlayerPosZ local rayX, rayY, rayZ = 0, 0, pickUpDistance local paX, paY, paZ = rad(g_PlayerAngX), rad(g_PlayerAngY), rad(g_PlayerAngZ) rayX, rayY, rayZ = Rotate3D(rayX, rayY, rayZ, paX, paY, paZ) local Pobj = IntersectAll(x, y, z, x + rayX, y + rayY, z + rayZ, 0) if Pobj ~= 0 then for k,v in pairs(g_Entity) do if v.obj == Pobj then if pickUppableEntity.Ent ~= k then pickUppableEntity = {Ent = k, Obj = Pobj, pickedUp = false} GetObjectSize(pickUppableEntity) end return end end end pickUppableEntity.Ent = nil end ---------------------------------------------------------------- -- Scheduler, this nifty little function keeps track of time. -- -- The main routine should be called every frame and returns -- -- a flag indicating whether the passed in time has expired -- -- since the last time it was called. -- -- If no time period is specified 100ms is used by default, -- -- i.e. 1/10th of a second. -- -- The caller can either ignore the return flag or use it to -- -- trigger time sensitive functionality. -- -- A global value giving the frames per second count is also -- -- generated, this can be used in script to make animations -- -- independent of frames. -- -- The reason this function is tied to an entity rather than -- -- being global is so that each entity can be triggered at a -- -- different time rather than all being triggered in the same -- -- frame. ---------------------------------------------------------------- g_scheduler = {} function scheduler(e, period) period = period or 100 -- defaults to tenths of a second (100ms) if g_Time == nil then return false end if g_scheduler[e] == nil then g_scheduler[e] = {frames_per_second = 60, period_accumulated = math.random(0, period), accumulated_time = 0, timer_value_last_frame = g_Time, frame_counter = 0}; -- 'test' mode sometimes doesn't clear Lua globals so if -- this appears to be the case initialise everything elseif g_scheduler[e].accumulated_time > 2000 then g_scheduler[e].frames_per_second = 60 g_scheduler[e].period_accumulated = math.random(0, period) g_scheduler[e].accumulated_time = 0 g_scheduler[e].timer_value_last_frame = g_Time g_scheduler[e].frame_counter = 0 end local entry = g_scheduler[e] local do_this_frame_flag = false entry.frame_counter = entry.frame_counter + 1 local time_since_last_frame = g_Time - entry.timer_value_last_frame if (entry.period_accumulated + time_since_last_frame) > period then entry.period_accumulated = (entry.period_accumulated + time_since_last_frame) - period; do_this_frame_flag = true else entry.period_accumulated = entry.period_accumulated + time_since_last_frame end if (entry.accumulated_time + time_since_last_frame) > 1000 then -- more than a second passed? entry.accumulated_time = (entry.accumulated_time + time_since_last_frame) - 1000; entry.frames_per_second = entry.frame_counter entry.frame_counter = 0 else entry.accumulated_time = entry.accumulated_time + time_since_last_frame end entry.timer_value_last_frame = entry.timer_value_last_frame + time_since_last_frame return do_this_frame_flag end