Maybe that was an earlier build. I did see it but it was last week.
Feel free to chime in, even if you aren’t TheFortex.
I mean, I told you the problem I just wanted confirmation. Something like “ROBLOX has an issue when creating beams in rapid succession” would do but if you must:
local RunService = game:GetService('RunService')
local FastCast = require(script.FastCastRedux)
local caster = FastCast.new()
local config = require(script.Parent:WaitForChild('Config'))
local firePoint = script.Parent.Point
local target = script.Parent.Parent.Parent:WaitForChild('Core'):WaitForChild('Target')
local weapongroup = script.Parent.Parent.Parent.Core:WaitForChild('WeaponGroups'):WaitForChild(config.WeaponGroup)
--Settings Load
local RNG = Random.new() -- Set up a randomizer.
local DEBUG_VISUALIZE = false -- If true, individual sub-rays will be shown with black cones.
local BULLET_MAXDIST = 10000 -- The furthest distance the bullet can travel
local BULLET_GRAVITY = Vector3.new(0, 0, 0) -- The amount of gravity applied to the bullet in world space (so yes, you can have sideways gravity)
local MIN_BULLET_SPREAD_ANGLE = config.minSpread -- THIS VALUE IS VERY SENSITIVE. Try to keep changes to it small. The least accurate the bullet can be. This angle value is in degrees. A value of 0 means straight forward. Generally you want to keep this at 0 so there's at least some chance of a 100% accurate shot.
local MAX_BULLET_SPREAD_ANGLE = config.maxSpread -- THIS VALUE IS VERY SENSITIVE. Try to keep changes to it small. The most accurate the bullet can be. This angle value is in degrees. A value of 0 means straight forward. This cannot be less than the value above. A value of 90 will allow the gun to shoot sideways at most, and a value of 180 will allow the gun to shoot backwards at most. Exceeding 180 will not add any more angular varience. -- The amount of time that must pass after firing the gun before we can fire again.
local TAU = math.pi * 2 -- Set up mathematical constant Tau (pi * 2)
--local CosmeticBullet = Instance.new("Part")
--CosmeticBullet.Material = Enum.Material.Neon
--CosmeticBullet.Color = Color3.fromRGB(0, 196, 255)
--CosmeticBullet.CanCollide = false
--CosmeticBullet.Anchored = true
--CosmeticBullet.Size = Vector3.new(0.4, 0.4, 2.4)
local BeamTracer = Instance.new('Beam')
BeamTracer.Name = 'Tracer'
BeamTracer.Texture = config.Texture
BeamTracer.Width0 = 0
BeamTracer.Width1 = 0.35
BeamTracer.Color = config.Color
BeamTracer.FaceCamera = true
BeamTracer.LightInfluence = 0
BeamTracer.LightEmission = 1
BeamTracer.Transparency = NumberSequence.new(0.333, 0)
BeamTracer.TextureMode = Enum.TextureMode.Stretch
BeamTracer.TextureSpeed = 0
--BeamTracer.Color = config.Color
local tp1 = Instance.new('Part')
tp1.Anchored = true
tp1.Size = Vector3.new(0.5, 0.5, 0.5)
tp1.Transparency = 1
tp1.BrickColor = BrickColor.Red()
local ta1 = Instance.new('Attachment', tp1)
ta1.Name = 'ta1'
local tp2 = Instance.new('Part')
tp2.Anchored = true
tp2.Transparency = 1
tp2.Size = Vector3.new(0.5, 0.5, 0.5)
tp2.BrickColor = BrickColor.Blue()
local ta2 = Instance.new('Attachment', tp2)
ta2.Name = 'ta2'
BeamTracer.Attachment0 = ta1
BeamTracer.Attachment1 = ta2
local function Fire(direction)
local directionalCF = CFrame.new(Vector3.new(), direction)
-- Now, we can use CFrame orientation to our advantage.
-- Overwrite the existing Direction value.
local direction = (directionalCF * CFrame.fromOrientation(0, 0, RNG:NextNumber(0, TAU)) * CFrame.fromOrientation(math.rad(RNG:NextNumber(MIN_BULLET_SPREAD_ANGLE, MAX_BULLET_SPREAD_ANGLE)), 0, 0)).LookVector
local cosmeticBullet = {tp1:Clone(), tp2:Clone(), BeamTracer:Clone()}
cosmeticBullet[1].CFrame = CFrame.new(firePoint.Position, firePoint.Position + direction)
cosmeticBullet[2].CFrame = CFrame.new(firePoint.Position, firePoint.Position + direction)
cosmeticBullet[1].Parent = workspace.FX
cosmeticBullet[2].Parent = workspace.FX
cosmeticBullet[3].Parent = cosmeticBullet[1]
cosmeticBullet[3].Attachment0 = cosmeticBullet[1].ta1
cosmeticBullet[3].Attachment1 = cosmeticBullet[2].ta2
caster:Fire(firePoint.Position, direction * BULLET_MAXDIST, config.Speed, cosmeticBullet, script.Parent, false, BULLET_GRAVITY, CanRayPierce)
end
function OnRayUpdated(castOrigin, segmentOrigin, segmentDirection, length, cosmeticBulletObject)
local baseCFrame = CFrame.new(segmentOrigin, segmentOrigin + segmentDirection)
cosmeticBulletObject[1].CFrame = baseCFrame * CFrame.new(Vector3.new(0, 0, length), segmentOrigin - segmentDirection)
cosmeticBulletObject[2].Position = segmentOrigin
end
function OnRayHit(hitPart, hitPoint, normal, material, cosmeticBulletObject)
cosmeticBulletObject[3]:Destroy()
cosmeticBulletObject[2]:Destroy()
cosmeticBulletObject[1]:Destroy()
end
function CanRayPierce(hitPart, hitPoint, normal, material)
if hitPart.Parent == workspace.FX then
return true
end
end
caster.LengthChanged:Connect(OnRayUpdated)
caster.RayHit:Connect(OnRayHit)
RunService.Heartbeat:Connect(function()
if target.Value ~= nil then
for i=1, config.BurstSize do
if not weapongroup.Value then return end
Fire((target.Value.Position - firePoint.Position).Unit)
wait(config.ShotCooldown)
end
wait(config.BurstCooldown)
end
end)
For everyone recently – Apologies for the recent regressions! I seem to be having a number of issues in person on my own time and they seem to have adversely affected my motive to work on this module. The result is a huge quality drop in the versions at 11.0.0 and later.
I’m working on a number of patches to try to resolve some of the problems caused. I also want to do more tweaks to the API (renaming events mainly), but I need to ensure things are backwards compatible. I’ll post more on this later down the line.
I’ve also updated the Changelog on the wiki. I completely neglected to do this before, which was bound to have caused issues for people.
Edit: With this post I’ve also released 11.1.2
* Fixed a bug causing pause and resume to do nothing.
Stop being so entitled, OP maintains this module for free, the least you could do is be polite when asking for help
I looked at your issue and it’s not an issue with FC itself. I know I help people here from time to time, but the general best idea would be to go to the scripting help subforum.
Since my API is clearly documented, it should be good to go for posting there. Generally speaking, posting here is if you think there’s a bug with the module that I have to fix.
Since you are using a modified version of the module, that is completely ruled out.
That’s what I was thinking, but I just wanted to make sure because I modified FastCast to work with two parts per cast and not one. I do delete the beam object first so I don’t think its because I delete one of the points it bugs out.
And to the people who think i’m being rude that are jumping in and reading this (not you EtiTheSpirit, your module is amazing):
I’m not being rude. I asked for confirmation if this was a Roblox issue with rendering beams months ago, so forgive me if i’m more direct now. I still have not found a fix after all this time and I had to abandon the project. Don’t jump in to a conversation that is months old and tell me that i’m entitled because I have lost my patience.
And maybe I am a little angry that I had to abandon one or two months of work. Show a little sympathy, please.
I’ve just released a brand new not garbage API! FastCast API
Let me know if you have any issues with it. The one hosted on the Gist (the old link) is obsolete now and will be deleted soon.
The new API for RayHit
is a bit problematic for me.
I currently rely on the returned parameter Position
that older versions of FastCast have, but with the new one it returns a RaycastResult
.
This means that if the ray returns no hit, this is nil. This is a problem because I cannot obtain the Position
parameter from anywhere in that event.
Would it be possible to add a property to the ActiveCast
that contains the end position of the ray regardless if an object is hit or not?
Edit: I’ve found a temporary workaround using UserData
, where I store the end goal as UserData.End
and then check the position if no object was hit in the RayHit
’s ActiveCaster
parameter. Would still be nice to have this in the module itself though.
RayHit
will never fire if the returned RaycastResult
is nil (think about it – a nil RaycastResult
is returned from WorldRoot:Raycast()
if there wasn’t a hit, and with no hit, RayHit
has no reason to fire). This change is part of why the CastTerminated
event was created, as this one fires whenever the cast ends for any reason. If it ends due to a hit, RayHit
will fire first (with a non-nil RaycastResult
) and then CastTerminated
will fire after.
If you still need to access the position CastTerminated
, you can call cast:GetPosition()
(where cast
is the parameter in the event)
I can update the API to reflect on this.
There’s a problem where if you’re running around a target while shooting at them, the bullets seemingly curve around the target. In order to hit the target, you have to aim behind the target which is a little awkward since usually you aim ahead of it to compensate for bullet velocity. The problem is especially noticeable when you aim off and on the target while running, you can see the bullets bending left and right but never actually on the target. It’s as if the target has a magnetic field or something lol. The module works perfect when you’re standing still but when I tested it in-game, people were complaining about the inaccuracies of the guns and that’s when I realized about the problem. I was wondering if this was an intentional feature or if there is any way to solve this? I know for a fact the problem isn’t the bullet inheriting the player’s velocity.
Are you using the example gun? Check the fire method. There’s code that makes bullets inherit the velocity of the player, which includes walking.
FastCast v12.0.0 Released
This one comes with a pretty big API change. No new features worth noting, but a lot of organization in the code was done. See Changelist - FastCast API for more information.
This is a major version update (11 => 12) for a good reason. The API of the Fire
method has been completely changed to use a new data table containing most cast information. The API documentation goes over exactly how this works, so please have a look at it! https://etithespirit.github.io/FastCastAPIDocs/fastcast-objects/fcrayinfo/ (The example gun should help too.)
Edit: This also comes with some writing improvements to the API to make some stuff more clear and provide examples for more complicated things (right now that’s just the pierce function, may be more in the future depending on feedback).
I am using the example gun, I haven’t changed the scripts at all except remove the bottom part that makes sure not to set the angle above 180 and changed the firerate to 0.1, bullets per shot to 1, and bullet spread angle to 0. https://gyazo.com/8e4e86fde7a1f80eee7f69a2fcacdbbb You can clearly see the dummy doing some kind of witchcraft that makes the bullets curve around it. I also removed the part that makes the bullet inherit the player velocity to see if that made any difference but the bullet still curves around the target.
That is such a strange issue… The bullets are flying straight (the curvature is just a really neat illusion).
It’s related to some form of client/server lag apparently. To test this, I modified the client code to fire the event with only the mouse’s position in 3D space, then I calculate the direction on the serverside. This resolved the problem. I’ll release the example gun with this change.
Edit: New version of the example gun is live. Thanks for the report.
I have made a tutorial on how to use the example gun! Check it out here: https://youtu.be/KuDfxCEaeyQ
I plan to do another Major version increment here in about a day. Version 13.0.0 will be another rewrite of the module, but rather than to do things over, it will be to port it to the Luau strong type system.
Version 13 is LIVE.
- The module is now compliant with Luau strong type limitations. (See Changelist - FastCast API)
- The long comment at the top of the module has been updated with new links since I deleted the old wiki.
Please note: While the system in Roblox is done, the type checker in script editors is NOT done. There are a number of type mismatch errors + missing type errors that are false and can be safely ignored.
The module using nonstrict formatting will no longer be supported nor developed past the release of v13.
Hi! I ran into a problem today where it errors when I try to do FiringCaster.CastTerminated:Wait()
See code here:
local function FireHook(side,fireType)
local DataTable = {}
if side == CustomEnums.GrappleSideType.Left then
DataTable = Left
end
if side == CustomEnums.GrappleSideType.Right then
DataTable = Right
end
local FireSide
if side == CustomEnums.GrappleSideType.Left then
FireSide = "Left"
end
if side == CustomEnums.GrappleSideType.Right then
FireSide = "Right"
end
if fireType == CustomEnums.GrappleFireType.Fire then
local mousePos = Mouse.Hit.p
local FirePoint = FirePoints[FireSide .. "FirePoint"]
if FirePoint then
local TargetCF = CFrame.new(FirePoint.WorldPosition,mousePos)
local FiringCaster = DataTable.Caster
if FiringCaster then
DataTable.Cast = FiringCaster:Fire(TargetCF.Position,TargetCF.LookVector,375,CastParams)
DataTable.Activated = true
local EndPoint = DataTable.Cast.RayInfo.CosmeticBulletObject:WaitForChild("End")
local Beam = Instance.new("Beam")
Beam.Texture = "rbxassetid://5670527105"
Beam.FaceCamera = true
Beam.Attachment0 = FirePoint
Beam.Attachment1 = EndPoint
Beam.LightInfluence = 0
Beam.TextureMode = Enum.TextureMode.Static
Beam.TextureSpeed = 7.5
Beam.Parent = FirePoint
DataTable.Objects[#DataTable.Objects + 1] = Beam
DataTable.Objects[#DataTable.Objects + 1] = DataTable.Cast.RayInfo.CosmeticBulletObject
local ActiveCast = FiringCaster.CastTerminating:Wait()
DataTable.Activated = false
if not DataTable.ManualTerminated then
ActiveCast.RayInfo.CosmeticBulletObject.Anchored = true
end
end
end
end
if fireType == CustomEnums.GrappleFireType.Cancel then
if DataTable.Activated then
DataTable.Cast:Terminate()
DataTable.ManualTerminated = true
end
for i,v in ipairs(DataTable.Objects) do
if v:IsA("Instance") then v:Destroy() end
end
end
end
The error is:
14:49:02.483 - Workspace.ProjectInfiniti.ODMGear:164: attempt to call a nil value
line 164 is FiringCaster.CastTerminating:Wait()
EDIT: I just checked the Signal module, and doesnt really look like it has a Wait() function (if so, can you add the wait function)
I’ve just released a patch including Signal:Wait()
among some other fixes.
https://etithespirit.github.io/FastCastAPIDocs/changelog/#fastcast-1302
ok thanks! great help for my project
I’ve just released 13.0.4 because I realize that I accidentally caused a memory leak in signal objects, so I’ve fixed that. You might wanna upgrade.
https://etithespirit.github.io/FastCastAPIDocs/changelog/#fastcast-1304