show implicitly unlocked items in schematic unlock dialog
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "ConfigLoader.h"
|
||||
#include "DisplayName.h"
|
||||
#include "FactionComponent.h"
|
||||
#include "GameConfig.h"
|
||||
#include "HealthComponent.h"
|
||||
@@ -277,3 +278,85 @@ TEST_CASE("RecipeSchematic: reset keeps -1 recipes unlocked and their seed items
|
||||
REQUIRE(sim.isItemUnlocked("premium_circuit"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Unlock dialog: newly-unlocked recipe preview (REQ-DEF-SCHEMATIC-DROP)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("RecipeSchematic: newlyUnlockedItemNames is sorted, deduplicated, and empty for level-ups",
|
||||
"[recipe_schematic]")
|
||||
{
|
||||
Simulation sim(loadConfig());
|
||||
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
killEnemyStations(sim);
|
||||
if (!sim.hasSchematicChoicesPending()) { continue; }
|
||||
|
||||
for (const SchematicChoiceOption& opt : sim.getPendingSchematicChoices())
|
||||
{
|
||||
// Strictly ascending implies sorted and deduplicated.
|
||||
for (std::size_t j = 1; j < opt.newlyUnlockedItemNames.size(); ++j)
|
||||
{
|
||||
CHECK(opt.newlyUnlockedItemNames[j - 1] < opt.newlyUnlockedItemNames[j]);
|
||||
}
|
||||
|
||||
// A level-up doesn't change the explicit unlock state, so the
|
||||
// implicit unlock set - and thus this preview - must be empty.
|
||||
if (!opt.isNewUnlock)
|
||||
{
|
||||
CHECK(opt.newlyUnlockedItemNames.empty());
|
||||
}
|
||||
}
|
||||
|
||||
sim.applySchematicChoice(0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("RecipeSchematic: newlyUnlockedItemNames matches recipes that actually become unlocked",
|
||||
"[recipe_schematic]")
|
||||
{
|
||||
Simulation sim(loadConfig());
|
||||
const GameConfig cfg = loadConfig();
|
||||
|
||||
auto unlockedTrackedRecipeIds = [&]()
|
||||
{
|
||||
std::set<std::string> ids;
|
||||
for (const RecipeDef& def : cfg.recipes.recipes)
|
||||
{
|
||||
if ((def.building == BuildingType::Miner || def.building == BuildingType::Assembler)
|
||||
&& sim.isRecipeUnlocked(def.id))
|
||||
{
|
||||
ids.insert(def.id);
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
};
|
||||
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
killEnemyStations(sim);
|
||||
if (!sim.hasSchematicChoicesPending()) { continue; }
|
||||
|
||||
const std::set<std::string> unlockedBefore = unlockedTrackedRecipeIds();
|
||||
const SchematicChoiceOption choice = sim.getPendingSchematicChoices()[0];
|
||||
|
||||
sim.applySchematicChoice(0);
|
||||
|
||||
std::set<std::string> expectedNames;
|
||||
for (const RecipeDef& def : cfg.recipes.recipes)
|
||||
{
|
||||
if ((def.building == BuildingType::Miner || def.building == BuildingType::Assembler)
|
||||
&& sim.isRecipeUnlocked(def.id) && unlockedBefore.count(def.id) == 0)
|
||||
{
|
||||
for (const RecipeOutput& out : def.outputs)
|
||||
{
|
||||
expectedNames.insert(toDisplayName(out.item));
|
||||
}
|
||||
}
|
||||
}
|
||||
const std::vector<std::string> expected(expectedNames.begin(), expectedNames.end());
|
||||
|
||||
REQUIRE(choice.newlyUnlockedItemNames == expected);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user