Hi,
So recently I have been attempting to make a Weapon System with Bullet Delays, and potentially Bullet Drop if I want to create a more realistic game, but a problem I have with it is that I want to have my visual effects relect where the rays are going in their direction, rather than a random spreading angle applied to them, which can lead to some weird results. I’m also having the issue of properly managing every ray, and how they will be calulated during the Bullet Delays.
The Module I created utilizes OOP (Object Oriented Programming) to structure its data, and fire its code.
Contents of Firing Event
self.FireEvent = Fire.OnServerEvent:Connect(function(Player, Position: Vector3)
local Params = RaycastParams.new(); -- Params
Params.FilterDescendantsInstances = {Player.Character};
Params.FilterType = Enum.RaycastFilterType.Exclude;
local Root = Player.Character.PrimaryPart; -- Part to Raycast From
-- This is done to avoid the ray going through objects in front of it
local Distance = Player:DistanceFromCharacter(Position); -- Distance from point fired at
local TimeDelay = Distance/self.ProjectileSpeed; -- Time it will take to get there
if self.RequireAmmo then -- Checks if the Weapon uses Ammo or not
self.Config:SetAttribute("Ammo",math.clamp(self.Config:GetAttribute("Ammo") - 1, 0, self.Config:GetAttribute("MaxAmmo")));
end
utl.GlobalEffectEvent:FireAllClients(self.Tool, Position, self.ProjectileSpeed, self.ProjectileCount, self.ProjectileSpread, TimeDelay, self.Sounds)
-- Plays Weapon Effects such as Bullet Trails, and Muzzle.
print(`Ping...`); -- Start...
local DelayedPositions = {}; -- Collects all Bullets being fired, and their
-- respective directions if spread is accounted for
for i = 1, self.ProjectileCount do -- iterates for every projectile
local x = self.Random:NextNumber(-self.ProjectileSpread, self.ProjectileSpread)
local y = self.Random:NextNumber(-self.ProjectileSpread, self.ProjectileSpread)
local Direction = CFrame.new(Root.Position, Position) * CFrame.Angles(math.rad(x), math.rad(y), 0)
DelayedPositions[i] = {Root.Position, Direction.LookVector * self.Range};
end
task.delay(TimeDelay, function() -- Bullet Delay
warn(`PONG! ({TimeDelay})`); -- End!
for i = 1, #DelayedPositions do -- iterate through data
local Items = DelayedPositions[i]; -- get for raycast
local Result = workspace:Raycast(Items[1], Items[2], Params) -- raycast
if Result then
local Humanoid = self:VerifyTarget(Result.Instance) -- Verifies a target
if Humanoid then
local Damage = self.Damage.X * (self:IsHeadshot(Result.Instance) and self.Damage.Y or 1) -- Calulates the damage output
self:DealDamage(Humanoid, Damage); -- Deal Damage;
end
end
end
end)
end)
Contents of Client Event
PlayEffects.OnClientEvent:Connect(function(Tool, Position, Speed, Count, Spread, Time, Sounds)
local Handle = Tool.Handle;
local Points = Handle.Points;
Points.Pointer.WorldCFrame = CFrame.lookAt(Points.Pointer.WorldPosition, Position) -- Point towards location to launch effects
-- this is so the effects will go towards
Points.Pointer.BulletEffect.Speed = NumberRange.new(Speed); -- Bullet Speed
Points.Pointer.BulletEffect.Lifetime = NumberRange.new(Time); -- Effect will die after it reaches its location
Points.Pointer.BulletEffect.SpreadAngle = Vector2.new(Spread, Spread) -- Currently how the Spreading of Effects works
Points.Pointer.BulletEffect:Emit(Count) -- Varies depending on Bullet Count
Points.Muzzle.MuzzleEffect:Emit(10) -- Fires Muzzle Effect
--/ This part isnt important to the topic, but you can view it
local SoundId = Sounds[math.random(1, #Sounds)] -- Random Sound to pick
local Sound = Instance.new("Sound"); -- new Instance
Sound.SoundId = `rbxassetid://{SoundId}`; -- apply soundId
Sound.Parent = Tool.Handle; -- place in Handle
Sound:Play() -- Play
task.wait(1) -- wait a bit
Debris:AddItem(Sound, Sound.TimeLength); -- kill
end)
I’m looking for an efficient way to mange it, as I feel my current solution to create and execute these effects is inefficient and could use some work to do so.
I am also not looking for people who just paste code without explaining it, just a general explanation on what I should do and then an optional code example to explain further.
If possible, how would I go about doing this?