StdLib

by Ter13
Essential standardized features for use in any DM project.
ID:2199585
 
STDLIB contains features that I believe are necessary for development of BYOND games. Standard definitions to make your life easier, helper functions, and structural overrides that allow you to more quickly and cleanly make a game.

Including StdLib:

STDLib's functions need to know certain things about your project before you can include it properly. DO NOT copy/paste StdLib into your project. DO use the library inclusion checkbox to include the project.



If you include and compile StdLib into a blank project, you may be presented with a number of warnings. These can be suppressed by #defining STDLIB_NOWARN in your DME file, but this is not recommended. Each of these warnings is important to address.

These issues can be addressed by defining TILE_WIDTH, TILE_HEIGHT, and FPS in your project. They should be the same as the values you supply to world.fps and world.icon_size. Optionally, if you plan on using client.fps, you should also define VFPS to the value you want your client FPS set to. This should all be done in the DME file for your project, above the auto-generated #include block, but below the auto-generated #define block as shown here:






Standard definitions:

TILE_WIDTH defaults to 32. - how wide STDLib thinks your tile size is.
TILE_HEIGHT defaults to 32. - how tall STDLib thinks your tile size is.
FPS defaults to 25. - The default FPS STDLib thinks your world runs at.
VFPS defaults to FPS. - The default FPS STDLib thinks your client runs at.
TICK_LAG defaults to 10/FPS
FRAME_LAG defaults to 10/VFPS

The following definitions are for saving timehacks for libraries dependent on StdLib. Currently EffectLib and CooldownLib both utilize these flags for their various saved objects and values.

PRESERVE_NONE defalts to 0. - Mark for removal when loaded.
PRESERVE_WORLDTIME defaults to 1. - Mark for updating timestamps to local time.
PRESERVE_REALTIME defaults to 2. - Mark this object for updating timestamps to local time, taking into account the real time between when the object was saved and when it was loaded.




Rounding functions:

floor(x) returns the integer floor of the the supplied value (rounds left)
ceil(x) returns the integer ceil of the supplied value (rounds right)
round_in(x) returns the whole integer nearer 0 from the supplied value (rounds toward zero)
round_out(x) returns the whole integer further from 0 from the supplied value (rounds away from zero)
clamp(v,l,h) returns the value such that l<=v<=h
decimal(x) returns only the decimal component of the supplied value.
to_places(x,places) clips a decimal number to a set number of decimal places.
sign(x) returns the sign of the supplied value as either 1 for positive, -1 for negative, or 0 for exactly 0.




Typecheck functions:

isatom(ref) checks if a value is a type of atom
ismovable(ref) checks if the value is a type of movable atom
islist(ref) checks if the value is a list
isclient(ref) checks if the value is a client




Coordinate functions:

screen2coord(client,screen_loc) parses screen loc and returns a list(x,y) in pixel offsets from the bottom-left of the screen. This expects tile:pixel values, and does not support anchors. This is meant to simplify getting the screen loc as returned from mouse proc parameters.

screen2world(client,screen_loc) parses screen loc and returns a list(x,y) in global pixel coordinates from the bottom-left of the map. This expects tile:pixel values, and does not support anchors. This is meant to simplify getting the screen loc as returned from mouse proc parameters.




Direction functions:

ang2dir(ang) gets the direction nearest the angle, where 0 is East, and all directions are clockwise.

dir2ang(dir) returns the angle of a direction where EAST is 0, NORTH is 90, etc.

dir2text(dir) returns the lowercase name of a direction.

text2dir(str) returns a direction from the lowercase name.

point2dir(x,y) Gets the direction of a point offset in arbitrary units from an imaginary origin. This does not use angles, merely whether there is a north/south, or east/west component to the offset.




Trigonometry functions:

atan2(x,y) gets the angle of an offset in arbitrary units from an imaginary origin.
tan(ang) tangent
arctan(ang) arctangent
cot(ang) cotangent
arccot(ang) arccotangent
sec(ang) secant
arcsec(ang) arcsecant
csc(ang) cosecant
arccsc(ang) arccosecant




Initialization events:

global.initialized this is set to 0 by default, and 1 after world.New() runs.

world.PostInit() this is called after world/New() is called. By default, it sets initialized and loops over all objects that have been marked with post-initialization behavior.

datum.post_init If this is true, when a datum is created, this object has post-init behavior, and will call datum.PostInit() after the world has been initialized, or immediately upon creation if the world has already been initialized.

datum.PostInit() This is called after world initialization if the datum has the post_init variable marked as true.

INIT_EVENT(evname) defines a new initialization event sequence that happens before world initialization.
HOOK_EVENT(evname) overrides an existing initialization event sequence that happens before world initialization.

These functions exist to allow you to more reliably define what happens before and after world/New() without requiring you to pollute the global namespace and restructure your code to deal with BYOND compiler order bugs.

Do not use INIT_EVENT more than once on the same event name.

singleton_init(type) loops through the types of a supplied type path, looks for any values with a non-null id variable, and adds them to a list associated by their id. This is used for quickly initializing singleton datums/atoms from which to draw behavior from. Because of this, init_event datums now have an unused id variable, just to suppress runtime errors.




Datum additions:

/overlay obj - a quick prototype container for overlay atoms. Allows you to define more data about overlays quickly and easily.
/underlay obj - a quick prototype container for underlay atoms. Pretty much idential to overlay objects. Only included for semantic completion.

datum.Destroy() This function exists to allow you to garbage collect objects that are no longer needed without calling for an explicit deletion. Any hanging references an object prototype maintains should be checked and removed here using the circular reference sweep pattern.
client.Destroy() This is to keep client in line with datums.




Mob additions:

save_worldtime This variable is set to the world's current time when a mob is written to a savefile.
save_realtime This variable is set to the world's realtime when a mob is written to a savefile.
>still requires you config a static tile height/width and fps rather than getting these from world.var natively.

still requires you config a static tile height/width and fps rather than getting these from world.var natively.

That's not going to change.

It's completely asinine to parse world.icon_size every time you want to figure out something that is both particular to the implementation and unchanging.

World.fps is the fps the world is running at, not the fps the world has been directed to run at.

Everything BYOND does in terms of time/ticker calculations is wrong, and I define these directives to help isolate the user from thinking the way that working in BYOND as your first major programming language trains you to --wrongly.
well, strictly speaking, world.fps doesn't exist, world.tick_lag does.

world.fps is calculated on read.

I'm actually curious as to what in your system needs the fps, in most cases the math on the tick_lag is easier and faster
I'm actually curious as to what in your system needs the fps, in most cases the math on the tick_lag is easier and faster

I use the FPS to calculate tick_lag because most users I help don't understand the decisecond math properly.

StdLib doesn't use FPS or TICK_LAG directly. The dependent libraries (MoveLib, ProjectileLib, ParticleLib, etc.) use the common tick lag values to assist in calculating glide offsets and working with some helper movement functions.

It's a value I use frequently when writing code, however, StdLib doesn't itself make use of it.