Sway Effect (TDS)

So, if you play tower defense simulator, you know that when you move your mouse when you have a tower, it moves in a sway movement, I made something similar to this Character Sway Effect which I customized and made it so that it works with regular rigs, here is the script, put it in starterplayer, then characterscripts `-

- LocalScript inside StarterPlayerScripts
local RunService = game:GetService("RunService")
local RS = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local UIS = game:GetService("UserInputService")

local plr = game.Players.LocalPlayer
local mouse = plr:GetMouse()
local Gui = plr.PlayerGui

local Towers = RS.Objects.Towers

local TowerToSpawn = nil

local mainPart = workspace.Rig.HumanoidRootPart
mainPart.Anchored = true
mainPart.CanCollide = false
mainPart.CanQuery = false
mainPart.CanTouch = false
mainPart.Size = Vector3.new(1,1,1)
mainPart.Parent = workspace

local oldCFrame = mainPart.CFrame

local rad = math.rad

local Camera = workspace.CurrentCamera

local function MouseRaycast(Blacklist)
	local MousePosition = UIS:GetMouseLocation()

        local MouseRay = Camera:ViewportPointToRay(MousePosition.X, MousePosition.Y)

        local raycastParams = RaycastParams.new()

	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	raycastParams.FilterDescendantsInstances = Blacklist

	local RaycastResult = workspace:Raycast(MouseRay.Origin, MouseRay.Direction * 1000, raycastParams)

	return RaycastResult
end

local MouseRaycastRig = MouseRaycast({workspace.Rig})

-- tweakable variables
local tweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Sine) -- the more time, the slower and smoother. 
local offset = Vector3.new(0,1.6,0) -- can be used if reaching too high or too low

local sway = 30 -- sway multiplier

RunService.Heartbeat:Connect(function()
	if TowerToSpawn then
		local Result = MouseRaycast({workspace.Rig})
		if Result and Result.Instance then
			if not mouse.Target then return end -- return if mouse is in the sky or smth
			local cFrame = CFrame.new(Result.Position.X, Result.Position.Y + offset.Y, Result.Position.Z)

			for i, v in ipairs(TowerToSpawn:GetChildren()) do
				if v:IsA("BasePart") then
					v.CollisionGroup = "Tower"
				end
			end

			if cFrame ~= oldCFrame then -- If the part has actually moved
				local m = cFrame.Position - oldCFrame.Position -- magnitude
				local angle = CFrame.Angles(rad(m.Z*sway),0,rad(-m.X*sway))
				cFrame *= angle

				TweenService:Create(mainPart,tweenInfo,{CFrame = cFrame}):Play()
				oldCFrame = cFrame
			end 
		end
	end
end)

local function AddPlaceHolderTower(Name)
	local TowerExists = Towers:FindFirstChild(Name)
	if TowerExists then
		TowerToSpawn = TowerExists:Clone()
		TowerToSpawn.Parent = workspace.Towers
		
		for i, v in ipairs(workspace.Rig:GetDescendants()) do
			if v:IsA("BasePart") then
				v.CollisionGroup = "Tower"
			end
		end
	end
end

Gui.ScreenGui.Frame.TowerButton.Activated:Connect(function()
	AddPlaceHolderTower("Rig")
end)

UIS.InputBegan:Connect(function(Input, Processed)
	if Processed then
		return
	end
	
	if TowerToSpawn then
		if Input.UserInputType == Enum.UserInputType.MouseButton1 then
			game:GetService("ReplicatedStorage").Remotes.SpawnTower:FireServer(TowerToSpawn.Name, Vector3.new(mouse.Hit.Position.X, 1.8, mouse.Hit.Position.Z), TowerToSpawn.HumanoidRootPart.Rotation)
		end
	end
end)`

There are other parts which are included and, because I am stupid, I put the original in scripting support :nerd_face: now, the next script is for the spring mechanic which is the quenty spring mechanic Spring and I recommend watching gnomecode on YT cuz umm, I changed a bit of the next code from his video for this one so umm, yeah, put this is replicated storage and make it module script

local RS = game:GetService("ReplicatedStorage")

local Tower = {}

function Tower.Spawn(Plr, Name, cframe, rotation)
	local TowerExists = game:GetService("ReplicatedStorage").Objects.Towers:FindFirstChild(Name)
	local RigClone = TowerExists:Clone()
	RigClone.HumanoidRootPart.Position = cframe
	RigClone.HumanoidRootPart.Rotation = rotation
	RigClone.Parent = workspace.Towers
	RigClone.HumanoidRootPart:SetNetworkOwner(nil)
	RigClone.Name = "Clone"
	
	for i, v in ipairs(workspace.Rig:GetDescendants()) do
		if v:IsA("BasePart") then
			v.CollisionGroup = "Tower"
		end
	end
end

RS.Remotes.SpawnTower.OnServerEvent:Connect(Tower.Spawn)

return Tower

I like to be organized so I put stuff in folders so put a folder in ReplicatedStorage and call it Remotes specifically for the noobs, and also put SpawnEvent inside Remotes, then make a Modules folder in ReplicatedStorage and name it Modules, again specifically, and then you put in the module I just said and the Spring module and name spring module, Spring, along with naming the one I just said, Tower. Now you should have a working product with all you need is to put in a script in serverscriptservice with the following code and boom, your done.

local Tower = require(game:GetService("ReplicatedStorage").Modules.Tower)

Also just add screengui in starterpack, then a frame with the size 1,0,1,0, and a textbutton called, “TowerButton” If you want the whole thing in a pack, just get it here see ya :smiley:

Sway Effect

I changed the effect so that it runs with a restricted area and might be the only update I make for this other than the errors I fix from ya’ll telling me about bugs on this forum page.

2 Likes

Took me like 1 day to make the placement system working but now the rotation which is the fun part :smiley:

Good job

Make sure to edit this post and change the category to #resources:community-resources, otherwise it will get taken down for being in the wrong category. Development Discussion is for talking about subjects, not publishing resources

there we go, I changed it to be under that category

with some moderation on the otherhand :roll_eyes:

also forgot to mention but umm, if you get the model, there will be - 1 on the cFrame value, just a heads up. :smiley: