- What is the issue? Include screenshots / videos if possible!
For context, I’m using FastCast: Redux.
Whenever i fire while ADS/Holding Mousebutton2, the ray that has been casted goes the opposite direction i want it to, This issue applies to every gun that i have scripted.
here’s a video that will hopefully summarize my issue:
External MediaHere’s my projectile module:
local RepStorage = game:GetService("ReplicatedStorage")
local Assets = RepStorage:WaitForChild("Assets")
local Events = RepStorage:WaitForChild("Events")
local ParticleEmitter = require(RepStorage.Dependencies.ParticleEmitter)
local FastCast = require(RepStorage.Dependencies:WaitForChild("FastCastRedux"))
FastCast.VisualizeCasts = true
local Caster = FastCast.new()
local behavior = Caster.newBehavior()
local module = {}
local BloodSounds = {
"rbxassetid://3802437361",
"rbxassetid://3092866899",
"rbxassetid://255661850",
"rbxassetid://4752240968",
}
local function BulletHole(raycastresult)
local part = Instance.new("Part")
part.Size = Vector3.new(.5,.5,.5)
part.Transparency = 1
part.Name = "BulletHole"
part.CFrame = CFrame.new(raycastresult.Position,raycastresult.Position-raycastresult.Normal)
part.CFrame = CFrame.lookAt(part.Position, part.Position * raycastresult.Normal)
part.Anchored = true
part.Parent = workspace.fastcast
ParticleEmitter:emit(5, part.CFrame, 15, 5, 0.1, 3, true)
end
local function bloodeffect(hit)
for i, v in pairs(Assets.Blood:GetChildren()) do
if v:IsA("ParticleEmitter") then
task.spawn(function()
local blood = v:Clone()
local bloodSFX = Instance.new("Sound")
bloodSFX.SoundId = BloodSounds[math.random(#BloodSounds)]
blood.Parent = hit
bloodSFX.Parent = hit
blood:Emit()
bloodSFX:Play()
task.wait(2)
blood:Destroy()
bloodSFX:Destroy()
end)
end
end
end
local function RayHit(cast, raycastResult, segmentVelocity, cosmeticBulletObject)
local hit = raycastResult.Instance
local character = hit:FindFirstAncestorOfClass("Model") or hit.Parent
local humanoid = character:FindFirstChildOfClass("Humanoid", 5)
if humanoid and hit then
bloodeffect(hit)
if humanoid.Health ~= 0 then
Events:WaitForChild("Damage"):FireServer(cast.modTable.Damage,humanoid)
end
else
BulletHole(raycastResult)
end
cosmeticBulletObject:Destroy()
end
local function LengthChanged(cast, lastPoint, rayDir, rayDisplacement, segmentVelocity, cosmeticBulletObject)
local bulletLength = cosmeticBulletObject.Size.Z / 2 -- This is used to move the bullet to the right spot based on a CFrame offset
local baseCFrame = CFrame.new(lastPoint, lastPoint + rayDir)
cosmeticBulletObject.CFrame = baseCFrame * CFrame.new(0, 0, -(rayDisplacement - bulletLength))
end
local function Reflect(surfaceNormal, bulletNormal)
return bulletNormal - (2 * bulletNormal:Dot(surfaceNormal) * surfaceNormal)
end
function CanRayPierce(cast, rayResult, segmentVelocity)
local hits = cast.UserData.Hits
if (hits == nil) then
cast.UserData.Hits = 1
else
cast.UserData.Hits += 1
end
if (cast.UserData.Hits > cast.modTable.MaxHits) then
return false
end
local hit = rayResult.Instance
local character = hit:FindFirstAncestorOfClass("Model") or hit.Parent
local humanoid = character:FindFirstChildOfClass("Humanoid", 5)
if humanoid and hit then
bloodeffect(hit)
if humanoid.Health ~= 0 then
Events:WaitForChild("Damage"):FireServer(cast.modTable.Damage,humanoid)
end
else
BulletHole(rayResult)
end
if hit then
if hit.Size.Z <= 1 and not hit:IsA("Terrain") then
return true
end
end
--[[
-- This function shows off the piercing feature literally. Pass this function as the last argument (after bulletAcceleration) and it will run this every time the ray runs into an object.
-- Do note that if you want this to work properly, you will need to edit the OnRayPierced event handler below so that it doesn't bounce.
if material == Enum.Material.Plastic or material == Enum.Material.Ice or material == Enum.Material.Glass or material == Enum.Material.SmoothPlastic then
-- Hit glass, plastic, or ice...
if hitPart.Transparency >= 0.5 then
-- And it's >= half transparent...
return true -- Yes! We can pierce.
end
end
return false
--]]
end
function RayTerminated(cast)
cast.RayInfo.CosmeticBulletObject:Destroy()
end
function OnRayPierced(cast, raycastResult, segmentVelocity, cosmeticBulletObject)
local position = raycastResult.Position
local normal = raycastResult.Normal
if math.random() < cast.modTable.RicochetChance then
local newNormal = Reflect(normal, segmentVelocity.Unit)
cast:SetVelocity(newNormal * segmentVelocity.Magnitude)
end
cast:SetPosition(position)
end
function module:Fire(player, mousepos, origin, WeaponData, isreplicated)
local Direction = (mousepos-origin).Unit
local modTable = {
player = player;
Damage = WeaponData["Damage"];
MaxHits = WeaponData["MaxHits"];
RicochetChance = WeaponData["RicochetChance"]
--// add stuff here
}
local CastParams = RaycastParams.new()
CastParams.FilterType = Enum.RaycastFilterType.Exclude
CastParams.FilterDescendantsInstances = {workspace.CurrentCamera, player.Character, workspace.fastcast, workspace.CurrentCamera:FindFirstChildOfClass("Model")}
behavior.RaycastParams = CastParams
behavior.HighFidelityBehavior = FastCast.HighFidelityBehavior.Default
behavior.CosmeticBulletTemplate = Assets.Tracers.Tracer
behavior.CosmeticBulletContainer = workspace.fastcast
behavior.AutoIgnoreContainer = false -- We already do this! We don't need the default value of true (see the bottom of this script)
behavior.MaxDistance = WeaponData["Bullet_Distance"]
behavior.Acceleration = WeaponData["Bullet_Acceleration"]
Caster:Fire(origin, Direction, WeaponData["Bullet_Speed"], behavior,modTable)
if WeaponData["CanPierce"] then
behavior.CanPierceFunction = CanRayPierce
end
if not isreplicated then
Events:WaitForChild("Projectile"):FireServer(mousepos, origin,workspace.CurrentCamera:FindFirstChildOfClass("Model"))
end
--print("Fired")
end
Caster.RayHit:Connect(RayHit)
Caster.RayPierced:Connect(OnRayPierced)
Caster.LengthChanged:Connect(LengthChanged)
Caster.CastTerminating:Connect(RayTerminated)
return module
– workspace.CurrentCamera:FindFirstChildOfClass(“Model”) - Referring to the viewmodel instance.
- What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I disabled the CanRayPierce function, but didn’t work. and there was no solution on the Devforum.
Any help is appreciated, Cheers!