explicit recipe unlocking
This commit is contained in:
@@ -87,6 +87,17 @@ Simulation::Simulation(GameConfig config, unsigned int seed)
|
||||
m_moduleSchematicLevels[def.id] = state;
|
||||
}
|
||||
|
||||
// Initialize assembler recipe schematic unlock state.
|
||||
for (const RecipeDef& def : m_config.recipes.recipes)
|
||||
{
|
||||
if (def.building == BuildingType::Assembler
|
||||
&& def.unlockAtStationLevel.has_value()
|
||||
&& def.unlockAtStationLevel.value() == -1)
|
||||
{
|
||||
m_unlockedRecipeSchematicIds.insert(def.id);
|
||||
}
|
||||
}
|
||||
|
||||
recomputeUnlocked();
|
||||
placeInitialStructures();
|
||||
registerForEvents();
|
||||
@@ -177,6 +188,17 @@ void Simulation::reset(unsigned int seed)
|
||||
m_moduleSchematicLevels[def.id] = state;
|
||||
}
|
||||
|
||||
m_unlockedRecipeSchematicIds.clear();
|
||||
for (const RecipeDef& def : m_config.recipes.recipes)
|
||||
{
|
||||
if (def.building == BuildingType::Assembler
|
||||
&& def.unlockAtStationLevel.has_value()
|
||||
&& def.unlockAtStationLevel.value() == -1)
|
||||
{
|
||||
m_unlockedRecipeSchematicIds.insert(def.id);
|
||||
}
|
||||
}
|
||||
|
||||
recomputeUnlocked();
|
||||
placeInitialStructures();
|
||||
}
|
||||
@@ -516,40 +538,66 @@ void Simulation::tickDeathsAndLoot()
|
||||
|
||||
void Simulation::awardSchematicDrop(int destroyedStationLevel)
|
||||
{
|
||||
std::vector<std::pair<std::string, bool>> pool; // (id, isModule)
|
||||
enum class DropType { Ship, Module, Recipe };
|
||||
struct PoolEntry { std::string id; DropType type; };
|
||||
std::vector<PoolEntry> pool;
|
||||
|
||||
for (const ShipDef& def : m_config.ships.ships)
|
||||
{
|
||||
if (def.unlockAtStationLevel == -1 || def.unlockAtStationLevel <= destroyedStationLevel)
|
||||
{
|
||||
pool.push_back({def.id, false});
|
||||
pool.push_back({def.id, DropType::Ship});
|
||||
}
|
||||
}
|
||||
for (const ModuleDef& def : m_config.modules.modules)
|
||||
{
|
||||
if (def.unlockAtStationLevel == -1 || def.unlockAtStationLevel <= destroyedStationLevel)
|
||||
{
|
||||
pool.push_back({def.id, true});
|
||||
pool.push_back({def.id, DropType::Module});
|
||||
}
|
||||
}
|
||||
for (const RecipeDef& def : m_config.recipes.recipes)
|
||||
{
|
||||
if (def.building != BuildingType::Assembler) { continue; }
|
||||
if (!def.unlockAtStationLevel.has_value()) { continue; }
|
||||
const int level = def.unlockAtStationLevel.value();
|
||||
if (level < 0 || level > destroyedStationLevel) { continue; }
|
||||
if (m_unlockedRecipeSchematicIds.count(def.id) > 0) { continue; }
|
||||
bool outputUnlocked = false;
|
||||
for (const RecipeOutput& out : def.outputs)
|
||||
{
|
||||
if (m_unlockedItemIds.count(out.item) > 0) { outputUnlocked = true; break; }
|
||||
}
|
||||
if (!outputUnlocked) { continue; }
|
||||
pool.push_back({def.id, DropType::Recipe});
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, static_cast<int>(pool.size()) - 1);
|
||||
const auto& [chosen, isModule] = pool[static_cast<std::size_t>(dist(m_rng))];
|
||||
const PoolEntry& chosen = pool[static_cast<std::size_t>(dist(m_rng))];
|
||||
|
||||
SchematicState& state = isModule
|
||||
? m_moduleSchematicLevels.at(chosen)
|
||||
: m_schematicLevels.at(chosen);
|
||||
const bool wasNew = !state.unlocked;
|
||||
state.unlocked = true;
|
||||
state.level += 1;
|
||||
if (chosen.type == DropType::Recipe)
|
||||
{
|
||||
m_unlockedRecipeSchematicIds.insert(chosen.id);
|
||||
recomputeUnlocked();
|
||||
}
|
||||
else
|
||||
{
|
||||
SchematicState& state = (chosen.type == DropType::Module)
|
||||
? m_moduleSchematicLevels.at(chosen.id)
|
||||
: m_schematicLevels.at(chosen.id);
|
||||
const bool wasNew = !state.unlocked;
|
||||
state.unlocked = true;
|
||||
state.level += 1;
|
||||
|
||||
SchematicDropEvent evt;
|
||||
evt.schematicId = chosen;
|
||||
evt.newLevel = state.level;
|
||||
evt.wasNewUnlock = wasNew;
|
||||
evt.isModuleSchematic = isModule;
|
||||
m_schematicDropEvents.push_back(evt);
|
||||
SchematicDropEvent evt;
|
||||
evt.schematicId = chosen.id;
|
||||
evt.newLevel = state.level;
|
||||
evt.wasNewUnlock = wasNew;
|
||||
evt.isModuleSchematic = (chosen.type == DropType::Module);
|
||||
m_schematicDropEvents.push_back(evt);
|
||||
|
||||
recomputeUnlocked();
|
||||
recomputeUnlocked();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -577,6 +625,18 @@ void Simulation::recomputeUnlocked()
|
||||
m_unlockedItemIds.insert(mat.item);
|
||||
}
|
||||
}
|
||||
for (const RecipeDef& def : m_config.recipes.recipes)
|
||||
{
|
||||
if (def.building == BuildingType::Assembler
|
||||
&& def.unlockAtStationLevel.has_value()
|
||||
&& m_unlockedRecipeSchematicIds.count(def.id) > 0)
|
||||
{
|
||||
for (const RecipeOutput& out : def.outputs)
|
||||
{
|
||||
m_unlockedItemIds.insert(out.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool changed = true;
|
||||
while (changed)
|
||||
@@ -590,6 +650,12 @@ void Simulation::recomputeUnlocked()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (recipe.building == BuildingType::Assembler
|
||||
&& recipe.unlockAtStationLevel.has_value()
|
||||
&& m_unlockedRecipeSchematicIds.count(recipe.id) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool producesUnlocked = false;
|
||||
for (const RecipeOutput& out : recipe.outputs)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user