Update: It’s probably somewhere there
ˇˇˇlua
function ActiveCastStatic.new(caster: Caster, origin: Vector3, direction: Vector3, velocity: Vector3 | number, castDataPacket: FastCastBehavior): ActiveCast
if typeof(velocity) == “number” then
velocity = direction.Unit * velocity
end
-- Basic setup
local cast = {
Caster = caster,
-- Data that keeps track of what's going on as well as edits we might make during runtime.
StateInfo = {
UpdateConnection = nil,
Paused = false,
TotalRuntime = 0,
DistanceCovered = 0,
HighFidelitySegmentSize = castDataPacket.HighFidelitySegmentSize,
HighFidelityBehavior = castDataPacket.HighFidelityBehavior,
IsActivelySimulatingPierce = false,
IsActivelyResimulating = false,
CancelHighResCast = false,
Trajectories = {
{
StartTime = 0,
EndTime = -1,
Origin = origin,
InitialVelocity = velocity,
Acceleration = castDataPacket.Acceleration
}
}
},
-- Information pertaining to actual raycasting.
RayInfo = {
Parameters = castDataPacket.RaycastParams,
WorldRoot = workspace,
MaxDistance = castDataPacket.MaxDistance or 1000,
CosmeticBulletObject = castDataPacket.CosmeticBulletTemplate, -- This is intended. We clone it a smidge of the way down.
CanPierceCallback = castDataPacket.CanPierceFunction
},
UserData = {}
}
if cast.StateInfo.HighFidelityBehavior == 2 then
cast.StateInfo.HighFidelityBehavior = 3
end
if cast.RayInfo.Parameters ~= nil then
cast.RayInfo.Parameters = CloneCastParams(cast.RayInfo.Parameters)
else
cast.RayInfo.Parameters = RaycastParams.new()
end
local usingProvider = false
if castDataPacket.CosmeticBulletProvider == nil then
-- The provider is nil. Use a cosmetic object clone.
if cast.RayInfo.CosmeticBulletObject ~= nil then
cast.RayInfo.CosmeticBulletObject = cast.RayInfo.CosmeticBulletObject:Clone()
cast.RayInfo.CosmeticBulletObject.CFrame = CFrame.new(origin, origin + direction)
cast.RayInfo.CosmeticBulletObject.Parent = castDataPacket.CosmeticBulletContainer
end
else
-- The provider is not nil.
-- Is it what we want?
if typeof(castDataPacket.CosmeticBulletProvider) == "PartCache" then
-- this modded version of typeof is implemented up top.
-- Aside from that, yes, it's a part cache. Good to go!
if cast.RayInfo.CosmeticBulletObject ~= nil then
-- They also set the template. Not good. Warn + clear this up.
warn("Do not define FastCastBehavior.CosmeticBulletTemplate and FastCastBehavior.CosmeticBulletProvider at the same time! The provider will be used, and CosmeticBulletTemplate will be set to nil.")
cast.RayInfo.CosmeticBulletObject = nil
castDataPacket.CosmeticBulletTemplate = nil
end
cast.RayInfo.CosmeticBulletObject = castDataPacket.CosmeticBulletProvider:GetPart()
cast.RayInfo.CosmeticBulletObject.CFrame = CFrame.new(origin, origin + direction)
usingProvider = true
else
warn("FastCastBehavior.CosmeticBulletProvider was not an instance of the PartCache module (an external/separate model)! Are you inputting an instance created via PartCache.new? If so, are you on the latest version of PartCache? Setting FastCastBehavior.CosmeticBulletProvider to nil.")
castDataPacket.CosmeticBulletProvider = nil
end
end
local targetContainer: Instance;
if usingProvider then
targetContainer = castDataPacket.CosmeticBulletProvider.CurrentCacheParent
else
targetContainer = castDataPacket.CosmeticBulletContainer
end
if castDataPacket.AutoIgnoreContainer == true and targetContainer ~= nil then
local ignoreList = cast.RayInfo.Parameters.FilterDescendantsInstances
if table.find(ignoreList, targetContainer) == nil then
table.insert(ignoreList, targetContainer)
cast.RayInfo.Parameters.FilterDescendantsInstances = ignoreList
end
end
local event
if RunService:IsClient() then
event = RunService.RenderStepped
else
event = RunService.Heartbeat
end
setmetatable(cast, ActiveCastStatic)
cast.StateInfo.UpdateConnection = event:Connect(function (delta)
if cast.StateInfo.Paused then return end
PrintDebug("Casting for frame.")
local latestTrajectory = cast.StateInfo.Trajectories[#cast.StateInfo.Trajectories]
if (cast.StateInfo.HighFidelityBehavior == 3 and latestTrajectory.Acceleration ~= Vector3.new() and cast.StateInfo.HighFidelitySegmentSize > 0) then
local timeAtStart = tick()
if cast.StateInfo.IsActivelyResimulating then
cast:Terminate()
error("Cascading cast lag encountered! The caster attempted to perform a high fidelity cast before the previous one completed, resulting in exponential cast lag. Consider increasing HighFidelitySegmentSize.")
end
cast.StateInfo.IsActivelyResimulating = true
-- Actually want to calculate this early to find displacement
local origin = latestTrajectory.Origin
local totalDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime
local initialVelocity = latestTrajectory.InitialVelocity
local acceleration = latestTrajectory.Acceleration
local lastPoint = GetPositionAtTime(totalDelta, origin, initialVelocity, acceleration)
local lastVelocity = GetVelocityAtTime(totalDelta, initialVelocity, acceleration)
local lastDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime
cast.StateInfo.TotalRuntime += delta
-- Recalculate this.
totalDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime
local currentPoint = GetPositionAtTime(totalDelta, origin, initialVelocity, acceleration)
local currentVelocity = GetVelocityAtTime(totalDelta, initialVelocity, acceleration)
local totalDisplacement = currentPoint - lastPoint -- This is the displacement from where the ray was on the last from to where the ray is now.
local rayDir = totalDisplacement.Unit * currentVelocity.Magnitude * delta
local targetWorldRoot = cast.RayInfo.WorldRoot
local resultOfCast = targetWorldRoot:Raycast(lastPoint, rayDir, cast.RayInfo.Parameters)
local point = currentPoint
if (resultOfCast ~= nil) then
point = resultOfCast.Position
end
local rayDisplacement = (point - lastPoint).Magnitude
-- Now undo this. The line below in the for loop will add this time back gradually.
cast.StateInfo.TotalRuntime -= delta
-- And now that we have displacement, we can calculate segment size.
local numSegmentsDecimal = rayDisplacement / cast.StateInfo.HighFidelitySegmentSize -- say rayDisplacement is 5.1, segment size is 0.5 -- 10.2 segments
local numSegmentsReal = math.floor(numSegmentsDecimal) -- 10 segments + 0.2 extra segments
if (numSegmentsReal == 0) then
numSegmentsReal = 1
end
local timeIncrement = delta / numSegmentsReal
for segmentIndex = 1, numSegmentsReal do
if getmetatable(cast) == nil then return end -- Could have been disposed.
if cast.StateInfo.CancelHighResCast then
cast.StateInfo.CancelHighResCast = false
break
end
PrintDebug("[" .. segmentIndex .. "] Subcast of time increment " .. timeIncrement)
SimulateCast(cast, timeIncrement, true)
end
if getmetatable(cast) == nil then return end -- Could have been disposed.
cast.StateInfo.IsActivelyResimulating = false
if (tick() - timeAtStart) > 0.016 * 5 then
warn("Extreme cast lag encountered! Consider increasing HighFidelitySegmentSize.")
end
else
SimulateCast(cast, delta, false)
end
end)
return cast
end
´´´´