Hey, i decided to make artillery system, but there is a problem, i have 3 options to choose from how to do it:
Have all server scripts inside each cannon model
Have lightweight server script inside each cannon model that will require OOP classes from server script service to create actual cannon
Have all scripts inside server script service
For now i use second aproach because it’s easier to make statement effects (i rotate few parts on server because making it on client would be less effective) or i can go for more invidual/customizable cannons, still i wanted to ask which one is best
In my project I have a total of 0 scripts outside of (ServerScriptService + 2 folders inside starterplayer). A lot of scripters that are better than me do this too. Edit: Talking about active scripts of course. Plenty of scripts in ReplicatedStorage.
For loops and event triggers in a thread should handle any system, or at least a part of the system (for example for a mining system you can have 1-2 threads for the mining process itself and then 1 script for the spawning of the mine’s minerals). If the artillity weapons act differently, I would use if statements to handle each one. Connect a bindable/remote function/event and pass the name or ID of the weapon when they fire or become active . So all of the weapons are handled by thread in a script. You could then do the same with another script that is for upgrading of the weapons.
You can do use a module script for the stat math, and insert the values like Damage and RateOfFire inside of the weapon model. Often number/int values. That way it will account for upgrades easily. A table in a script would need to be updated and scoped in a messy way, so using physical values for most of your stats / weapon information is what I prefer.
Really the only approach that is realistic with ease of hacking tools for Roblox.
May as well consider local content prototyping till it’s set up for anti-hacking also.
?.. I meant I agree. No the client can not see the server scripts. Unless they are on the client…
They can see and mess with everything on the client…
When you run your program in the studio there are a few folders you can not open while it’s running. Them are total server folders. Anything in there cannot be touched.
The trick is to get everything that could hurt the game if hacked inside them.
local scripts fire:remotes to talk to the boss.
Still option 3 makes that i can’t have big customizability even with systems that support it, as every cannon, also main script in cannon only initializes this cannon depending on what type is it
It may just be my small brain here, but I don’t know what you mean.
You can set up a timer for each weapon.
Now I get what you mean if you have complex weapons like a champion’s in League of Legends. You should definitely make either a function or a script for each weapon that has a special, however the call to attack with the weapon should still optimally be handled by 1 event, and then send it sends you to the script/function for that weapon. And even then about half of the weapon can probably still be handled by the main thread.
--Define gun
local gun = character:FindFirstChildWhichIsA("Tool") --A different bool ensures this doesn't mistake it for another tool.
if not gun then return end
local gunClass = gun:FindFirstChild("GunClass")
--Define wait for reload sound
local wait1 = nil
local wait2 = nil
if gunClass.Value == "Class1" then
wait1 = 0.3
end
wait2 = 1 - wait1
--Wait for a time determined by fireRate
task.wait(wait1/fireRate.Value)
playGunSound("GunReloadSound",gun,soundAssetReload,baseVolumeValueReload,playbackspeedReload)
task.wait(wait2/fireRate.Value)
--Reset values
canShoot.Value = true
isShooting.Value = false
Ok again, in setup script per model scenario, i can set up easy debounces, this mean i don’t need to store them inside objects, but rather inside script inside my cannon, also i can require my classes to get functionality, and control them directly from model , this way i have easy maintanance over specific model
If i’ll go for one script scenario, i can only call Cannon:Shoot() or Cannon:Load() also i can only create new cannon object only via pattern, this mean i can’t make
local cannon = Cannon.new("Cannon", "Iron Breech", "Wooden wheel")
If you don’t want to make values inside of the objects, you could make a grand table in the main-script approach. This is again, not something you’d usually do, because it makes things less easy to comprehend and read from: Instead of using FindFirstChild on the weapon, you’d instead determine a path in the table. However once you have set up the necessary events for the table, you can theoretically store everything inside of it without needing any physical values.
I don’t understand what you mean by not being able to do local cannon = Cannon.new("Cannon", "Iron Breech", "Wooden wheel").
It looks like a function call that creates a cannon based on its class properties, which you could set up in a module script and simply look at the cannon’s name in workspace to determine its class. If you want to get real crazy about it, you could make the name some kind of code that determines its properties, and then use string functions to decypher it.
hmmmm, ok i’ll definetively try, but last question is, if using script per cannon only to require few modules and eventually determine some functions is really bad for performance?
Well it will generally have the same peformance no matter what approach you take, because there will be an equal amount of threads running. Beyond that, Idk peformance well. Bindable events shouldn’t delay by any noticable amount, but if you’re worried about them, you could make a function per cannon instead of a script per cannon. Each function would practically be its own script that starts when it’s called at the 1 event that triggers when a weapon requests to fire.
Now Idk how weapons are fired, but assuming it’s player input (if it’s player and input and then it autofires, you can just make a loop inside of the thread it’s firing in).
This is poorly written pseudo-code.
local functions = {
class1 = function()
--code for this weapon
end
}
WeaponFireEvent.OnServerEvent:Connect(function(plr,weapon)
functions[weapon:FindFirstChild("Class").Value}()
end)