Skip to content
Cataclysm: Bright Nights
GitHubDiscord

Game Objects

Many of the things that physically exist within the game world are game objects(GO). Currently this only covers items, but creatures and vehicles are coming soon and then probably furniture at some point. GOs have a small common interface with methods like name and position that you can find in game_object.h. GOs use private constructors, this means your variables must always be references or pointers. Trying to assign a variable without a layer of indirection like that will cause a compile error. Likewise trying to copy one object over another will cause a similar error.

item& it_ref = ...; // Good
item* it_pointer; // Good

item it = ...; // Compile error
it_ref = other; // Compile error
*it_pointer = other; // Compile error

New GOs can be created via ::spawn static methods that return a detached_ptr to the newly created game object. A detached_ptr represents an object that does not currently exist in the game world. There can only be one detached_ptr to an object at a time (those who know std::unique_ptr will be familiar with this behavior). Functions that add an object to the world will require that you std::move in a detached_ptr. In general detached_ptrs must be std::move‘d when they’re passed into a function. Note that you should never use any variable after it has been moved. Likewise functions that remove an object from the world will return a detached_ptr. This ensures that you can’t add the same thing to the world twice.

Functions that don’t add things to the world just accept normal pointers. You can turn a detached_ptr into a normal pointer by doing this. Note that you can use this to keep a valid pointer to something even after you std::move it, but you must do this before the std::move happens.

&*detached

And you can go the other way using this. Though note that it removes the object from the game world in the process and will cause errors if called on an object that isn’t in the game world.

detached_ptr<item> as_detached = normal_ptr->detach();

Trying to access an invalid detached_ptr (for instance one that has been std::move‘d from) will cause a debugmsg and give you the null version of that object.

Safe References

Game objects support safe references. safe_reference<item> will refuse access to an object that has been destroyed or is outside of the reality bubble without losing track of it, and they can be saved and loaded. You must check them as a boolean (e.g. if( ref )) to see if they’re valid. Trying to access them when they’re not will cause debugmsgs and give you a null object instead. They have a small interface that lets you check if they’re destroyed or unloaded etc. If they were destroyed or unloaded this turn, they have a method that will allow you to access the object in a const fashion, for instance to display an error message.

If you’re moving objects around you need to use detached_ptrs, but otherwise when choosing which reference to use the most important thing to consider is how long you want to hold onto it. If you’re just using something temporarily, for instance most arguments and variables, you should use a normal reference or pointer. If you need to store it for longer you should use a safe reference and this means it can be easily stored in the save file. In the rare case that you do want to save it across turns but don’t want to store it in the save file, which means caches, there’s also a fast cache_reference<item>, which does last across turns but can’t be saved.

Game objects can sometimes be split into pieces or merged together. Item stacks are the main example of this but there are others like vehicles being split or dissoluted devourers merging. When a stack of items is split, the stack that stays in place is the one that safe references will follow. When they are merged safe references to either half of the merge will now point to the merge result.