implement blueprints
This commit is contained in:
@@ -452,6 +452,29 @@ void GameWorldView::stepSpeed(int delta)
|
||||
setGameSpeed(kSpeeds[next]);
|
||||
}
|
||||
|
||||
void GameWorldView::placeBlueprintAtTile(QPoint center)
|
||||
{
|
||||
const Blueprint& bp = *m_blueprintMode;
|
||||
|
||||
for (const BlueprintBuilding& bb : bp.buildings)
|
||||
{
|
||||
if (!isValidPlacement(bb.type, center + bb.offset, bb.rotation)) { return; }
|
||||
}
|
||||
|
||||
int totalCost = 0;
|
||||
for (const BlueprintBuilding& bb : bp.buildings)
|
||||
{
|
||||
const BuildingDef* def = findBuildingDef(bb.type);
|
||||
if (def) { totalCost += def->cost; }
|
||||
}
|
||||
if (m_sim->buildingBlocksStock() < totalCost) { return; }
|
||||
|
||||
for (const BlueprintBuilding& bb : bp.buildings)
|
||||
{
|
||||
m_sim->tryPlaceBuilding(bb.type, center + bb.offset, bb.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::placeAtTile(QPoint tile)
|
||||
{
|
||||
if (!m_builderType.has_value())
|
||||
@@ -776,6 +799,32 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
}
|
||||
}
|
||||
|
||||
// Blueprint placement ghost
|
||||
if (m_blueprintMode.has_value())
|
||||
{
|
||||
for (const BlueprintBuilding& bb : m_blueprintMode->buildings)
|
||||
{
|
||||
const QPoint anchor = m_blueprintGhostTile + bb.offset;
|
||||
const bool valid = isValidPlacement(bb.type, anchor, bb.rotation);
|
||||
const QColor& ghostColor = valid
|
||||
? m_visuals->overlays.ghostValid
|
||||
: m_visuals->overlays.ghostInvalid;
|
||||
const BuildingDef* def = findBuildingDef(bb.type);
|
||||
if (!def) { continue; }
|
||||
const ParsedSurfaceMask parsed = parseSurfaceMask(def->surfaceMask, bb.rotation);
|
||||
for (const QPoint& cell : parsed.bodyCells)
|
||||
{
|
||||
painter.fillRect(tileRect(anchor + cell), ghostColor);
|
||||
}
|
||||
for (const Port& port : parsed.outputPorts)
|
||||
{
|
||||
drawPortGlyph(painter,
|
||||
anchor + portBodyTile(port.tile, port.direction),
|
||||
port.direction, Qt::white);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Demolish hover tint
|
||||
if (m_demolishMode && m_demolishHoverId != kInvalidEntityId)
|
||||
{
|
||||
@@ -883,6 +932,14 @@ void GameWorldView::keyPressEvent(QKeyEvent* event)
|
||||
m_ghostRotation = rotateClockwise(m_ghostRotation);
|
||||
m_ghostValid = isValidPlacement(*m_builderType, m_ghostTile, m_ghostRotation);
|
||||
}
|
||||
else if (m_blueprintMode.has_value())
|
||||
{
|
||||
for (BlueprintBuilding& bb : m_blueprintMode->buildings)
|
||||
{
|
||||
bb.offset = QPoint(-bb.offset.y(), bb.offset.x());
|
||||
bb.rotation = rotateClockwise(bb.rotation);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Qt::Key_Q:
|
||||
if (m_builderType.has_value())
|
||||
@@ -890,6 +947,14 @@ void GameWorldView::keyPressEvent(QKeyEvent* event)
|
||||
m_ghostRotation = rotateCounterClockwise(m_ghostRotation);
|
||||
m_ghostValid = isValidPlacement(*m_builderType, m_ghostTile, m_ghostRotation);
|
||||
}
|
||||
else if (m_blueprintMode.has_value())
|
||||
{
|
||||
for (BlueprintBuilding& bb : m_blueprintMode->buildings)
|
||||
{
|
||||
bb.offset = QPoint(bb.offset.y(), -bb.offset.x());
|
||||
bb.rotation = rotateCounterClockwise(bb.rotation);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Qt::Key_Escape:
|
||||
emit escapeMenuRequested();
|
||||
@@ -919,9 +984,10 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() != Qt::LeftButton)
|
||||
{
|
||||
if (event->button() == Qt::RightButton && m_builderType.has_value())
|
||||
if (event->button() == Qt::RightButton)
|
||||
{
|
||||
exitBuilderMode();
|
||||
if (m_builderType.has_value()) { exitBuilderMode(); }
|
||||
else if (m_blueprintMode.has_value()) { exitBlueprintMode(); }
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -942,6 +1008,10 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
placeAtTile(tile);
|
||||
}
|
||||
}
|
||||
else if (m_blueprintMode.has_value())
|
||||
{
|
||||
placeBlueprintAtTile(tile);
|
||||
}
|
||||
else if (m_demolishMode)
|
||||
{
|
||||
EntityId hovered = buildingAtTile(tile);
|
||||
@@ -1012,6 +1082,10 @@ void GameWorldView::mouseMoveEvent(QMouseEvent* event)
|
||||
placeAtTile(tile);
|
||||
}
|
||||
}
|
||||
else if (m_blueprintMode.has_value())
|
||||
{
|
||||
m_blueprintGhostTile = tile;
|
||||
}
|
||||
else if (m_demolishMode)
|
||||
{
|
||||
m_demolishHoverId = buildingAtTile(tile);
|
||||
@@ -1088,7 +1162,8 @@ void GameWorldView::toggleDemolishMode()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_builderType.has_value()) { exitBuilderMode(); }
|
||||
if (m_builderType.has_value()) { exitBuilderMode(); }
|
||||
if (m_blueprintMode.has_value()) { exitBlueprintMode(); }
|
||||
m_demolishMode = true;
|
||||
}
|
||||
emit demolishModeChanged(m_demolishMode);
|
||||
@@ -1100,9 +1175,25 @@ void GameWorldView::enterBuilderMode(BuildingType type)
|
||||
m_ghostRotation = Rotation::East;
|
||||
m_ghostValid = false;
|
||||
m_demolishMode = false;
|
||||
m_blueprintMode.reset();
|
||||
emit demolishModeChanged(false);
|
||||
}
|
||||
|
||||
void GameWorldView::enterBlueprintMode(Blueprint blueprint)
|
||||
{
|
||||
if (m_builderType.has_value()) { exitBuilderMode(); }
|
||||
m_demolishMode = false;
|
||||
emit demolishModeChanged(false);
|
||||
m_blueprintGhostTile = m_ghostTile;
|
||||
m_blueprintMode = std::move(blueprint);
|
||||
}
|
||||
|
||||
void GameWorldView::exitBlueprintMode()
|
||||
{
|
||||
m_blueprintMode.reset();
|
||||
emit blueprintModeExited();
|
||||
}
|
||||
|
||||
void GameWorldView::exitBuilderMode()
|
||||
{
|
||||
m_builderType.reset();
|
||||
@@ -1127,6 +1218,7 @@ void GameWorldView::setGameSpeed(double multiplier)
|
||||
void GameWorldView::resetForNewGame()
|
||||
{
|
||||
exitBuilderMode();
|
||||
exitBlueprintMode();
|
||||
m_activeBeams.clear();
|
||||
m_toasts.clear();
|
||||
m_ghostRotation = Rotation::East;
|
||||
|
||||
Reference in New Issue
Block a user