This might be a garbage idea, but if you want something that is not super accurate, but fairly simple, you could have an invisible ‘cone’ shape for the shotgun damage area, and just flash that part into the world when the gun is fired, and any collisions with players are put into a table and the cone is removed. Then for each player, fire one ray, to make sure they are not behind a wall, or behind each other, etc…, removing them from the list if they are not hit by the ray. Then, loop through the targets in order from closest to the shooter to farthest, and give a random percentage of the damage, based on how close the target is to the gun source., For instance, suppose there is a total of 30 pts of damage that can be done, like 30 pieces of buck shot. if someone is half way through the cone, they may have a chance to get hit by 60% of that 30 pts, lets say they take 10 pts of damage, well, that only leaves 20 more points left for farther away targets, but at a lesser chance of hitting, due to their distance. Sorry if this doenst make much sense, the idea just sort of jumped out at me.
This is what I use for my shotgun spread. It gives a circular pattern, although it is more dense around the centre. This is an intended feature for mine, so most pellets go where you’re aiming, but you can mess around with it yourself.
There are more efficient ways to calculate it, but I was just throwing it together and it’s not like this is running often lol.
“dir” is the initial aiming vector, and “spread” is the maximum spread size in radians.
local ang = CFrame.Angles(0,0,math.pi * 2 * math.random()) * CFrame.Angles(math.random() * spread,0,0)
dir = (CFrame.new(Vector3.new(),dir) * ang).lookVector