/** ** Draw formatted text with variable value. ** ** @param unit unit with variable to show. ** @param defaultfont default font if no specific font in extra data. ** ** @note text is limited to 256 chars. (enough?) ** @note text must have exactly 2 %d. ** @bug if text format is incorrect. */ void CContentTypeFormattedText2::Draw(const CUnit *unit, CFont *defaultfont) const { CFont *font; char buf[256]; UStrInt usi1, usi2; Assert(unit); font = this->Font ? this->Font : defaultfont; Assert(font); usi1 = GetComponent(unit, this->Index1, this->Component1, 0); usi2 = GetComponent(unit, this->Index2, this->Component2, 0); if (usi1.type == USTRINT_STR) { if (usi2.type == USTRINT_STR) { sprintf(buf, this->Format, usi1.s, usi2.s); } else { sprintf(buf, this->Format, usi1.s, usi2.i); } } else { if (usi2.type == USTRINT_STR) { sprintf(buf, this->Format, usi1.i, usi2.s); } else { sprintf(buf, this->Format, usi1.i, usi2.i); } } if (this->Centered) { VideoDrawTextCentered(this->PosX, this->PosY, font, buf); } else { VideoDrawText(this->PosX, this->PosY, font, buf); } }
/** ** Draw unit stats */ static void DrawUnitStats(const CUnit *unit) { int x = UI.InfoPanel.X; int y = UI.InfoPanel.Y; CUnitType *type = unit->Type; // Armor std::ostringstream armor; armor << _("Armor: ") << type->Variable[ARMOR_INDEX].Value; VideoDrawText(x + 16, y + 83, GameFont, armor.str()); if (type->Variable[RADAR_INDEX].Value) { // Radar Range std::ostringstream radarRange; radarRange << _("Radar Range: ") << type->Variable[RADAR_INDEX].Value; VideoDrawText(x + 16, y + 97, GameFont, radarRange.str()); } else { // Sight Range std::ostringstream sightRange; sightRange << _("Sight Range: ") << type->Variable[SIGHTRANGE_INDEX].Value; VideoDrawText(x + 16, y + 97, GameFont, sightRange.str()); } if (type->CanAttack) { // Kills std::ostringstream kills; kills << _("Kills: ") << "~<" << unit->Variable[KILL_INDEX].Value << "~>"; VideoDrawTextCentered(x + 114, y + 52, GameFont, kills.str()); // Attack Range std::ostringstream attackRange; attackRange << _("Attack Range: ") << type->Variable[ATTACKRANGE_INDEX].Value; VideoDrawText(x + 16, y + 111, GameFont, attackRange.str()); // Damage int min_damage = std::max(1, type->Variable[PIERCINGDAMAGE_INDEX].Value / 2); int max_damage = type->Variable[PIERCINGDAMAGE_INDEX].Value + type->Variable[BASICDAMAGE_INDEX].Value; std::ostringstream damage; damage << _("Damage: ") << min_damage << "-" << max_damage; VideoDrawText(x + 16, y + 125, GameFont, damage.str()); } else if (unit->Variable[MANA_INDEX].Max != 0) { // Mana std::ostringstream mana; mana << _("Mana: ") << unit->Variable[MANA_INDEX].Value; VideoDrawText(x + 16, y + 111, GameFont, mana.str()); } }
/** ** Draw training units */ static void DrawTrainingUnits(const CUnit *unit) { if (unit->OrderCount == 1 || unit->Orders[1]->Action != UnitActionTrain) { if (!UI.SingleTrainingText.empty()) { VideoDrawText(UI.SingleTrainingTextX, UI.SingleTrainingTextY, UI.SingleTrainingFont, UI.SingleTrainingText); } if (UI.SingleTrainingButton) { CUIButton *button = UI.SingleTrainingButton; bool mouseOver = (ButtonAreaUnderCursor == ButtonAreaTraining && ButtonUnderCursor == 0); unit->Orders[0]->Type->Icon.Icon->DrawUnitIcon(unit->Player, button->Style, mouseOver ? (IconActive | (MouseButtons & LeftButton)) : 0, button->X, button->Y, ""); } } else { if (!UI.TrainingText.empty()) { VideoDrawTextCentered(UI.TrainingTextX, UI.TrainingTextY, UI.TrainingFont, UI.TrainingText); } if (!UI.TrainingButtons.empty()) { size_t currentButton = 0; for (int i = 0; i < unit->OrderCount; ++i) { if (unit->Orders[i]->Action == UnitActionTrain && currentButton < UI.TrainingButtons.size()) { CUIButton *button = &UI.TrainingButtons[i]; bool mouseOver = (ButtonAreaUnderCursor == ButtonAreaTraining && ButtonUnderCursor == i); unit->Orders[i]->Type->Icon.Icon->DrawUnitIcon(unit->Player, button->Style, mouseOver ? (IconActive | (MouseButtons & LeftButton)) : 0, button->X, button->Y, ""); currentButton++; } } } } }
/** ** Draw formatted text with variable value. ** ** @param unit unit with variable to show. ** @param defaultfont default font if no specific font in extra data. ** ** @note text is limited to 256 chars. (enough?) ** @note text must have exactly 1 %d. ** @bug if text format is incorrect. */ void CContentTypeFormattedText::Draw(const CUnit *unit, CFont *defaultfont) const { CFont *font; char buf[256]; UStrInt usi1; Assert(unit); font = this->Font ? this->Font : defaultfont; Assert(font); Assert(0 <= this->Index && this->Index < UnitTypeVar.NumberVariable); usi1 = GetComponent(unit, this->Index, this->Component, 0); if (usi1.type == USTRINT_STR) { sprintf(buf, this->Format, usi1.s); } else { sprintf(buf, this->Format, usi1.i); } if (this->Centered) { VideoDrawTextCentered(this->PosX, this->PosY, font, buf); } else { VideoDrawText(this->PosX, this->PosY, font, buf); } }
/** ** Draw the unit info into top-panel. ** ** @param unit Pointer to unit. */ static void DrawUnitInfo(CUnit *unit) { int i; CUnitType *type; const CUnitStats *stats; int x; int y; CUnit *uins; Assert(unit); UpdateUnitVariables(unit); for (i = 0; i < (int)UI.InfoPanelContents.size(); ++i) { if (CanShowContent(UI.InfoPanelContents[i]->Condition, unit)) { for (std::vector<CContentType *>::const_iterator content = UI.InfoPanelContents[i]->Contents.begin(); content != UI.InfoPanelContents[i]->Contents.end(); ++content) { if (CanShowContent((*content)->Condition, unit)) { (*content)->Draw(unit, UI.InfoPanelContents[i]->DefaultFont); } } } } type = unit->Type; stats = unit->Stats; Assert(type); Assert(stats); // Draw IconUnit #ifdef USE_MNG if (type->Portrait.Num) { type->Portrait.Mngs[type->Portrait.CurrMng]->Draw( UI.SingleSelectedButton->X, UI.SingleSelectedButton->Y); if (type->Portrait.Mngs[type->Portrait.CurrMng]->iteration == type->Portrait.NumIterations) { type->Portrait.Mngs[type->Portrait.CurrMng]->Reset(); // FIXME: should be configurable if (type->Portrait.CurrMng == 0) { type->Portrait.CurrMng = (SyncRand() % (type->Portrait.Num - 1)) + 1; type->Portrait.NumIterations = 1; } else { type->Portrait.CurrMng = 0; type->Portrait.NumIterations = SyncRand() % 16 + 1; } } } else #endif if (UI.SingleSelectedButton) { x = UI.SingleSelectedButton->X; y = UI.SingleSelectedButton->Y; type->Icon.Icon->DrawUnitIcon(unit->Player, UI.SingleSelectedButton->Style, (ButtonAreaUnderCursor == ButtonAreaSelected && ButtonUnderCursor == 0) ? (IconActive | (MouseButtons & LeftButton)) : 0, x, y, ""); } x = UI.InfoPanel.X; y = UI.InfoPanel.Y; // // Show progress if they are selected. // if (NumSelected == 1 && Selected[0] == unit) { // // Building training units. // if (unit->Orders[0]->Action == UnitActionTrain) { if (unit->OrderCount == 1 || unit->Orders[1]->Action != UnitActionTrain) { if (!UI.SingleTrainingText.empty()) { VideoDrawText(UI.SingleTrainingTextX, UI.SingleTrainingTextY, UI.SingleTrainingFont, UI.SingleTrainingText); } if (UI.SingleTrainingButton) { unit->Orders[0]->Type->Icon.Icon->DrawUnitIcon(unit->Player, UI.SingleTrainingButton->Style, (ButtonAreaUnderCursor == ButtonAreaTraining && ButtonUnderCursor == 0) ? (IconActive | (MouseButtons & LeftButton)) : 0, UI.SingleTrainingButton->X, UI.SingleTrainingButton->Y, ""); } } else { if (!UI.TrainingText.empty()) { VideoDrawTextCentered(UI.TrainingTextX, UI.TrainingTextY, UI.TrainingFont, UI.TrainingText); } if (!UI.TrainingButtons.empty()) { for (i = 0; i < unit->OrderCount && i < (int)UI.TrainingButtons.size(); ++i) { if (unit->Orders[i]->Action == UnitActionTrain) { unit->Orders[i]->Type->Icon.Icon->DrawUnitIcon(unit->Player, UI.TrainingButtons[i].Style, (ButtonAreaUnderCursor == ButtonAreaTraining && ButtonUnderCursor == i) ? (IconActive | (MouseButtons & LeftButton)) : 0, UI.TrainingButtons[i].X, UI.TrainingButtons[i].Y, ""); } } } } return; } // // Building upgrading to better type. // if (unit->Orders[0]->Action == UnitActionUpgradeTo) { if (UI.UpgradingButton) { unit->Orders[0]->Type->Icon.Icon->DrawUnitIcon(unit->Player, UI.UpgradingButton->Style, (ButtonAreaUnderCursor == ButtonAreaUpgrading && ButtonUnderCursor == 0) ? (IconActive | (MouseButtons & LeftButton)) : 0, UI.UpgradingButton->X, UI.UpgradingButton->Y, ""); } return; } // // Building research new technology. // if (unit->Orders[0]->Action == UnitActionResearch) { if (UI.ResearchingButton) { unit->Data.Research.Upgrade->Icon->DrawUnitIcon(unit->Player, UI.ResearchingButton->Style, (ButtonAreaUnderCursor == ButtonAreaResearching && ButtonUnderCursor == 0) ? (IconActive | (MouseButtons & LeftButton)) : 0, UI.ResearchingButton->X, UI.ResearchingButton->Y, ""); } return; } } // // Transporting units. // if (type->CanTransport && unit->BoardCount) { int j; uins = unit->UnitInside; for (i = j = 0; i < unit->InsideCount; ++i, uins = uins->NextContained) { if (uins->Boarded && j < (int)UI.TransportingButtons.size()) { uins->Type->Icon.Icon->DrawUnitIcon(unit->Player, UI.TransportingButtons[j].Style, (ButtonAreaUnderCursor == ButtonAreaTransporting && ButtonUnderCursor == j) ? (IconActive | (MouseButtons & LeftButton)) : 0, UI.TransportingButtons[j].X, UI.TransportingButtons[j].Y, ""); UiDrawLifeBar(uins, UI.TransportingButtons[j].X, UI.TransportingButtons[j].Y); if (uins->Type->CanCastSpell && uins->Variable[MANA_INDEX].Max) { UiDrawManaBar(uins, UI.TransportingButtons[j].X, UI.TransportingButtons[j].Y); } if (ButtonAreaUnderCursor == ButtonAreaTransporting && ButtonUnderCursor == j) { UI.StatusLine.Set(uins->Type->Name); } ++j; } } return; } }
/** ** Draw text with variable. ** ** @param unit unit with variable to show. ** @param defaultfont default font if no specific font in extra data. */ void CContentTypeText::Draw(const CUnit *unit, CFont *defaultfont) const { char *text; // Optional text to display. CFont *font; // Font to use. int x; // X coordinate to display. int y; // Y coordinate to display. x = this->PosX; y = this->PosY; font = this->Font ? this->Font : defaultfont; Assert(font); Assert(unit || this->Index == -1); Assert(this->Index == -1 || (0 <= this->Index && this->Index < UnitTypeVar.NumberVariable)); if (this->Text) { text = EvalString(this->Text); if (this->Centered) { VideoDrawTextCentered(x, y, font, text); } else { VideoDrawText(x, y, font, text); } x += font->Width(text); delete[] text; } if (this->ShowName) { VideoDrawTextCentered(x, y, font, unit->Type->Name); return; } if (this->Index != -1) { if (!this->Stat) { EnumVariable component = this->Component; switch (component) { case VariableValue: case VariableMax: case VariableIncrease: case VariableDiff: case VariablePercent: VideoDrawNumber(x, y, font, GetComponent(unit, this->Index, component, 0).i); break; case VariableName: VideoDrawText(x, y, font, GetComponent(unit, this->Index, component, 0).s); break; default: Assert(0); } } else { int value = unit->Type->Variable[this->Index].Value; int diff = unit->Stats->Variables[this->Index].Value - value; if (!diff) { VideoDrawNumber(x, y, font, value); } else { char buf[64]; sprintf(buf, diff > 0 ? "%d~<+%d~>" : "%d~<-%d~>", value, diff); VideoDrawText(x, y, font, buf); } } } }
/** ** Draw the unit info in the info panel. ** Called when a single unit is selected or the mouse hovers over a unit. ** ** @param unit Pointer to unit. */ static void DrawUnitInfo(CUnit *unit) { int x = UI.InfoPanel.X; int y = UI.InfoPanel.Y; bool isEnemy = unit->IsEnemy(ThisPlayer); bool isNeutral = (unit->Player->Type == PlayerNeutral); UpdateUnitVariables(unit); // Draw icon and life bar if (UI.SingleSelectedButton) { CUIButton *button = UI.SingleSelectedButton; bool mouseOver = (ButtonAreaUnderCursor == ButtonAreaSelected && ButtonUnderCursor == 0); unit->Type->Icon.Icon->DrawUnitIcon(unit->Player, button->Style, mouseOver ? (IconActive | (MouseButtons & LeftButton)) : 0, button->X, button->Y, ""); if (!isNeutral) { UiDrawLifeBar(unit, button->X, button->Y); } } // Unit type name VideoDrawTextCentered(x + 114, y + 25, GameFont, unit->Type->Name); // Hit points if (!isEnemy && !isNeutral) { std::ostringstream os; os << unit->Variable[HP_INDEX].Value << "/" << unit->Variable[HP_INDEX].Max; VideoDrawTextCentered(x + 38, y + 62, SmallFont, os.str()); } // Resource amount if (unit->Type->CanHarvestFrom && isNeutral) { std::string resourceName; int amount = 0; for (int i = 0; i < MaxCosts; ++i) { if (unit->ResourcesHeld[i] != 0) { resourceName = _(DefaultDisplayResourceNames[i].c_str()); amount = unit->ResourcesHeld[i] / CYCLES_PER_SECOND; break; } } std::ostringstream os; os << resourceName << ": " << amount; VideoDrawTextCentered(x + 76, y + 86, GameFont, os.str()); } // // Show extra info if only one unit is selected. // if (NumSelected == 1 && Selected[0] == unit) { // Training units. if (!isEnemy && unit->Orders[0]->Action == UnitActionTrain) { DrawTrainingUnits(unit); return; } // Transporting units. if (!isEnemy && unit->Type->CanTransport && unit->BoardCount) { DrawTransportingUnits(unit); return; } // My unit stats if (!isEnemy && !isNeutral && unit->Orders[0]->Action != UnitActionBuilt) { DrawUnitStats(unit); } } }
/** ** Draw menu button 'button' on x,y ** ** @param style Button style ** @param flags State of Button (clicked, mouse over...) ** @param x X display position ** @param y Y display position ** @param text text to print on button */ void DrawMenuButton(ButtonStyle *style, unsigned flags, int x, int y, const std::string &text) { std::string *nc; std::string *rc; std::string oldnc; std::string oldrc; ButtonStyleProperties *p; ButtonStyleProperties *pimage; if (flags & MI_FLAGS_CLICKED) { p = &style->Clicked; } else if (flags & MI_FLAGS_ACTIVE) { p = &style->Hover; } else { p = &style->Default; } // // Image // pimage = p; if (!p->Sprite) { // No image. Try hover, selected, then default if ((flags & MI_FLAGS_ACTIVE) && style->Hover.Sprite) { pimage = &style->Hover; } else if (style->Default.Sprite) { pimage = &style->Default; } } if (pimage->Sprite) { pimage->Sprite->Load(); } if (pimage->Sprite) { pimage->Sprite->DrawFrame(pimage->Frame, x, y); } // // Text // if (!text.empty()) { GetDefaultTextColors(oldnc, oldrc); nc = !p->TextNormalColor.empty() ? &p->TextNormalColor : !style->TextNormalColor.empty() ? &style->TextNormalColor : &oldnc; rc = !p->TextReverseColor.empty() ? &p->TextReverseColor : !style->TextReverseColor.empty() ? &style->TextReverseColor : &oldrc; SetDefaultTextColors(*nc, *rc); if (p->TextAlign == TextAlignCenter || p->TextAlign == TextAlignUndefined) { VideoDrawTextCentered(x + p->TextX, y + p->TextY, style->Font, text); } else if (p->TextAlign == TextAlignLeft) { VideoDrawText(x + p->TextX, y + p->TextY, style->Font, text); } else { VideoDrawText(x + p->TextX - style->Font->Width(text), y + p->TextY, style->Font, text); } SetDefaultTextColors(oldnc, oldrc); } // // Border // if (!p->BorderColor) { p->BorderColor = Video.MapRGB(TheScreen->format, p->BorderColorRGB.r, p->BorderColorRGB.g, p->BorderColorRGB.b); } if (p->BorderSize) { for (int i = 0; i < p->BorderSize; ++i) { Video.DrawRectangleClip(p->BorderColor, x - i, y - i, style->Width + 2 * i, style->Height + 2 * i); } } }