Untitled
unknown
plain_text
a year ago
23 kB
19
Indexable
-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local TransportModule = require(game.ServerScriptService.Game.TransportModule)
local DrillModule = require(game.ServerScriptService.Game.DrillModule)
local FactoryModule = require(game.ServerScriptService.Game.FactoryModule)
local TurretModule = require(game.ServerScriptService.Game.TurretModule)
local MachineModule=require(game.ServerScriptService.Game.MachineModule)
local UnitFactoryModule=require(game.ServerScriptService.Game.UnitFactoryModule)
local GameStart=game.ReplicatedStorage.BindableEvents.StartGame
local RemoteEvents = ReplicatedStorage:WaitForChild("RemoteEvents")
local PlaceBuildingEvent = RemoteEvents:WaitForChild("PlaceBuilding")
local MachinesFolder = game.ServerStorage.Machines
local DataManger=require(game.ServerScriptService.Data.DataManager)
-- === Helper Functions (Server-Side) ===
local Dictionary = {
["Conveyor"] = {
Class = "Conveyors",
Hp = 30,
Cost = {["Copper"] = 2}
},
["Router"] = {
Class = "Routers",
Hp = 50,
Cost = {["Copper"] = 20,
["Tin"]=10
}
},
["Junction"] = {
Class = "Junctions",
Hp = 75,
Cost = {["Copper"] = 30,
["Silicon"]=5
}
},
["Basic Drill"] = {
Class = "Drills",
Hp = 100,
Cost = {["Copper"] = 50}
},
["Advanced Drill"] = {
Class = "Drills",
Hp = 175,
Cost = {
["Copper"] = 60,
["Graphite"] = 30,
["Bronze"] = 20
}
},
["Silicon Smelter"] = {
Class = "Factories",
Hp = 250,
Cost = {
["Copper"] = 60,
["Graphite"] = 35,
["Tin"]=30,
["Bronze"]=30
}
},
["Graphite Press"] = {
Class = "Factories",
Hp = 225,
Cost = {
["Copper"] = 75,
["Sand"] = 80
}
},
["Iron Furnace"] = {
Class = "Factories",
Hp = 250,
Cost = {
["Copper"] = 80,
["Graphite"] = 40,
["Raw Iron"] = 60,
["Bronze"]=20
}
},
["Bronze Alloy Forge"] = {
Class = "Factories",
Hp = 250,
Cost = {
["Copper"] = 100,
["Graphite"] = 50,
["Tin"] = 40
}
},
["Aluminium Smelter"] = {
Class = "Factories",
Hp = 500,
Cost = {
["Copper"] = 125,
["Graphite"] = 60,
["Iron"] = 40,
["Silicon"]=30
}
},
["Steel Manufactuary"] = {
Class = "Factories",
Hp = 650,
Cost = {
["Copper"] = 200,
["Graphite"] = 100,
["Iron"] = 75,
["Bronze"] = 50,
["Aluminium"]=40
}
},
["Basic Turret"] = {
Class = "Turrets",
Hp = 150,
Cost = {
["Copper"] = 75,
["Graphite"] = 25
}
},
["Machine Gun Turret"] = {
Class = "Turrets",
Hp = 200,
Cost = {
["Copper"] = 150,
["Graphite"] = 45,
["Iron"]=25
}
},
["Basic Anti Air Turret"] = {
Class = "Turrets",
Hp = 175,
Cost = {
["Bronze"]=40,
["Graphite"] = 50,
["Aluminium"] = 30
}
},
["Advanced Anti Air Turret"] = {
Class = "Turrets",
Hp = 250,
Cost = {
["Graphite"] =75,
["Aluminium"] = 40,
["Iron"]=40
}
},
["Mortar"] = {
Class = "Turrets",
Hp = 750,
Cost = {
["Steel"]=50,
["Graphite"] = 175,
["Iron"]=100
}
},
["Sniper"] = {
Class = "Turrets",
Hp = 450,
Cost = {
["Steel"]=35,
["Bronze"]=150,
["Iron"]=100
}
},
["Basic Tank Factory"] = {
Class = "Unit Factories",
Hp = 750,
Cost = {
["Silicon"] = 150,
["Graphite"] = 100,
["Iron"]=75
}
},
["Basic Drone Factory"] = {
Class = "Unit Factories",
Hp = 750,
Cost = {
["Silicon"] = 150,
["Aluminium"] = 60,
["Graphite"] = 75
}
},
["Basic Support Factory"] = {
Class = "Unit Factories",
Hp = 750,
Cost = {
["Silicon"] = 200,
["Bronze"] = 75,
["Graphite"] = 80
}
}
}
local function IsOfferdable(Player,Building)
local CoreModule=require(game.ServerScriptService.Game.CoreModule)
local Core
local Team=Player.Team
for _,core in ipairs(workspace.Cores:GetChildren()) do
if CoreModule.Cores[core] then
if CoreModule.Cores[core].Team==Team then
Core=core
break
end
end
end
local BuildingCost=Dictionary[Building].Cost
local Affordable=true
for Item,Count in pairs(BuildingCost) do
if CoreModule.Cores[Core].Storage[Item]<Count then
Affordable=false
end
end
if Affordable then
for Item, Amount in pairs(BuildingCost) do
CoreModule.Cores[Core].Storage[Item]-=Amount
local UpdateClient=game.ReplicatedStorage.RemoteEvents.UpdateStorageDisplay
for _, Player in ipairs(Players:GetChildren()) do
if Player.Team==Team then
UpdateClient:FireClient(Player,Item,CoreModule.Cores[Core].Storage[Item])
end
end
end
end
return Affordable or true
end
local OreDictionary=
{
["Copper"]=1,
["Coal"]=1,
["Sand"]=1,
["Bauxite"]=2,
["Tin"]=1,
["Raw Iron"]=2
}
local Drill_Stats = {
["Basic Drill"] =1,
["Advanced Drill"] =2,
}
local Colors={
["Blue"]="Lapis",
["Red"]="Really red"
}
local function SpecialConditions(modelName, cframe)
local Model= MachinesFolder:FindFirstChild(modelName):Clone()
Model.Parent=workspace
if Model:IsA("BasePart") then
Model.CFrame=cframe
else Model:SetPrimaryPartCFrame(cframe)
end
local Pass=false
if Dictionary[modelName].Class=="Drills" then
local drill=Model
local drillSize = Model.Size
local drillPosition = Model.Position
local gridWidth = drillSize.X / 3
local gridDepth = drillSize.Z / 3
local startX = drillPosition.X - (drillSize.X / 2) + 1.5
local startZ = drillPosition.Z - (drillSize.Z / 2) + 1.5
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {workspace.Ores}
raycastParams.FilterType = Enum.RaycastFilterType.Include
local oreCounts = {}
for x = 0, gridWidth - 1 do
for z = 0, gridDepth - 1 do
local checkX = startX + (x * 3)
local checkZ = startZ + (z * 3)
local origin = Vector3.new(checkX, (drill.Position+Vector3.new(0,5,0)).Y, checkZ)
local result = workspace:Raycast(origin, Vector3.new(0, -9, 0), raycastParams)
--visualizeRay(origin, Vector3.new(0, -9, 0))
if result and result.Instance then
local OreName=result.Instance.Name
if Drill_Stats[modelName]>=OreDictionary[OreName] then
Pass=true
end
end
end
end
else
Pass=true
end
Model:Destroy()
if not Pass then
end
return Pass
end
function CheckCollision(Model)
local Size
local Position
if Model:IsA("Model") then
Size=Model.Base.Size
Position=Model.PrimaryPart.CFrame.Position
else
Size=Model.Size
Position=Model.Position
end
local gridWidth = Size.X/3
local gridDepth = Size.Z/3
local startX = Position.X - Size.X/2 + 1.5
local startZ = Position.Z - Size.Z/2 + 1.5
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {workspace.Machines,workspace.Units,workspace.Cores}
raycastParams.FilterType = Enum.RaycastFilterType.Include
for x = 0, gridWidth-1 do
for z = 0, gridDepth-1 do
local checkX = startX + x*3
local checkZ = startZ + z*3
local origin = Vector3.new(checkX, (Position+Vector3.new(0,9,0)).Y, checkZ)
local result = workspace:Raycast(origin, Vector3.new(0, -30, 0), raycastParams)
--visualizeRay(origin,Vector3.new(0, -30, 0))
if result then
return true
end
end
end
return false
end
-- Function to validate placement (simplified for now)
local function isValidPlacement(player, modelName, targetCFrame)
if not player or not modelName or not targetCFrame then
warn("Invalid arguments received for placement.")
return false, "Invalid arguments."
end
local originalModel = MachinesFolder:FindFirstChild(modelName)
if not originalModel then
warn(player.Name .. " tried to place non-existent model: " .. modelName)
return false, "Invalid item."
end
local playerPos = player.Character and player.Character.HumanoidRootPart and player.Character.HumanoidRootPart.Position
if playerPos and (playerPos - targetCFrame.Position).Magnitude > 50 then -- Max 50 studs from player
return false, "Too far from player."
end
return true, "Placement valid." -- If all checks pass
end
local function Build_Conveyor(Build)
if workspace.Machines:FindFirstChild("Conveyors")==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines
folder.Name="Conveyors"
end
Build.Parent=workspace.Machines["Conveyors"]
TransportModule.Conveyors.add(Build)
end
local function Build_Router(Build)
if workspace.Machines:FindFirstChild("Routers")==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines
folder.Name="Routers"
end
Build.Parent=workspace.Machines["Routers"]
TransportModule.Routers.add(Build)
end
local function Build_Junction(Build)
if workspace.Machines:FindFirstChild("Junctions")==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines
folder.Name="Junctions"
end
Build.Parent=workspace.Machines["Junctions"]
TransportModule.Junctions.add(Build)
end
local function Build_Drill(Build)
if workspace.Machines:FindFirstChild(Build.Name)==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines
folder.Name="Drills"
end
if workspace.Machines.Drills:FindFirstChild(Build.Name)==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines.Drills
folder.Name=Build.Name
end
Build.Parent=workspace.Machines.Drills[Build.Name]
DrillModule.Drills.add(Build)
end
local function Build_Factory(Build)
if workspace.Machines:FindFirstChild(Build.Name)==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines
folder.Name="Factories"
end
if workspace.Machines.Factories:FindFirstChild(Build.Name)==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines.Factories
folder.Name=Build.Name
end
Build.Parent=workspace.Machines.Factories[Build.Name]
FactoryModule.Factories.add(Build)
end
local function Build_Turret(Build)
if workspace.Machines:FindFirstChild(Build.Name)==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines
folder.Name="Turrets"
end
if workspace.Machines["Turrets"]:FindFirstChild(Build.Name)==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines.Turrets
folder.Name=Build.Name
end
Build.Parent=workspace.Machines.Turrets[Build.Name]
TurretModule.Turrets.add(Build,MachineModule.Machines[Build].Team)
end
local function Build_Unit_Factory(Build)
if workspace.Machines:FindFirstChild("Unit Factories")==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines
folder.Name="Unit Factories"
end
if workspace.Machines["Unit Factories"]:FindFirstChild(Build.Name)==nil then
local folder=Instance.new("Folder")
folder.Parent=workspace.Machines["Unit Factories"]
folder.Name=Build.Name
end
Build.Parent=workspace.Machines["Unit Factories"][Build.Name]
Build["Recipe Changer"].Enabled=true
UnitFactoryModule.UnitFactories.add(Build,MachineModule.Machines[Build].Team)
end
local function snapToGrid(position, gridSize, objectSize)
if objectSize==nil then return end
local halfObjectSizeX = objectSize.X / 2
local halfObjectSizeZ = objectSize.Z / 2
-- Calculate the corner's position relative to the grid origin (0,0)
local snappedCornerX = math.round((position.X - halfObjectSizeX) / 3) * 3
local snappedCornerZ = math.round((position.Z - halfObjectSizeZ) / 3) * 3
-- The final center position is the snapped corner plus half the object's size
local snappedX = snappedCornerX + halfObjectSizeX
local snappedZ = snappedCornerZ + halfObjectSizeZ
local Y=objectSize.Y/2
return Vector3.new(snappedX, Y+0.5, snappedZ)
end
local GameStarted=false
GameStart.Event:Connect(function()
GameStarted=true
end)
-- === Main Event Listener ===
PlaceBuildingEvent.OnServerEvent:Connect(function(player, modelName, targetCFrame)
--print(player.Name .. " requested to place " .. modelName .. " at " .. tostring(targetCFrame.Position))
if not GameStarted then return end
if workspace.Cores:FindFirstChild(player.Team.Name)==nil then
return
end
local DataManager=require(game.ServerScriptService.Data.DataManager)
--[[
if DataManager.Profiles[player].Data.Research[modelName]==false then
print(player.Name .. " Didnt research: " .. modelName)
return
end]]
local success, errorMessage = isValidPlacement(player, modelName, targetCFrame)
local temp=game.ServerStorage.Machines:FindFirstChild(modelName):Clone()
local Size
if game.ServerStorage.Machines[modelName]:IsA("Model") then
Size=game.ServerStorage.Machines[modelName]:GetExtentsSize()
else
Size=game.ServerStorage.Machines[modelName].Size
end
if temp:isA("BasePart") then
temp.CFrame=targetCFrame
else
temp.PrimaryPart.CFrame=targetCFrame
end
if success and SpecialConditions(modelName,targetCFrame) and not CheckCollision(temp) then
if IsOfferdable(player,modelName) then
local originalModel = MachinesFolder:FindFirstChild(modelName)
if originalModel then
if true and game.ReplicatedStorage.BindableEvents:FindFirstChild("MachinePlacedByPlayer") then
game.ReplicatedStorage.BindableEvents.MachinePlacedByPlayer:Fire(player,modelName)
end
local newInstance = originalModel:Clone()
newInstance.Name = originalModel.Name
if newInstance:IsA("BasePart") then
newInstance.CFrame = targetCFrame
else
newInstance:SetPrimaryPartCFrame(targetCFrame)
for _, part in ipairs(newInstance:GetChildren()) do
if part:FindFirstChild("ColorPart") then
part.BrickColor=BrickColor.new(Colors[player.Team.Name])
end
end
end
local name=newInstance.Name
local Class=Dictionary[name].Class
local HP=Dictionary[name].Hp
MachineModule.Machines.add(player.Team,newInstance,Class,name,HP)
if name =="Conveyor" then
Build_Conveyor(newInstance)
elseif name=="Junction" then
Build_Junction(newInstance)
elseif name=="Router" then
Build_Router(newInstance)
elseif MachineModule.Machines[newInstance].Type=="Drills" then
Build_Drill(newInstance)
elseif MachineModule.Machines[newInstance].Type=="Factories" then
Build_Factory(newInstance)
elseif MachineModule.Machines[newInstance].Type=="Turrets" then
Build_Turret(newInstance)
elseif MachineModule.Machines[newInstance].Type=="Unit Factories" then
Build_Unit_Factory(newInstance)
else
warn("No type found")
end
-- TODO: Deduct resources/money from player here
if newInstance:IsA("BasePart") then
newInstance.Anchored=true
else
newInstance.PrimaryPart.Anchored=true
end
local SendMachines = game.ReplicatedStorage.RemoteEvents.SendPlayerMachines
local SentMachine=nil
--print(player.Name .. " successfully placed " .. modelName)
else
warn("Server couldn't find original model '" .. modelName .. "' in MachinesFolder.")
end
end
end
temp:Destroy()
end)
local function SpecialDestroying(Machine)
local MachineModule=require(game.ServerScriptService.Game.MachineModule)
local TransportModule=require(game.ServerScriptService.Game.TransportModule)
if Machine.Name=="Conveyor" then
local Conveyor=Machine
local origin = Conveyor.Position + Vector3.new(0, 1, 0)
local item_find_params = RaycastParams.new()
item_find_params.FilterDescendantsInstances = {workspace.Items}
item_find_params.FilterType = Enum.RaycastFilterType.Include
local machine_find_params = RaycastParams.new()
machine_find_params.FilterDescendantsInstances = {workspace.Machines}
machine_find_params.FilterType = Enum.RaycastFilterType.Include
local Directions = {
{
{Origin=Vector3.new(0,0,-1.7), End=Vector3.new(0,0,3.4)},
{Origin=Vector3.new(-1.7,0,0), End=Vector3.new(3.4,0,0)}
}
}
for i=0,4 do
local rotation = Conveyor.CFrame.Rotation
for _, list in Directions do
for _,detectionGroup in list do
local Origin = detectionGroup.Origin
local Direction = detectionGroup.End
local item = workspace:Raycast(origin+Origin, Direction, item_find_params)
if item and item.Instance then
item.Instance:Destroy()
end
end
end
end
end
end
local DestroyMachines = game.ReplicatedStorage.RemoteEvents.DestroyMachines
local UpdateDisplayRemoteEvent= game.ReplicatedStorage.RemoteEvents.UpdateStorageDisplay
DestroyMachines.OnServerEvent:Connect(function(plr, Machines)
local MachineModule=require(game.ServerScriptService.Game.MachineModule)
local CoreModule=require(game.ServerScriptService.Game.CoreModule)
local Core
for _, core in ipairs(workspace.Cores:GetChildren()) do
if core and CoreModule.Cores[core] then
if CoreModule.Cores[core].Team==plr.Team then
Core=core
end
end
end
local Cost
for _, Machine in pairs(Machines) do
if Machine.Parent:IsA("Model") then
Machine=Machine.Parent
end
Cost=Dictionary[Machine.Name].Cost
for item,amount in pairs(Cost) do
CoreModule.Cores[Core].Storage[item]+=math.floor(amount/2) --Refund Multiplier
for _, Player in ipairs(Players:GetChildren()) do
if Player.Team==plr.Team then
UpdateDisplayRemoteEvent:FireClient(Player,item,CoreModule.Cores[Core].Storage[item])
end
end
end
SpecialDestroying(Machine)
MachineModule.Machines.Destroy(Machine)
end
end)
---------------------------------------------------------------------
--Proximity Handler
local ProximityPromptService=game:GetService("ProximityPromptService")
local SendUnitFactoryRecipe=game.ReplicatedStorage.RemoteEvents.SendUnitFactoryRecipes
ProximityPromptService.PromptTriggered:Connect(function(Prompt,Player)
SendUnitFactoryRecipe:FireClient(Player,Prompt.Parent)
end)
local SelectRecipe=game.ReplicatedStorage.RemoteEvents.SelectRecipe
SelectRecipe.OnServerEvent:Connect(function(player,UnitFactory,UnitName)
local UnitFactoryModule=require(game.ServerScriptService.Game.UnitFactoryModule)
UnitFactoryModule.UnitFactories.SelectRecipe(UnitFactory,UnitName)
end)
--------------------------------
local RequestTargetableMachines =game.ReplicatedStorage.RemoteEvents.RequestTargetableMachines
local UnitsModule=require(game.ServerScriptService.Game.UnitsModule)
RequestTargetableMachines.OnServerEvent:Connect(function(player)
local SendTargetableMachines=game.ReplicatedStorage.RemoteEvents.RecieveTargetableMachines
local Targets={}
for unit, _ in pairs(UnitsModule.Units) do
if typeof(unit)=="Instance" and UnitsModule.Units[unit].Team~=player.Team then
table.insert(Targets,unit)
end
end
local MachineModule=require(game.ServerScriptService.Game.MachineModule)
for Machine, _ in pairs(MachineModule.Machines) do
if typeof(Machine)=="Instance" and Machine then
if MachineModule.Machines[Machine].Team~=player.Team then
table.insert(Targets,Machine)
end
end
end
local CoreModuele=require(game.ServerScriptService.Game.CoreModule)
for Core, _ in pairs(CoreModuele.Cores) do
if typeof(Core)=="Instance" and Core then
if not(CoreModuele.Cores[Core].Team==player.Team) then
table.insert(Targets,Core)
end
end
end
SendTargetableMachines:FireClient(player,Targets)
end)
local CommandRemoteEvent=game.ReplicatedStorage.RemoteEvents.CommandUnits
CommandRemoteEvent.OnServerEvent:Connect(function(plr,units,target)
for _, unit in ipairs(units) do
if unit.parent then
if typeof(target)=="Instance" and target.Parent:IsA("Model") then
target=target.Parent
end
UnitsModule.Units[unit].CommandedTarget=target
end
end
end)
-------------------------------------------------------------------------------------------
--Send Info
local SendInfo=game.ReplicatedStorage.RemoteEvents.SendMachineUIinfo
local RequestInfo=game.ReplicatedStorage.RemoteEvents.RequestMachineUIinfo
RequestInfo.OnServerEvent:Connect(function(player: Player, Machine:Instance)
local Info={}
local MachineModule=require(game.ServerScriptService.Game.MachineModule)
if Machine==nil or MachineModule.Machines[Machine]==nil then
return
end
if MachineModule.Machines[Machine].Team~=player.Team then
return
end
Info.Visible=true
Info.Health=MachineModule.Machines[Machine].HP
Info.MaxHP=MachineModule.Machines[Machine].MaxHP
Info.Drill=false
Info.Machine=Machine.Name
Info.Ammo=false
Info.UnitCooldown=false
if Machine:FindFirstAncestor("Factories") then
local FactoryModule=require(game.ServerScriptService.Game.FactoryModule)
local Storage={}
for Item, Count in FactoryModule.Factories[Machine].current do
Storage[Item]=Count
end
for Item, Count in FactoryModule.Factories[Machine].output_storage do
Storage[Item]=Count
end
Info.Storage=Storage
end
if Machine:FindFirstAncestor("Drills") then
local DrillModule=require(game.ServerScriptService.Game.DrillModule)
Info.Drill=true
Info.DrillItem=DrillModule.Drills[Machine].ore
Info.DrillSpeed=1/DrillModule.Drills[Machine].cooldown
local Storage={}
Storage[DrillModule.Drills[Machine].ore]=DrillModule.Drills[Machine].storage
Info.Storage=Storage
end
if Machine:FindFirstAncestor("Turrets") then
local TurretModule=require(game.ServerScriptService.Game.TurretModule)
Info.Ammo=true
Info.AmmoCount=TurretModule.Turrets[Machine].Ammo_Storage
Info.AmmoMax=TurretModule.Turrets[Machine].Stats.Max_Ammo
end
if Machine:FindFirstAncestor("Unit Factories") then
local UnitFactoryModule=require(game.ServerScriptService.Game.UnitFactoryModule)
if UnitFactoryModule.UnitFactories[Machine].Recipe then
Info.UnitCooldown=true
Info.RecipeTime=UnitFactoryModule.UnitFactories[Machine].Recipe.ProcessingTime
Info.UnitTime=UnitFactoryModule.UnitFactories[Machine].Cooldown
Info.Unit=UnitFactoryModule.UnitFactories[Machine].Recipe.Output
local Storage={}
for Item, Count in UnitFactoryModule.UnitFactories[Machine].InputStorage do
Storage[Item]=Count
end
Info.Storage=Storage
end
end
SendInfo:FireClient(player,Info)
end)
game.ReplicatedStorage.BindableEvents.WaveToServer.Event:Connect(function(Wave,win)
for _,player in Players:GetChildren() do
local DoubleGold=DataManger.Profiles[player].Data.DoubleGold
local Multiplier=1
if DoubleGold then
Multiplier=2
end
local Gold=math.pow(Wave,1.3)*20*Multiplier
Gold=math.round(Gold/10)
Gold*=10
game.ReplicatedStorage.RemoteEvents.Lost:FireClient(player,Wave,Gold,DoubleGold,win)
DataManger.AddGold(player,Gold)
DataManger.AddWavesWon(player,Wave)
end
end)
game.ReplicatedStorage.RemoteEvents.ReturnToLobbyRequest.OnServerEvent:Connect(function(player)
local TeleportService=game:GetService("TeleportService")
TeleportService:TeleportAsync(95592715929300,{player})
end)Editor is loading...
Leave a Comment