Quick-menu:
The Goals
I want to make it so the scripts shown will produce an output, specifically in a way that puts the shields in front of the player. I also want the shields to space themselves appropriately based on the distance, equally if the shields are significant, relative to the radius of the shields.
For example; if the shields are close to the player, it would take around 7-8 shields before they begin spacing themselves equally, as by then the amount of shields basically covers the player’s entire horizontal vulnerabilities.
Another example; if there are only four shields, they have an offset to make sure the shields are covering an equal degree on either side. The shields are also oriented as the player’s rotation.
The Problem
I am not really good at dealing with this range of math, and so far all it’s been doing is orienting incorrectly, and also isn’t spacing like I wished.
I’ve tried various kinds of math arrangements and methods, most of which I can’t remember precisely. There is probably a better way to do this, so if so, I would like some help on understanding better techniques.
Code
“ShieldScript” Script in StarterPlayer.StarterCharacterScripts
local Players = game:GetService("Players")
local sev = Instance.new("RemoteEvent", script.Parent)
sev.Name = "ShieldInteractionBridge"
local shields = {}
local function createShieldInstance()
local plate = Instance.new("Part", workspace)
plate.Color = Color3.new(0,1,1)
plate.Material = Enum.Material.Neon
plate.Size = Vector3.new(2.1, 5, .2)
plate.CanCollide = false
plate.Locked = true
table.insert(shields, plate)
plate:SetNetworkOwner(Players:GetPlayerFromCharacter(script.Parent))
sev:FireAllClients("add", plate)
end
local function removeShieldInstance(plate)
local id = table.find(shields, plate)
assert(id, "Shield is not part of the Shields table.")
table.remove(shields, id)
sev:FireAllClients("remove", plate)
end
wait(5)
for n=1,10 do
createShieldInstance()
end
“ClientShieldMovement” LocalScript in StarterPlayer.StarterCharacterScripts
local plr = game:GetService("Players").LocalPlayer
local TS = game:GetService("TweenService")
local info = TweenInfo.new(.3, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out)
local sev = script.Parent:WaitForChild("ShieldInteractionBridge")
local shields = {}
local config = {
rotation = 0,
radius = 15,
spacing = 1,
evenSpacing = false
}
local testval = Instance.new("NumberValue", script.Parent)
testval.Name = "radius"
testval.Value = 12
testval.Changed:Connect(function(val)
config.radius = val
end)
local function onServerInteracting(mode, ...)
local args = {...}
if mode == "add" then
-- 1: Shield
table.insert(shields, args[1])
elseif mode == "remove" then
-- 1: Shield
table.remove(shields, table.find(shields, args[1]))
end
end
sev.OnClientEvent:Connect(onServerInteracting)
-- IxGamerXL: This is the part that I need help with
game:GetService("RunService").Heartbeat:Connect(function(dt)
local space = 1 - (math.deg(math.pi - math.log(config.radius+1, math.pi*2))/180)
local angleInc = config.spacing * space --(math.pi * 2) / #shields
local extraInc = #shields% 2 == 0 and angleInc / 2 or 0
local primary = script.Parent.PrimaryPart
local pcf,po = primary.CFrame,primary.Orientation
for i,plate in ipairs(shields) do
local radian = math.rad(po.Y) + angleInc * i - math.pi/2 - (angleInc * (#shields/2))
local ax = math.sin(radian)*config.radius
local az = math.cos(radian)*config.radius
TS:Create(plate, info, {
CFrame = CFrame.new(pcf.Position)
* CFrame.new(Vector3.new(ax,0,az), Vector3.zero)
--* CFrame.Angles(0,math.rad(po.Y),0)
}):Play()
plate.AssemblyLinearVelocity = Vector3.zero
plate.AssemblyAngularVelocity = Vector3.zero
end
end)
There are no other instances that are required for this to work, just make sure this Script and LocalScript are both put in StarterPlayer.StarterCharacterScripts
.
End Note
Have a solution you have tested and confirmed to work? Please share the new code to me! Just make sure the code isn’t cryptic or confusing, as I will want to understand the correct operations for later use.