diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarObjectDatabase.hpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/game/StarObjectDatabase.hpp')
-rw-r--r-- | source/game/StarObjectDatabase.hpp | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/source/game/StarObjectDatabase.hpp b/source/game/StarObjectDatabase.hpp new file mode 100644 index 0000000..5f3f675 --- /dev/null +++ b/source/game/StarObjectDatabase.hpp @@ -0,0 +1,224 @@ +#ifndef STAR_OBJECT_DATABASE_HPP +#define STAR_OBJECT_DATABASE_HPP + +#include "StarPeriodicFunction.hpp" +#include "StarTtlCache.hpp" +#include "StarGameTypes.hpp" +#include "StarItemDescriptor.hpp" +#include "StarParticle.hpp" +#include "StarSet.hpp" +#include "StarTileDamage.hpp" +#include "StarDamageTypes.hpp" +#include "StarStatusTypes.hpp" +#include "StarEntityRendering.hpp" +#include "StarTileEntity.hpp" + +namespace Star { + +STAR_CLASS(World); +STAR_CLASS(Image); +STAR_CLASS(ItemDatabase); +STAR_CLASS(RecipeDatabase); +STAR_CLASS(Object); +STAR_STRUCT(ObjectOrientation); +STAR_STRUCT(ObjectConfig); +STAR_CLASS(ObjectDatabase); + +STAR_EXCEPTION(ObjectException, StarException); + +struct ObjectOrientation { + struct Anchor { + TileLayer layer; + Vec2I position; + bool tilled; + bool soil; + Maybe<MaterialId> material; + }; + + struct ParticleEmissionEntry { + float particleEmissionRate; + float particleEmissionRateVariance; + // Particle positions are considered relative to image pixels, and are + // flipped with image flipping + Particle particle; + Particle particleVariance; + bool placeInSpaces; + }; + + // The JSON values that were used to configure this orientation. + Json config; + + EntityRenderLayer renderLayer; + List<Drawable> imageLayers; + bool flipImages; + + // Offset of image from (0, 0) object position, in tile coordinates + Vec2F imagePosition; + + // If an object has frames > 1, then the image name will have the marker + // "{frame}" replaced with an integer in [0, frames) + unsigned frames; + float animationCycle; + + // Spaces the object occupies. By default, this is simply the single space + // at the object position, but can be specified in config as either a list of + // Vec2I, or by setting a threshold value using "spaceScanning", which will + // scan the image (frame 1) for non-transparent pixels. + List<Vec2I> spaces; + RectI boundBox; + + // Allow an orientation to override the metaboundbox in case you don't want to + // specify spaces + Maybe<RectF> metaBoundBox; + + // Anchors of the object to place it in the world + // For background tiles set in order for the object to + // remain placed. Must be within 1 space of the bounding box of spaces. + // For foreground tiles this cannot logically contain any position + // also in spaces, as objects cannot overlap with foreground tiles. + List<Anchor> anchors; + + // if true, only one anchor needs to be valid for the orientation to be valid, + // otherwise all anchors must be valid + bool anchorAny; + + Maybe<Direction> directionAffinity; + + // Optional list of material spaces + List<MaterialSpace> materialSpaces; + + // optionally override the default spaces used for interaction + Maybe<List<Vec2I>> interactiveSpaces; + + Vec2F lightPosition; + float beamAngle; + + List<ParticleEmissionEntry> particleEmitters; + + Maybe<PolyF> statusEffectArea; + Json touchDamageConfig; + + static ParticleEmissionEntry parseParticleEmitter(String const& path, Json const& config); + bool placementValid(World const* world, Vec2I const& position) const; + bool anchorsValid(World const* world, Vec2I const& position) const; +}; + +// TODO: This is used very strangely and inconsistently. We go to all the trouble of populating +// this ObjectConfig structure from the JSON, but then keep around the JSON anyway. In some +// places we access the objectConfig, but in many more we use the object's configValue method +// to access the raw config JSON which means it's inconsistent which parameters can be overridden +// by instance values at various levels. This whole system needs reevaluation. +struct ObjectConfig { + // Returns the index of the best valid orientation. If no orientations are + // valid, returns NPos + size_t findValidOrientation(World const* world, Vec2I const& position, Maybe<Direction> directionAffinity = Maybe<Direction>()) const; + + String path; + // The JSON values that were used to configure this Object + Json config; + + String name; + String type; + String race; + String category; + StringList colonyTags; + StringList scripts; + StringList animationScripts; + + unsigned price; + bool printable; + bool scannable; + + bool interactive; + + StringMap<Color> lightColors; + bool pointLight; + float pointBeam; + float beamAmbience; + Maybe<PeriodicFunction<float>> lightFlickering; + + String soundEffect; + float soundEffectRangeMultiplier; + + List<PersistentStatusEffect> statusEffects; + Json touchDamageConfig; + + bool hasObjectItem; + bool retainObjectParametersInItem; + + bool smashable; + bool smashOnBreak; + bool unbreakable; + String smashDropPool; + List<List<ItemDescriptor>> smashDropOptions; + StringList smashSoundOptions; + JsonArray smashParticles; + + String breakDropPool; + List<List<ItemDescriptor>> breakDropOptions; + + TileDamageParameters tileDamageParameters; + float damageShakeMagnitude; + String damageMaterialKind; + + EntityDamageTeam damageTeam; + + Maybe<float> minimumLiquidLevel; + Maybe<float> maximumLiquidLevel; + float liquidCheckInterval; + + float health; + + Json animationConfig; + + List<ObjectOrientationPtr> orientations; + + // If true, the object will root - it will prevent the blocks it is + // anchored to from being destroyed directly, and damage from those + // blocks will be redirected to the object + bool rooting; + + bool biomePlaced; +}; + +class ObjectDatabase { +public: + static List<Vec2I> scanImageSpaces(ImageConstPtr const& image, Vec2F const& position, float fillLimit, bool flip = false); + static Json parseTouchDamage(String const& path, Json const& touchDamage); + static List<ObjectOrientationPtr> parseOrientations(String const& path, Json const& configList); + + ObjectDatabase(); + + void cleanup(); + + StringList allObjects() const; + bool isObject(String const& name) const; + + ObjectConfigPtr getConfig(String const& objectName) const; + List<ObjectOrientationPtr> const& getOrientations(String const& objectName) const; + + ObjectPtr createObject(String const& objectName, Json const& objectParameters = JsonObject()) const; + ObjectPtr diskLoadObject(Json const& diskStore) const; + ObjectPtr netLoadObject(ByteArray const& netStore) const; + + bool canPlaceObject(World const* world, Vec2I const& position, String const& objectName) const; + // If the object is placeable in the given position, creates the given object + // and sets its position and direction and returns it, otherwise returns + // null. + ObjectPtr createForPlacement(World const* world, String const& objectName, Vec2I const& position, + Direction direction, Json const& parameters = JsonObject()) const; + + List<Drawable> cursorHintDrawables(World const* world, String const& objectName, Vec2I const& position, + Direction direction, Json parameters = {}) const; + +private: + static ObjectConfigPtr readConfig(String const& path); + + StringMap<String> m_paths; + mutable Mutex m_cacheMutex; + mutable HashTtlCache<String, ObjectConfigPtr> m_configCache; +}; + +} + +#endif |