// Checks if the floor has any passengers going up by iterating through the // passenger list bool Floor::hasPassengersGoingUp() { bool status = false; std::list<Passenger>::const_iterator iter = getPassengers().begin(); while(iter != getPassengers().end()) { if(iter->getStartFloor() < iter->getEndFloor()) { status = true; break; } ++iter; } return status; }
void VEquipScreen::Render() { this->equippedItems.clear(); this->inventoryItems.clear(); fw().Stage_GetPrevious(this->shared_from_this())->Render(); fw().renderer->setPalette(this->pal); fw().renderer->drawFilledRect({0, 0}, fw().Display_GetSize(), Colour{0, 0, 0, 128}); // The labels/values in the stats column are used for lots of different things, so keep them // around clear them and keep them around in a vector so we don't have 5 copies of the same // "reset unused entries" code around std::vector<sp<Label>> statsLabels; std::vector<sp<Label>> statsValues; for (int i = 0; i < 9; i++) { auto labelName = UString::format("LABEL_%d", i + 1); auto label = form->FindControlTyped<Label>(labelName); if (!label) { LogError("Failed to find UI control matching \"%s\"", labelName.c_str()); } label->SetText(""); statsLabels.push_back(label); auto valueName = UString::format("VALUE_%d", i + 1); auto value = form->FindControlTyped<Label>(valueName); if (!value) { LogError("Failed to find UI control matching \"%s\"", valueName.c_str()); } value->SetText(""); statsValues.push_back(value); } auto nameLabel = form->FindControlTyped<Label>("NAME"); auto iconGraphic = form->FindControlTyped<Graphic>("SELECTED_ICON"); // If no vehicle/equipment is highlighted (mouse-over), or if we're dragging equipment around // show the currently selected vehicle stats. // // Otherwise we show the stats of the vehicle/equipment highlighted. if (highlightedEquipment) { iconGraphic->SetImage(highlightedEquipment->equipscreen_sprite); nameLabel->SetText(tr(highlightedEquipment->name)); int statsCount = 0; // All equipment has a weight statsLabels[statsCount]->SetText(tr("Weight")); statsValues[statsCount]->SetText(UString::format("%d", highlightedEquipment->weight)); statsCount++; // Draw equipment stats switch (highlightedEquipment->type) { case VEquipmentType::Type::Engine: { auto &engineType = static_cast<const VEngineType &>(*highlightedEquipment); statsLabels[statsCount]->SetText(tr("Top Speed")); statsValues[statsCount]->SetText(UString::format("%d", engineType.top_speed)); statsCount++; statsLabels[statsCount]->SetText(tr("Power")); statsValues[statsCount]->SetText(UString::format("%d", engineType.power)); break; } case VEquipmentType::Type::Weapon: { auto &weaponType = static_cast<const VWeaponType &>(*highlightedEquipment); statsLabels[statsCount]->SetText(tr("Damage")); statsValues[statsCount]->SetText(UString::format("%d", weaponType.damage)); statsCount++; statsLabels[statsCount]->SetText(tr("Range")); statsValues[statsCount]->SetText(UString::format("%d", weaponType.range)); statsCount++; statsLabels[statsCount]->SetText(tr("Accuracy")); statsValues[statsCount]->SetText(UString::format("%d", weaponType.accuracy)); statsCount++; // Only show rounds if non-zero (IE not infinite ammo) if (highlightedEquipment->max_ammo) { statsLabels[statsCount]->SetText(tr("Rounds")); statsValues[statsCount]->SetText( UString::format("%d", highlightedEquipment->max_ammo)); statsCount++; } break; } case VEquipmentType::Type::General: { auto &generalType = static_cast<const VGeneralEquipmentType &>(*highlightedEquipment); if (generalType.accuracy_modifier) { statsLabels[statsCount]->SetText(tr("Accuracy")); statsValues[statsCount]->SetText( UString::format("%d", generalType.accuracy_modifier)); statsCount++; } if (generalType.cargo_space) { statsLabels[statsCount]->SetText(tr("Cargo")); statsValues[statsCount]->SetText( UString::format("%d", generalType.cargo_space)); statsCount++; } if (generalType.passengers) { statsLabels[statsCount]->SetText(tr("Passengers")); statsValues[statsCount]->SetText(UString::format("%d", generalType.passengers)); statsCount++; } if (generalType.alien_space) { statsLabels[statsCount]->SetText(tr("Aliens Held")); statsValues[statsCount]->SetText( UString::format("%d", generalType.alien_space)); statsCount++; } if (generalType.missile_jamming) { statsLabels[statsCount]->SetText(tr("Jamming")); statsValues[statsCount]->SetText( UString::format("%d", generalType.missile_jamming)); statsCount++; } if (generalType.shielding) { statsLabels[statsCount]->SetText(tr("Shielding")); statsValues[statsCount]->SetText(UString::format("%d", generalType.shielding)); statsCount++; } if (generalType.cloaking) { statsLabels[statsCount]->SetText(tr("Cloaks Craft")); statsCount++; } if (generalType.teleporting) { statsLabels[statsCount]->SetText(tr("Teleports")); statsCount++; } break; } } } else { auto vehicle = this->highlightedVehicle; if (!vehicle) vehicle = this->selected; nameLabel->SetText(vehicle->name); // FIXME: These stats would be great to have a generic (string?) referenced list statsLabels[0]->SetText(tr("Constitution")); if (vehicle->getConstitution() == vehicle->getMaxConstitution()) { statsValues[0]->SetText(UString::format("%d", vehicle->getConstitution())); } else { statsValues[0]->SetText(UString::format("%d/%d", vehicle->getConstitution(), vehicle->getMaxConstitution())); } statsLabels[1]->SetText(tr("Armor")); statsValues[1]->SetText(UString::format("%d", vehicle->getArmor())); // FIXME: This value doesn't seem to be the same as the %age shown in the ui? statsLabels[2]->SetText(tr("Accuracy")); statsValues[2]->SetText(UString::format("%d", vehicle->getAccuracy())); statsLabels[3]->SetText(tr("Top Speed")); statsValues[3]->SetText(UString::format("%d", vehicle->getTopSpeed())); statsLabels[4]->SetText(tr("Acceleration")); statsValues[4]->SetText(UString::format("%d", vehicle->getAcceleration())); statsLabels[5]->SetText(tr("Weight")); statsValues[5]->SetText(UString::format("%d", vehicle->getWeight())); statsLabels[6]->SetText(tr("Fuel")); statsValues[6]->SetText(UString::format("%d", vehicle->getFuel())); statsLabels[7]->SetText(tr("Passengers")); statsValues[7]->SetText( UString::format("%d/%d", vehicle->getPassengers(), vehicle->getMaxPassengers())); statsLabels[8]->SetText(tr("Cargo")); statsValues[8]->SetText( UString::format("%d/%d", vehicle->getCargo(), vehicle->getMaxCargo())); iconGraphic->SetImage(vehicle->type.equip_icon_small); } // Now draw the form, the actual equipment is then drawn on top form->Render(); auto paperDollControl = form->FindControlTyped<Graphic>("PAPER_DOLL"); Vec2<int> equipOffset = paperDollControl->Location + form->Location; // Draw the equipment grid { for (auto &slot : selected->type.equipment_layout_slots) { Vec2<int> p00 = (slot.bounds.p0 * EQUIP_GRID_SLOT_SIZE) + equipOffset; Vec2<int> p11 = (slot.bounds.p1 * EQUIP_GRID_SLOT_SIZE) + equipOffset; Vec2<int> p01 = {p00.x, p11.y}; Vec2<int> p10 = {p11.x, p00.y}; if (slot.type == selectionType) { // Scale the sin curve from (-1, 1) to (0, 1) float glowFactor = (sin(this->glowCounter) + 1.0f) / 2.0f; Colour equipColour; switch (selectionType) { case VEquipmentType::Type::Engine: equipColour = EQUIP_GRID_COLOUR_ENGINE; break; case VEquipmentType::Type::Weapon: equipColour = EQUIP_GRID_COLOUR_WEAPON; break; case VEquipmentType::Type::General: equipColour = EQUIP_GRID_COLOUR_GENERAL; break; } Colour selectedColour; selectedColour.r = mix(equipColour.r, EQUIP_GRID_COLOUR.r, glowFactor); selectedColour.g = mix(equipColour.g, EQUIP_GRID_COLOUR.g, glowFactor); selectedColour.b = mix(equipColour.b, EQUIP_GRID_COLOUR.b, glowFactor); selectedColour.a = 255; fw().renderer->drawLine(p00, p01, selectedColour, 2); fw().renderer->drawLine(p01, p11, selectedColour, 2); fw().renderer->drawLine(p11, p10, selectedColour, 2); fw().renderer->drawLine(p10, p00, selectedColour, 2); } else { fw().renderer->drawLine(p00, p01, EQUIP_GRID_COLOUR, 2); fw().renderer->drawLine(p01, p11, EQUIP_GRID_COLOUR, 2); fw().renderer->drawLine(p11, p10, EQUIP_GRID_COLOUR, 2); fw().renderer->drawLine(p10, p00, EQUIP_GRID_COLOUR, 2); } } } // Draw the equipped stuff for (auto &e : selected->equipment) { auto pos = e->equippedPosition; VehicleType::AlignmentX alignX = VehicleType::AlignmentX::Left; VehicleType::AlignmentY alignY = VehicleType::AlignmentY::Top; Rect<int> slotBounds; bool slotFound = false; for (auto &slot : this->selected->type.equipment_layout_slots) { if (slot.bounds.p0 == pos) { alignX = slot.align_x; alignY = slot.align_y; slotBounds = slot.bounds; slotFound = true; break; } } if (!slotFound) { LogError("No matching slot for equipment at {%d,%d}", pos.x, pos.y); } if (pos.x >= EQUIP_GRID_SLOTS.x || pos.y >= EQUIP_GRID_SLOTS.y) { LogError("Equipment at {%d,%d} outside grid", pos.x, pos.y); } pos *= EQUIP_GRID_SLOT_SIZE; pos += equipOffset; int diffX = slotBounds.getWidth() - e->type.equipscreen_size.x; int diffY = slotBounds.getHeight() - e->type.equipscreen_size.y; switch (alignX) { case VehicleType::AlignmentX::Left: pos.x += 0; break; case VehicleType::AlignmentX::Right: pos.x += diffX * EQUIP_GRID_SLOT_SIZE.x; break; case VehicleType::AlignmentX::Centre: pos.x += (diffX * EQUIP_GRID_SLOT_SIZE.x) / 2; break; } switch (alignY) { case VehicleType::AlignmentY::Top: pos.y += 0; break; case VehicleType::AlignmentY::Bottom: pos.y += diffY * EQUIP_GRID_SLOT_SIZE.y; break; case VehicleType::AlignmentY::Centre: pos.y += (diffY * EQUIP_GRID_SLOT_SIZE.y) / 2; break; } fw().renderer->draw(e->type.equipscreen_sprite, pos); Vec2<int> endPos = pos; endPos.x += e->type.equipscreen_sprite->size.x; endPos.y += e->type.equipscreen_sprite->size.y; this->equippedItems.emplace_back(std::make_pair(Rect<int>{pos, endPos}, e)); } // Only draw inventory that can be used by this type of craft VEquipmentType::User allowedEquipmentUser; switch (this->selected->type.type) { case VehicleType::Type::Flying: allowedEquipmentUser = VEquipmentType::User::Air; break; case VehicleType::Type::Ground: allowedEquipmentUser = VEquipmentType::User::Ground; break; default: LogError( "Trying to draw equipment screen of unsupported vehicle type for vehicle \"%s\"", this->selected->name.c_str()); allowedEquipmentUser = VEquipmentType::User::Air; } // Draw the inventory if the selected is in a building, and that is a base auto bld = this->selected->building.lock(); sp<Base> base; if (bld) { base = bld->base; } if (base) { auto inventoryControl = form->FindControlTyped<Graphic>("INVENTORY"); Vec2<int> inventoryPosition = inventoryControl->Location + form->Location; for (auto &invPair : base->inventory) { // The gap between the bottom of the inventory image and the count label static const int INVENTORY_COUNT_Y_GAP = 4; // The gap between the end of one inventory image and the start of the next static const int INVENTORY_IMAGE_X_GAP = 4; auto equipIt = state->getRules().getVehicleEquipmentTypes().find(invPair.first); if (equipIt == state->getRules().getVehicleEquipmentTypes().end()) { // It's not vehicle equipment, skip continue; } auto &equipmentType = *equipIt->second; if (equipmentType.type != this->selectionType) { // Skip equipment of different types continue; } if (!equipmentType.users.count(allowedEquipmentUser)) { // The selected vehicle is not a valid user of the equipment, don't draw continue; } int count = invPair.second; if (count == 0) { // Not in stock continue; } auto countImage = labelFont->getString(UString::format("%d", count)); auto &equipmentImage = equipmentType.equipscreen_sprite; fw().renderer->draw(equipmentImage, inventoryPosition); Vec2<int> countLabelPosition = inventoryPosition; countLabelPosition.y += INVENTORY_COUNT_Y_GAP + equipmentImage->size.y; // FIXME: Center in X? fw().renderer->draw(countImage, countLabelPosition); Vec2<int> inventoryEndPosition = inventoryPosition; inventoryEndPosition.x += equipmentImage->size.x; inventoryEndPosition.y += equipmentImage->size.y; this->inventoryItems.emplace_back(Rect<int>{inventoryPosition, inventoryEndPosition}, equipmentType); // Progress inventory offset by width of image + gap inventoryPosition.x += INVENTORY_IMAGE_X_GAP + equipmentImage->size.x; } } if (this->drawHighlightBox) { Vec2<int> p00 = highlightBox.p0; Vec2<int> p11 = highlightBox.p1; Vec2<int> p01 = {p00.x, p11.y}; Vec2<int> p10 = {p11.x, p00.y}; fw().renderer->drawLine(p00, p01, highlightBoxColour, 1); fw().renderer->drawLine(p01, p11, highlightBoxColour, 1); fw().renderer->drawLine(p11, p10, highlightBoxColour, 1); fw().renderer->drawLine(p10, p00, highlightBoxColour, 1); } if (this->draggedEquipment) { // Draw equipment we're currently dragging (snapping to the grid if possible) Vec2<int> equipmentPos = fw().gamecore->MouseCursor->getPosition() + this->draggedEquipmentOffset; // If this is within the grid try to snap it Vec2<int> equipmentGridPos = equipmentPos - equipOffset; equipmentGridPos /= EQUIP_GRID_SLOT_SIZE; if (equipmentGridPos.x < 0 || equipmentGridPos.x >= EQUIP_GRID_SLOTS.x || equipmentGridPos.y < 0 || equipmentGridPos.y >= EQUIP_GRID_SLOTS.y) { // This is outside thge grid } else { // Inside the grid, snap equipmentPos = equipmentGridPos * EQUIP_GRID_SLOT_SIZE; equipmentPos += equipOffset; } fw().renderer->draw(this->draggedEquipment->equipscreen_sprite, equipmentPos); } fw().gamecore->MouseCursor->Render(); }