Untitled

mail@pastecode.io avatar
unknown
lua
a year ago
6.3 kB
8
Indexable
Never
-- Services

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

--ReplicatedItems

local Modules = ReplicatedStorage:WaitForChild("Modules")
local Events = ReplicatedStorage:WaitForChild("Events")
local EnemyModels = ReplicatedStorage:WaitForChild("EnemyModels")

--ModuleScripts

local Waves = require(Modules:WaitForChild("Waves"))
local EnemyDataBase = require(Modules:WaitForChild("EnemyDataBase"))
local EnemyInfoDataBase = require(Modules:WaitForChild("EnemyInfoDataBase"))

--Events

local EnemySyncer = Events:WaitForChild("EnemySyncer")

--Workspace Varibales

local Nodes = workspace.Nodes
local SpawnCFrame = Nodes[0].CFrame

--FunctionsDefine

--MathFunctions

local function Lerp(a, b, t)
	return a + (b - a) * t
end

local function QuadraticBezier(t, p0, p1, p2)
	local l1 = Lerp(p0, p1, t)
	local l2 = Lerp(p1, p2, t)
	local quad = Lerp(l1, l2, t)
	return quad
end


--Enemy Functions

local function AddEnemyToDataBase(EnemyName)
	local Table = {}
	for ItemName, Item in pairs(EnemyInfoDataBase[EnemyName]) do
		Table[ItemName] = Item
		if ItemName == "CFrame" then
			Table["CFrame"] = SpawnCFrame
		elseif ItemName == "XOffset" then
			Table["XOffset"] = Random.new():NextNumber(-1, 1)
		end
	end
	table.insert(EnemyDataBase, Table)
end

local function InitiateDataBaseTurningSequence(EnemyData)
	EnemyData.Turning = true
	task.wait(((Nodes[EnemyData.Node].Position - Nodes[EnemyData.Node].Mid.Position).Magnitude / EnemyData.Speed) - EnemyData.TurningHelper)
	EnemyData.CFrame = Nodes[EnemyData["Node"]].Mid.CFrame
	task.wait((Nodes[EnemyData.Node].Mid.Position - Nodes[EnemyData.Node].End.Position).Magnitude / EnemyData.Speed)
	EnemyData.Turning = false

	EnemyData.CFrame = Nodes[EnemyData["Node"]].End.CFrame
	EnemyData.Node += 1
end

local function InitiateGraphicalTurningSequenceLoop(DeltaTime, EnemyID, EnemyData, Time, Distance, Position, LookPosition, Node0, Node1, Node2, EndCFrame)
	EnemyData.CornerStatus += DeltaTime

	Time = EnemyData.CornerStatus / Distance
	if Time > 1 then
		workspace.Enemies:WaitForChild(EnemyID).PrimaryPart.CFrame = EndCFrame
		EnemyData.CornerStatus = 0
		RunService:UnbindFromRenderStep("CornerTurn"..EnemyID)
	else
		Position = QuadraticBezier(Time, Node0, Node1, Node2)
		LookPosition = QuadraticBezier(Time + 0.001, Node0, Node1, Node2)

		if workspace.Enemies:FindFirstChild(EnemyID) then
			workspace.Enemies:WaitForChild(EnemyID).PrimaryPart.CFrame = CFrame.lookAt(Position, LookPosition)
		end
	end
end

