###### tags: `Guide To Contibuting` # Citadel Codebase Specifications (REQUIRED) ## For an up to date list, check [CONTRIBUTING.md](https://github.com/Citadel-Station-13/Citadel-Station-13/CONTRIBUTING.md) in our codebase, .github folder. ## Specifications You are expected to follow these specifications in order to make everyone's lives easier. It'll save both your time and ours, by making sure you don't have to make any changes and we don't have to ask you to. Thank you for reading this section! <!-- stolen from tg, we should have this, because clean code good --> ### All BYOND paths must contain the full path (i.e. absolute pathing) DM will allow you nest almost any type keyword into a block, such as: ```DM datum datum1 var varname1 = 1 varname2 static varname3 varname4 proc proc1() code proc2() code datum2 varname1 = 0 proc proc3() code proc2() ..() code ``` The use of this is not allowed in this project as it makes finding definitions via full text searching next to impossible. The only exception is the variables of an object may be nested to the object, but must not nest further. The previous code made compliant: ```DM /datum/datum1 var/varname1 var/varname2 var/static/varname3 var/static/varname4 /datum/datum1/proc/proc1() code /datum/datum1/proc/proc2() code /datum/datum1/datum2 varname1 = 0 /datum/datum1/datum2/proc/proc3() code /datum/datum1/datum2/proc2() ..() code ``` ### Type paths must begin with a / eg: `/datum/thing`, not `datum/thing` ### Datum type paths must began with "datum" In DM, this is optional, but omitting it makes finding definitions harder. ### Do not use text/string based type paths It is rarely allowed to put type paths in a text format, as there are no compile errors if the type path no longer exists. Here is an example: ```DM //Good var/path_type = /obj/item/baseball_bat //Bad var/path_type = "/obj/item/baseball_bat" ``` ### Tabs, not spaces You must use tabs to indent your code, NOT SPACES. (You may use spaces to align something, but you should tab to the block level first, then add the remaining spaces) ### No magic numbers or strings This means stuff like having a "mode" variable for an object set to "1" or "2" with no clear indicator of what that means. Make these #defines with a name that more clearly states what it's for. For instance: ```DM /datum/proc/do_the_thing(thing_to_do) switch(thing_to_do) if(1) (...) if(2) (...) ``` There's no indication of what "1" and "2" mean! Instead, you'd do something like this: ```DM #define DO_THE_THING_REALLY_HARD 1 #define DO_THE_THING_EFFICIENTLY 2 /datum/proc/do_the_thing(thing_to_do) switch(thing_to_do) if(DO_THE_THING_REALLY_HARD) (...) if(DO_THE_THING_EFFICIENTLY) (...) ``` This is clearer and enhances readability of your code! Get used to doing it! ### Use our time defines The codebase contains some defines which will automatically multiply a number by the correct amount to get a number in deciseconds. Using these is preffered over using a literal amount in deciseconds. The defines are as follows: * SECONDS * MINUTES * HOURS This is bad: ````DM /datum/datum1/proc/proc1() if(do_after(mob, 15)) mob.dothing() ```` This is good: ````DM /datum/datum1/proc/proc1() if(do_after(mob, 1.5 SECONDS)) mob.dothing() ```` ### Operators #### Spacing (this is not strictly enforced, but more a guideline for readability's sake) * Operators that should be separated by spaces * Boolean and logic operators like &&, || <, >, ==, etc (but not !) * Bitwise AND & * Argument separator operators like , (and ; when used in a forloop) * Assignment operators like = or += or the like * Operators that should not be separated by spaces * Bitwise OR | * Access operators like . and : * Parentheses () * logical not ! Math operators like +, -, /, *, etc are up in the air, just choose which version looks more readable. #### Use * Bitwise AND - '&' * Should be written as ```bitfield & bitflag``` NEVER ```bitflag & bitfield```, both are valid, but the latter is confusing and nonstandard. * Associated lists declarations must have their key value quoted if it's a string * WRONG: list(a = "b") * RIGHT: list("a" = "b")