User:NXTBoy/Scripts/LightRay
From Legacy Roblox Wiki
< User:NXTBoy | Scripts
This is a slightly updated copy of the code running in my raycasting place. This class made everything much more fun to work with - ray the wrong length? ray.length = 50.
local LightRay = {}
__private = setmetatable({}, {__mode="k"})
--[==========================[Getters and Setters ]==========================]
LightRay.__getters = {}
function LightRay.__getters.endPoint(p)
return p.endPoint or p.startPoint + p.direction
end
function LightRay.__getters.direction(p)
return p.direction or p.endPoint - p.startPoint
end
function LightRay.__getters.length(p)
return LightRay.__getters.direction(p).magnitude
end
function LightRay.__getters.unitRay(p)
return Ray.new(p.startPoint, getters.direction(p).unit)
end
LightRay.__setters = {}
function LightRay.__setters.length(p, length)
p.direction = getters.direction(p).unit * length
p.endPoint = false
end
function LightRay.__setters.startPoint(p, startPoint)
p.endPoint = getters.endPoint(p)
p.direction = false
p.startPoint = startPoint
end
--[===============================[Metatable ]===============================]
function LightRay:__index(k)
local properties = __private[self]
local getter = self.__getters[k]
return getter and getter(properties) or properties[k] or LightRay[k]
end
function LightRay:__newindex(k, v)
local properties = __private[self]
local setter = self.__setters[k]
if setter then setter(properties, v) end
end
function LightRay.__mul(a, b)
if type(a) == "number" then
a, b = b, a
end
if type(b) == "number" then
return LightRay.new(a.startPoint, a.direction * b, a.color)
else
error("Invalid argument!")
end
end
--[==============================[Constructors]==============================]
function __createRay(props)
local ray = setmetatable({}, LightRay)
__private[ray] = props
return ray
end
function LightRay.new(origin, direction, color)
if not origin or not direction then error("Argument is Nil") end
return __createRay({
startPoint = origin,
direction = direction,
endPoint = false,
color = color
})
end
function LightRay.between(startPoint, endPoint, color)
if not startPoint or not endPoint then error("Argument is Nil") end
return __createRay({
startPoint = startPoint,
direction = false,
endPoint = endPoint,
color = color
})
end
function LightRay.fromRay(ray)
return LightRay.new(ray.Origin, ray.Direction)
end
--[============================[Member Functions]============================]
function LightRay:toRay()
return Ray.new(self.startPoint, self.direction)
end
function LightRay:draw(diameter)
local beam = game.Lighting.Beam:clone()
beam.Size = Vector3.new(diameter, self.length, diameter)
beam.CFrame = CFrame.new(self.startPoint + self.direction / 2, self.endPoint)*CFrame.Angles(math.rad(90), 0, 0)
beam.BrickColor = self.color or beam.BrickColor
return beam
end
function LightRay:raycast(filter)
if self.length > 1000 then
print("WARNING: Ray length ("..self.length..") must be <= 1000. Truncating ray")
self.length = 999 --Avoid rounding errors at all cost
end
local part, hitPoint = workspace:findPartOnRay(self:toRay(), filter)
if not hitPoint then
hitPoint = self.endPoint
end
local s, b = self:split(hitPoint)
return part, s, b
end
function LightRay:specularReflection(normal)
normal = normal.unit
local incident = self.direction
local dotProduct = normal:Dot(incident)
--prevent internal reflection
local reflected = dotProduct < 0 and incident - 2*dotProduct*normal or incident
return LightRay.new(self.startPoint, reflected, self.color)
end
function LightRay:split(point)
if not point then error("Argument is Nil") end
return LightRay.between(self.startPoint, point, self.color),
LightRay.between(point, self.endPoint, self.color)
end
function LightRay:clone()
return LightRay.new(self.origin, self.direction, self.color)
end