#pragma once #include "design/effect.h" #include "design/effector.h" #include "vec2.h" #include "util/formula.h" #include "util/basic_type.h" #include "compat/misc.h" #include "render/spritesheet.h" #include #include #include #include "util/hex_grid.h" class SaveFile; #ifndef MODIFY_STAGE_MAXARGS #define MODIFY_STAGE_MAXARGS 8 #endif enum SysVariableType { SVT_SubsystemVariable, SVT_HexVariable, SVT_ShipVariable, }; enum TemplateCondition { TC_Tag, TC_Modifier, TC_Variable, TC_HexVariable, TC_ShipVariable, TC_Subsystem, TC_NOT = 1<<20, }; class Design; class Subsystem; class HullDef; class SubsystemDef { public: struct Variable { Formula* formula; std::string str_formula; std::string name; int index; int globalId; SysVariableType type; bool dependent; }; struct Effect { const EffectDef* type; std::vector values; std::vector str_values; }; struct Effector { const EffectorDef* type; bool enabled; unsigned skinIndex; std::string skinName; std::vector values; std::vector str_values; }; struct StateDesc { BasicTypes type; Formula* formula; std::string str_formula; }; struct HookDesc { std::string name; std::vector str_args; std::vector formulas; mutable std::vector argValues; HookDesc() {} HookDesc(const std::string& str); }; struct ModifyStage { unsigned index; int stage; int umodifid; std::unordered_map argumentNames; std::vector> str_variables; std::vector> str_hexVariables; std::vector> str_shipVariables; std::unordered_map variables; std::unordered_map hexVariables; std::unordered_map shipVariables; ModifyStage() : stage(0), umodifid(-1), index(0) {} void applyVariables(Subsystem* sys) const; void applyHexVariables(Subsystem* sys, int hexIndex) const; void applyShipVariables(Design* dsg, Subsystem* sys) const; }; struct AppliedStage { const ModifyStage* stage; float arguments[MODIFY_STAGE_MAXARGS]; Formula* formulas[MODIFY_STAGE_MAXARGS]; void clear() { for(unsigned i = 0; i < MODIFY_STAGE_MAXARGS; ++i) { if(formulas[i]) { delete formulas[i]; formulas[i] = 0; } } } AppliedStage() { memset(this, 0, sizeof(AppliedStage)); } }; struct ShipModifier { AppliedStage stage; std::string modifyName; std::vector str_arguments; std::vector> conditions; }; struct Assert { std::string str_formula; Formula* formula; std::string message; bool fatal; bool unique; }; struct ModuleDesc { int index; std::string id; std::string name; std::string description; Color color; std::string umodident; int umodid; std::string def_onEnable; std::string def_onDisable; asIScriptFunction* scr_onEnable; asIScriptFunction* scr_onDisable; std::vector modifiers; std::vector uniqueModifiers; std::vector appliedStages; std::vector str_appliedStages; std::vector uniqueAppliedStages; std::vector str_uniqueAppliedStages; std::vector hexAppliedStages; std::vector str_hexAppliedStages; std::vector adjacentModifiers; std::vector effects; std::unordered_set tags; std::unordered_set numTags; std::unordered_map> tagValues; bool hasTag(const std::string& tag) const; bool hasTag(int index) const; const std::string& getTagValue(int index, unsigned num = 0) const; unsigned getTagValueCount(int index) const; bool hasTagValue(int index, const std::string& value) const; std::string def_onCheckErrors; asIScriptFunction* scr_onCheckErrors; bool onCheckErrors(Design* design, Subsystem* sys, const vec2u& hex) const; std::vector hooks; std::vector asserts; std::string spriteMat; render::Sprite sprite; int drawMode; bool required; bool unique; bool vital; bool defaultUnlock; void onEnable(EffectEvent& evt, const vec2u& position) const; void onDisable(EffectEvent& evt, const vec2u& position) const; ModuleDesc() : index(-1), scr_onEnable(0), scr_onDisable(0), drawMode(0), required(false), unique(false), vital(false), defaultUnlock(false), scr_onCheckErrors(nullptr) { } }; std::string name; std::string description; std::string id; int index; int ordering; int damageOrder; int elevation; Color baseColor; Color typeColor; std::string hexMat; std::string picMat; render::Sprite picture; std::vector variableIndices; std::vector variables; std::vector hexVariableIndices; std::vector hexVariables; std::vector shipVariableIndices; std::vector shipVariables; std::vector effects; std::vector effectors; std::vector states; std::vector modules; std::vector shipModifiers; std::vector postModifiers; std::vector adjacentModifiers; std::unordered_map moduleIndices; const SubsystemDef::ModuleDesc* defaultModule; const SubsystemDef::ModuleDesc* coreModule; std::vector modifiers; std::unordered_map modifierIds; std::vector asserts; uset tags; std::vector hullTags; uset numTags; std::unordered_map> tagValues; void finalize(); bool hasTag(const std::string& tag) const; bool hasTag(int index) const; const std::string& getTagValue(int index, unsigned num = 0) const; unsigned getTagValueCount(int index) const; bool hasTagValue(int index, const std::string& value) const; std::string def_onCheckErrors; asIScriptFunction* scr_onCheckErrors; std::vector hooks; bool onCheckErrors(Design* design, Subsystem* sys) const; bool canUseOn(const HullDef* hull) const; bool hasHullTag(const std::string& tag) const; bool hasCore; bool isContiguous; bool exteriorCore; bool defaultUnlock; bool isHull; bool isApplied; bool hexLimitArc; bool passExterior; bool fauxExterior; bool alwaysTakeDamage; SubsystemDef(); ~SubsystemDef(); }; extern int SV_Size, HV_Resistance, HV_HP, ShV_HexSize; extern umap subsystemIndices; extern umap variableIndices; extern umap hexVariableIndices; extern umap shipVariableIndices; void clearSubsystemDefinitions(); void loadSubsystemDefinitions(const std::string& filename); const SubsystemDef* getSubsystemDef(const std::string& name); const SubsystemDef* getSubsystemDef(int id); int getSubsystemDefCount(); void enumerateVariables(std::function); int getVariableIndex(const std::string& name); const std::string& getVariableId(int index); void enumerateHexVariables(std::function); int getHexVariableIndex(const std::string& name); const std::string& getHexVariableId(int index); void enumerateShipVariables(std::function); unsigned getShipVariableCount(); int getShipVariableIndex(const std::string& name); const std::string& getShipVariableId(int index); void enumerateSysTags(std::function); int getSysTagIndex(const std::string& name, bool create = false); Formula* parseFormula(const std::string& str, const SubsystemDef* def = 0, const SubsystemDef::ModifyStage* modifier = 0); void bindSubsystemMaterials(); void bindSubsystemHooks(); void finalizeSubsystems(); void executeSubsystemTemplates(); class Blueprint; struct SubsystemEvent { const Subsystem* subsystem; const Design* design; Object* obj; Blueprint* blueprint; void* data; float efficiency; float partiality; }; class asIScriptFunction; class asIScriptObject; class SaveMessage; class Subsystem { public: const SubsystemDef* type; std::vector hexes; std::vector modules; std::vector adjacentModifiers; std::vector> hexAdjacentModifiers; std::vector moduleCounts; vec2u core; vec3d direction; int exteriorHexes; bool hasErrors; static asIScriptFunction* ScriptInitFunction; static asIScriptFunction* ScriptHookFunctions[EH_COUNT]; Effector* effectors; float* variables; float* baseVariables; float* hexVariables; float* hexBaseVariables; BasicType* defaults; unsigned stateOffset; unsigned effectorOffset; unsigned dataOffset; std::vector effects; std::vector> hexEffects; std::vector hookClasses; void addHook(Design* design, const SubsystemDef::HookDesc& desc); const Design* inDesign; unsigned index; int getModuleCount(int index); float* variable(int index); const float* variable(int index) const; float* hexVariable(int index, int hexIndex); const float* hexVariable(int index, int hexIndex) const; Subsystem(); Subsystem(const SubsystemDef& def); Subsystem(SaveFile& file); ~Subsystem(); void save(SaveFile& file) const; void postLoad(Design* design); void init(const SubsystemDef& def); void init(SaveFile& file); void initVariables(Design* design); void initEffects(Design* design); void initLinks(Design* design); void evaluatePost(Design* design); void evaluateAsserts(Design* design); void skinEffectors(Empire& emp); void applyAdjacencies(Design* design); DamageEventStatus damage(DamageEvent& event, const vec2u& position) const; DamageEventStatus globalDamage(DamageEvent& event, vec2u& position, vec2d& endPoint) const; bool hasGlobalDamage() const; void ownerChange(EffectEvent& event, Empire* prevEmpire, Empire* newEmpire) const; void call(EffectHook hook, EffectEvent& event) const; void tick(EffectEvent& event) const; void save(EffectEvent& event, SaveMessage& msg) const; void load(EffectEvent& event, SaveMessage& msg) const; void markConnected(HexGrid& grid, vec2u hex); void writeData(net::Message& msg) const; Subsystem(net::Message& msg); };