# Goonstation Code Guide
* Don't use `goto`. Bad.
* Don't use the `:` operator to override type safety checks. Instead, cast the variable to the proper type.
## Procs To Use
* Use `SPAWN_DBG()` instead of `spawn()`
* Use `TIME` instead of `world.timeofday`
* Bitflags (`&`) - Write as `bitfield & bitflag`
### Defines to use
#### Time Defines
The codebase contains some defines (e.g. `SECONDS`) which will automatically multiply a number by the correct amount to get a number in deciseconds. Using these is preferred over using a literal amount in deciseconds.
#### SI Units
The codebase also has defines for other SI units, such as `WATTS`. There are also SI unit prefixes for use, such as `MILLI`. These should be used whenever you're dealing with a quantity that's a SI unit. If you're using a derived unit, add its formula to the defines. These can be chained like so: `100 MILLI WATTS` or `1 KILO METER`.
### No magic numbers
Don't use numbers that have no explanation behind them. Instead, it's reccomended that you either put it into a const variable, a local file #define, or a global #define. For example,
Do this instead:
#define DO_THING_CORRECT 0
#define DO_THING_OTHER 1
### Use early returns
We don't want dozens of nesting levels, don't enclose a proc inside an if block if you can just return on a condition instead.
if (baz == 420)
if (!foo || bar)
if (baz == "error_code")
### Spaces after control statements
See: `if(x)` vs `if (x)`
Nobody cares about this. This is heavily frowned upon for changing with little to no reason.
### Abstract types and typesof
Some types exist just as a parent and should never be created in-game (e.g. `/obj/item`). Mark those using the `ABSTRACT_TYPE(type)` macro. You can check if a type is abstract using the `IS_ABSTRACT(type)` macro.
To get a list of all concrete (non-abstract) subtypes of a type you should use `concrete_typesof(type)`, the result is cached so no need to store it yourself. (As a consequence please `.Copy` the list if you want to make changes to it locally.) Proper usage of `ABSTRACT_TYPE` + `concrete_typesof` is preferred to using `typesof` and `childrentypesof` *usually* though exceptions apply.
If you want to filter the results of `concrete_typesof` further (e.g. by the value of a var or by a blacklist) consider using `filtered_concrete_typesof(type, filter)`. `filter` is a proc that should return 1 if you want to include the item. Again, the result is cached (so the `filter` proc should not depend on outisde variables or randomness).
var/is_cool = 0
name = "Uncool Hat"
name = "Cool hat"
is_cool = 1
var/obj/item/hat/hat = hat_type
return pick(filtered_concrete_typesof(/obj/item/hat, /proc/is_hat_cool))
See `_stdlib/_types.dm` for details.
## Whack BYOND shit
### Startup/Runtime trade-offs with lists and the "hidden" init() proc
First, read the comments in [this BYOND thread](http://www.byond.com/forum/post/2086980?page=2#comment19776775).
There are two key points there:
* Defining a list in the variable's definition calls a hidden proc: init(). If you have to define a list at startup, do so in New() and avoid the overhead of a second call (Init() and then New())
* It also consumes more memory to the point where the list is actually required, even if the object in question may never use it!
Remember: although this trade-off makes sense in many cases, it doesn't cover them all. Think carefully about your addition before deciding if you need to use it.
### for-in-to loops
`for (var/i = 1, i <= some_value, i++)` is the standard way to write a for loop in most languages, but DM's `for(var/i in 1 to some_value)` syntax is actually faster in its implementation.
So, where possible, it's advised to use DM's syntax. (Note: the to keyword is inclusive, so it automatically defaults to replacing `<=`; if you want `<` then you should write it as `1 to some_value-1`).
**Be Warned:** if either `some_value` or `i` changes within the body of the for (underneath the `for(...)`) or if you are looping over a list and changing the length of the list then you cannot use this type of for-loop!
### Default Return (`.`)
Like other languages in the C family, DM has a `.` or "dot" operator, used for accessing variables/members/functions of an object instance. For example:
var/mob/M = foo
However, DM also has a dot variable, accessed just as `.` on its own, defaulting to a value of null. Now, what's special about the dot operator is that it is automatically returned (as in the return statement) at the end of a proc, provided the proc does not already manually return (e.g. `return x`)
With `.` being present in every proc, we use it as a temporary variable. However, the `.` operator cannot replace a typecasted variable - it can hold data any other var in DM can, it just can't be accessed as one, although the `.` operator is compatible with a few operators that look weird but work perfectly fine, such as: `.++` for incrementing `.`'s value.
### global vs static variable keyword
DM has a variable keyword, called `global`. This var keyword is for vars inside of types. For instance:
/mob/var/global/foo = TRUE
This does **not** mean that you can access it everywhere like a global var. Instead, it means that that var will only exist once for all instances of its type, in this case that var will only exist once for all mobs - it's shared across everything in its type. (Much more like the keyword `static` in other languages like PHP/C++/C#/Java)
Isn't that confusing?
There is also an undocumented keyword called `static` that has the same behavior as global but more correctly describes DM's behavior. Therefore, always use `static` instead of `global` in variables, as it reduces surprise when reading code.
## Useful Things
### VSCode Debugger
### Debugging Overlays
### Target Dummy
* You can spawn in a target dummy (`/mob/living/carbon/human/tdummy`) to more easily test things that do damage - they have the ass day health percent and damage popups visible even if your build isn't set to ass day.
### Signals and Components
* ninjanomnom from TG has written up a [useful primer](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) on signals and components. Most of the stuff there applies, although elements do not exist in this codebase.