Implement config-driven unlock groups so that multiple things can be unlocked at once (including buildings)

This commit is contained in:
2026-07-22 21:34:59 +02:00
parent a8a6a04f1e
commit a9082c57f3
36 changed files with 1005 additions and 543 deletions

View File

@@ -100,6 +100,10 @@ public:
bool isRecipeUnlocked(const std::string& recipeId) const;
bool isItemUnlocked(const std::string& itemId) const;
// Building unlock query (REQ-LOCK-BUILDING). True if the building type is not
// gated by any unlock group, or its granting group has been awarded.
bool isBuildingUnlocked(BuildingType type) const;
// -- Determinism (see docs/replay_design.md) -----------------------------
// 64-bit fingerprint of the RNG stream state. Cheap; written to the replay
// file periodically + after each command for desync detection.
@@ -196,6 +200,24 @@ private:
};
std::map<std::string, SchematicState> m_schematicLevels;
std::map<std::string, SchematicState> m_moduleSchematicLevels;
std::map<std::string, SchematicState> m_buildingLevels;
// Unlock groups awarded so far (REQ-LOCK-EXPLICIT). Group ids.
std::set<std::string> m_awardedUnlockGroupIds;
// Ids granted by some unlock group, per kind — cached from config at init.
// An item starts locked iff it appears in the corresponding set.
std::set<std::string> m_grantedShipIds;
std::set<std::string> m_grantedModuleIds;
std::set<std::string> m_grantedBuildingIds;
std::set<std::string> m_grantedRecipeIds;
// Builds the granted-id sets and initializes all per-item unlock maps from
// them (shared by the constructor and reset). Ends with recomputeUnlocked().
void initializeUnlockState();
// Builds a schematic choice option for one unlock group (REQ-DEF-SCHEMATIC-DROP).
SchematicChoiceOption makeUnlockOption(const UnlockGroupDef& group) const;
// Determinism helpers — fold sub-state into the hasher in deterministic order.
static void appendSchematicMap(Hasher& hasher,
@@ -228,11 +250,8 @@ private:
std::set<std::string> getUnlockedShipSchematicIds() const;
std::set<std::string> getUnlockedModuleSchematicIds() const;
// True if schematicId names a currently explicitly-unlocked ship, module, or
// assembler recipe schematic (REQ-LOCK-PREREQ satisfaction basis).
bool isSchematicIdExplicitlyUnlocked(const std::string& schematicId) const;
// True if every prerequisite in unlockRequires is explicitly unlocked (REQ-LOCK-PREREQ).
bool prerequisitesSatisfied(const std::vector<std::string>& unlockRequires) const;
// True if every prerequisite unlock group has been awarded (REQ-LOCK-PREREQ).
bool prerequisitesSatisfied(const std::vector<std::string>& requiredGroupIds) const;
// Ids (sorted alphabetically by display name) of the recipes in
// hypothetical.recipeIds that are not yet in m_unlockedRecipeIds.