222 lines
6.7 KiB
C++
222 lines
6.7 KiB
C++
#pragma once
|
|
|
|
#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;
|
|
};
|
|
|
|
}
|