local function InitiateGraphicalTurningSequence(EnemyID, EnemyData)
	workspace.Enemies[EnemyID].PrimaryPart.CFrame = EnemyData.CFrame

	local Distance = ((Nodes[EnemyData["Node"]].Position - Nodes[EnemyData["Node"]].Mid.Position).Magnitude / EnemyData["Speed"]) - EnemyData.TurnerHelper + (Nodes[EnemyData["Node"]].Mid.Position - Nodes[EnemyData["Node"]].End.Position).Magnitude / EnemyData["Speed"]
	local Time = 0
	local Position = 0
	local LookPosition = 0
	local Node = EnemyData["Node"]

	local Node0 = Nodes[Node].Position + (workspace.Enemies[EnemyID].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(EnemyData.XOffset, EnemyData.YOffset, 0)).Position - workspace.Enemies[EnemyID].PrimaryPart.Position)
	local Node1 = Nodes[Node].Mid.Position + (workspace.Enemies[EnemyID].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(EnemyData.XOffset, EnemyData.YOffset, EnemyData.XOffset)).Position - workspace.Enemies[EnemyID].PrimaryPart.Position)
	local Node2 = Nodes[Node].End.Position + (workspace.Enemies[EnemyID].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(0, EnemyData.YOffset, EnemyData.XOffset)).Position - workspace.Enemies[EnemyID].PrimaryPart.Position)


	local EndCFrame = Nodes[Node].End.CFrame + (workspace.Enemies[EnemyID].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(0, EnemyData.YOffset, EnemyData.XOffset)).Position - workspace.Enemies[EnemyID].PrimaryPart.Position)

	RunService:BindToRenderStep("CornerTurn"..EnemyID, 0, function(DeltaTime)
		InitiateGraphicalTurningSequenceLoop(DeltaTime, EnemyID, EnemyData, Time, Distance, Position, LookPosition, Node0, Node1, Node2, EndCFrame)
	end)
end

local function LoopThroughEnemies(OverallDeltaTime)
	for EnemyID, EnemyData in pairs(EnemyDataBase) do
		if EnemyData["Turning"] == false then
			EnemyData.CFrame = Nodes
			EnemyData.CFrame = Nodes[EnemyData["Node"]].CFrame:ToWorldSpace(CFrame.new(0, 0,(EnemyData.CFrame.Position - Nodes[EnemyData["Node"]].Position).Magnitude - (EnemyData.Speed * OverallDeltaTime)))
			if Nodes[EnemyData["Node"]].CFrame:ToWorldSpace():ToObjectSpace(EnemyData.CFrame).Position.Z <= 0 then
				EnemyData.TurningHelper = (Nodes[EnemyData["Node"]].CFrame:ToWorldSpace():ToObjectSpace(EnemyData.CFrame).Position.Z * -1) / EnemyData.Speed
				EnemyData.CFrame = Nodes[EnemyData["Node"]].CFrame
				coroutine.wrap(InitiateDataBaseTurningSequence)(EnemyData)
				coroutine.wrap(InitiateGraphicalTurningSequence)(EnemyID, EnemyData)
			end
			workspace.Enemies[EnemyID].PrimaryPart.CFrame = EnemyData.CFrame + (workspace.Enemies[EnemyID].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(EnemyData.XOffset, EnemyData.YOffset, 0)).Position - workspace.Enemies[EnemyID].PrimaryPart.Position)
		end
	end
end

local function DoNeedenThings(Enemy, EnemyName)
	local AnimationController = Instance.new("AnimationController", Enemy)
	local Animator = Instance.new("Animator", AnimationController)
	local Animation = Enemy:WaitForChild("Walk")
	local Track = Animator:LoadAnimation(Animation)
	Track:Play()
end


--WaveLoop

local function WaveSequence()
	for WaveCount, WaveData in pairs(Waves) do
		for EnemyName, EnemyData in pairs(WaveData.Enemies) do
			task.wait(EnemyData.StartDelay)
			for	Count=1, EnemyData.Amount do
				AddEnemyToDataBase(EnemyName)
				local Enemy = EnemyModels[EnemyName]:Clone()
				Enemy.Parent = workspace.Enemies
				Enemy.Name = #EnemyDataBase
				DoNeedenThings(Enemy)
				if EnemyData.Interval ~= 0 then
					task.wait(EnemyData.Interval)
				end
			end
		end
	end
end

--EnemyMover

RunService:BindToRenderStep("ClientLoop", 0, LoopThroughEnemies)


--WaveLoop
EnemySyncer.OnClientEvent:Connect(function()
	coroutine.wrap(WaveSequence)()
end)