Implement config-driven unlock groups so that multiple things can be unlocked at once (including buildings)
This commit is contained in:
@@ -67,6 +67,7 @@
|
||||
#include "BuilderModeExitedEvent.h"
|
||||
#include "BlueprintModeExitedEvent.h"
|
||||
#include "BuildingBlocksChangedEvent.h"
|
||||
#include "UnlockedBuildingsChangedEvent.h"
|
||||
#include "ExpansionCostChangedEvent.h"
|
||||
#include "GameSpeedChangedEvent.h"
|
||||
#include "SchematicChoicesAvailableEvent.h"
|
||||
@@ -367,6 +368,20 @@ void GameWorldView::onFrame()
|
||||
EventManager::getInstance()->sendEventImmediately(
|
||||
std::make_shared<BossWaveUpdatedEvent>(newBoss, newCountdown));
|
||||
}
|
||||
|
||||
// Unlocked building set changes only after a drop is applied or on Restart
|
||||
// (REQ-LOCK-BUILDING); the build grid rebuilds its visible buttons.
|
||||
int newUnlockedBuildingCount = 0;
|
||||
for (const BuildingDef& def : m_sim->getConfig().buildings.buildings)
|
||||
{
|
||||
if (m_sim->isBuildingUnlocked(def.type)) { ++newUnlockedBuildingCount; }
|
||||
}
|
||||
if (newUnlockedBuildingCount != m_lastUnlockedBuildingCount)
|
||||
{
|
||||
m_lastUnlockedBuildingCount = newUnlockedBuildingCount;
|
||||
EventManager::getInstance()->sendEventImmediately(
|
||||
std::make_shared<UnlockedBuildingsChangedEvent>());
|
||||
}
|
||||
}
|
||||
|
||||
// Sim-state polls are input sources for the live game; in replay these are
|
||||
@@ -801,13 +816,18 @@ void GameWorldView::placeBlueprintAtTile(QPoint center)
|
||||
|
||||
for (const BlueprintBuilding& bb : bp.buildings)
|
||||
{
|
||||
// Locked building types are excluded from this placement entirely
|
||||
// (REQ-LOCK-BUILDING, REQ-LOCK-UI-BLUEPRINT): not validity-checked here.
|
||||
if (!m_sim->isBuildingUnlocked(bb.type)) { continue; }
|
||||
if (!isValidPlacement(bb.type, center + bb.offset, bb.rotation)) { return; }
|
||||
}
|
||||
|
||||
// Cost only applies to buildings that are genuinely new (not rotate-in-place).
|
||||
// Cost only applies to buildings that are genuinely new (not rotate-in-place),
|
||||
// and excludes locked building types (REQ-LOCK-UI-BLUEPRINT).
|
||||
int totalCost = 0;
|
||||
for (const BlueprintBuilding& bb : bp.buildings)
|
||||
{
|
||||
if (!m_sim->isBuildingUnlocked(bb.type)) { continue; }
|
||||
if (m_sim->getBuildings().findRotateInPlaceTarget(
|
||||
bb.type, center + bb.offset, bb.rotation).has_value())
|
||||
{
|
||||
@@ -820,6 +840,7 @@ void GameWorldView::placeBlueprintAtTile(QPoint center)
|
||||
|
||||
for (const BlueprintBuilding& bb : bp.buildings)
|
||||
{
|
||||
if (!m_sim->isBuildingUnlocked(bb.type)) { continue; }
|
||||
const QPoint anchor = center + bb.offset;
|
||||
const std::optional<BuildingId> rotateTarget =
|
||||
m_sim->getBuildings().findRotateInPlaceTarget(bb.type, anchor, bb.rotation);
|
||||
@@ -1946,6 +1967,9 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
{
|
||||
for (const BlueprintBuilding& bb : m_blueprintMode->buildings)
|
||||
{
|
||||
// Locked building types are omitted from the blueprint (REQ-LOCK-BUILDING,
|
||||
// REQ-LOCK-UI-BLUEPRINT), so they are not ghosted either.
|
||||
if (!m_sim->isBuildingUnlocked(bb.type)) { continue; }
|
||||
const QPoint anchor = m_blueprintGhostTile + bb.offset;
|
||||
const bool valid = isValidPlacement(bb.type, anchor, bb.rotation);
|
||||
drawBuildingGhost(painter, bb.type, anchor, bb.rotation, valid,
|
||||
|
||||
Reference in New Issue
Block a user