/* * CardGui.cpp * This class is in charge of rendering Cards on the screen */ #include "PrecompiledHeader.h" #include "JGE.h" #include "CardGui.h" #include "ManaCostHybrid.h" #include "Subtypes.h" #include "Translate.h" #include "MTGDefinitions.h" #include "GameObserver.h" #include #include "Counters.h" const float CardGui::Width = 28.0; const float CardGui::Height = 40.0; const float CardGui::BigWidth = 200.0; const float CardGui::BigHeight = 285.0; const float kWidthScaleFactor = 0.8f; map CardGui::counterGraphics; namespace { inline float SineHelperFunction(const float& value) { return sinf(2 * M_PI * (value) / 256.0f); } inline float CosineHelperFunction(const float& value) { return cosf(2 * M_PI * (value - 35) / 256.0f); } } CardGui::CardGui(MTGCardInstance* card, float x, float y) : PlayGuiObject(Height, x, y, 0, false), card(card) { } CardGui::CardGui(MTGCardInstance* card, const Pos& ref) : PlayGuiObject(Height, ref, 0, false), card(card) { } float CardView::GetCenterX() { bool largeCard = mHeight == BigHeight; float centerX = x + (largeCard ? BigWidth : Width) * 0.5f * zoom; return centerX; } float CardView::GetCenterY() { bool largeCard = mHeight == BigHeight; float centerY = y + (largeCard ? BigHeight : Height) * 0.5f * zoom; return centerY; } CardView::CardView(const SelectorZone owner, MTGCardInstance* card, float x, float y) : CardGui(card, x, y), owner(owner) { const Pos* ref = card->view; while (card) { if (ref == card->view) card->view = this; card = card->next; } } CardView::CardView(const SelectorZone owner, MTGCardInstance* card, const Pos& ref) : CardGui(card, ref), owner(owner) { const Pos* r = card->view; while (card) { if (r == card->view) card->view = this; card = card->next; } } CardView::~CardView() { if (card) { const Pos* r = this; while (card) { if (r == card->view) card->view = NULL; card = card->next; } } } void CardGui::Update(float dt) { PlayGuiObject::Update(dt); } void CardGui::DrawCard(const Pos& inPosition, int inMode) { DrawCard(card, inPosition, inMode); } void CardGui::DrawCard(MTGCard* inCard, const Pos& inPosition, int inMode) { switch (inMode) { case DrawMode::kNormal: RenderBig(inCard, inPosition); break; case DrawMode::kText: AlternateRender(inCard, inPosition); break; default: break; } } void CardGui::Render() { WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); JRenderer * renderer = JRenderer::GetInstance(); GameObserver * game = GameObserver::GetInstance(); TargetChooser * tc = NULL; if (game) tc = game->getCurrentTargetChooser(); bool alternate = true; JQuadPtr quad = WResourceManager::Instance()->RetrieveCard(card, CACHE_THUMB); if (quad.get()) alternate = false; else quad = AlternateThumbQuad(card); float cardScale = quad ? 40 / quad->mHeight : 1; float scale = actZ * cardScale; JQuadPtr shadow; if (actZ > 1) { shadow = WResourceManager::Instance()->GetQuad("shadow"); shadow->SetColor(ARGB(static_cast(actA)/2,255,255,255)); renderer->RenderQuad(shadow.get(), actX + (actZ - 1) * 15, actY + (actZ - 1) * 15, actT, 28 * actZ / 16, 40 * actZ / 16); } JQuadPtr extracostshadow; if (card->isExtraCostTarget) { extracostshadow = WResourceManager::Instance()->GetQuad("extracostshadow"); extracostshadow->SetColor(ARGB(static_cast(actA)/2,100,0,0)); renderer->RenderQuad(extracostshadow.get(), actX + (actZ - 1) * 15, actY + (actZ - 1) * 15, actT, 28 * actZ / 16, 40 * actZ / 16); } // Am I a parent of a selected card, or am I a parent and myself being selected? bool isActiveConnectedParent = mHasFocus && card->childrenCards.size(); if (!isActiveConnectedParent) { for (size_t i = 0; i < card->childrenCards.size(); ++i) { MTGCardInstance * child = card->childrenCards[i]; if (CardView* cv = dynamic_cast(child->view)) { if (cv->mHasFocus) { isActiveConnectedParent = true; break; } } } } if (isActiveConnectedParent) { JQuadPtr white = WResourceManager::Instance()->GetQuad("white"); white->SetColor(ARGB(255,230,50,50)); renderer->RenderQuad(white.get(), actX, actY, actT, 30 * actZ / 16, 42 * actZ / 16); } // Am I a child of a selected card, or am I a child and myself being selected? bool isActiveConnectedChild = mHasFocus && card->parentCards.size(); if (!isActiveConnectedChild) { for (size_t i = 0; i < card->parentCards.size(); ++i) { MTGCardInstance * parent = card->parentCards[i]; if (CardView* cv = dynamic_cast(parent->view)) { if (cv->mHasFocus) { isActiveConnectedChild = true; break; } } } } if (isActiveConnectedChild) { JQuadPtr white = WResourceManager::Instance()->GetQuad("white"); white->SetColor(ARGB(255,0,0,255)); renderer->RenderQuad(white.get(), actX, actY, actT, 30 * actZ / 16, 42 * actZ / 16); } if (quad) { quad->SetColor(ARGB(static_cast(actA),255,255,255)); renderer->RenderQuad(quad.get(), actX, actY, actT, scale, scale); } if (alternate) { mFont->SetColor(ARGB(static_cast(actA), 0, 0, 0)); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE * 0.5f * actZ); mFont->DrawString(_(card->getName()), actX - actZ * Width / 2 + 1, actY - actZ * Height / 2 + 1); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); JQuadPtr icon; if (card->hasSubtype("plains")) icon = WResourceManager::Instance()->GetQuad("c_white"); else if (card->hasSubtype("swamp")) icon = WResourceManager::Instance()->GetQuad("c_black"); else if (card->hasSubtype("forest")) icon = WResourceManager::Instance()->GetQuad("c_green"); else if (card->hasSubtype("mountain")) icon = WResourceManager::Instance()->GetQuad("c_red"); else if (card->hasSubtype("island")) icon = WResourceManager::Instance()->GetQuad("c_blue"); if (icon.get()) { icon->SetColor(ARGB(static_cast(actA),255,255,255)); renderer->RenderQuad(icon.get(), actX, actY, 0); icon->SetColor(ARGB(255,255,255,255)); //Putting color back as this quad is shared } } JQuadPtr mor; if(card->isMorphed && !alternate) { mor = WResourceManager::Instance()->GetQuad("morph"); mor->SetColor(ARGB(255,255,255,255)); renderer->RenderQuad(mor.get(), actX, actY, actT,scale, scale); } //draws the numbers power/toughness if (card->isCreature()) { mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); char buffer[200]; sprintf(buffer, "%i/%i", card->power, card->life); renderer->FillRect(actX - (12 * actZ), actY + 6 * actZ, 25 * actZ, 12 * actZ, ARGB(((static_cast(actA))/2),0,0,0)); mFont->SetColor(ARGB(static_cast(actA),255,255,255)); mFont->SetScale(actZ); mFont->DrawString(buffer, actX - 10 * actZ, actY + 8 * actZ); mFont->SetScale(1); } if (card->counters->mCount > 0) { unsigned c = -1; for (int i = 0; i < card->counters->mCount; i++) { if (card->counters->counters[i]->name != "") c = i; break; } if (c + 1) { mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); char buffer[200]; sprintf(buffer, "%i", card->counters->counters[0]->nb); mFont->SetColor(ARGB(static_cast(actA),255,255,255)); mFont->SetScale(actZ); mFont->DrawString(buffer, actX - 10 * actZ, actY - (12 * actZ)); mFont->SetScale(1); } } if (tc && !tc->canTarget(card)) { if (!shadow) shadow = WResourceManager::Instance()->GetQuad("shadow"); shadow->SetColor(ARGB(200,255,255,255)); renderer->RenderQuad(shadow.get(), actX, actY, actT, (28 * actZ + 1) / 16, 40 * actZ / 16); } // Render a mask over the card, if set if (mask && quad) JRenderer::GetInstance()->FillRect(actX - (scale * quad->mWidth / 2),actY - (scale * quad->mHeight / 2), scale * quad->mWidth, scale* quad->mHeight, mask); if ((tc && tc->alreadyHasTarget(card)) || (game && card == game->mLayers->actionLayer()->currentActionCard))//paint targets red. { if (card->isTapped()) { renderer->FillRect(actX - (scale * quad->mWidth / 2)-7,actY - (scale * quad->mHeight / 2)+7,scale* quad->mHeight,scale * quad->mWidth, ARGB(128,255,0,0)); } else { renderer->FillRect(actX - (scale * quad->mWidth / 2),actY - (scale * quad->mHeight / 2), scale * quad->mWidth, scale* quad->mHeight, ARGB(128,255,0,0)); } } if(tc && tc->source && tc->source->view && tc->source->view->actZ >= 1.3 && card == tc->source)//paint the source green while infocus. { if (tc->source->isTapped()) { renderer->FillRect(actX - (scale * quad->mWidth / 2)-7,actY - (scale * quad->mHeight / 2)+7,scale* quad->mHeight,scale * quad->mWidth, ARGB(128,0,255,0)); } else { renderer->FillRect(tc->source->view->actX - (scale * quad->mWidth / 2),tc->source->view->actY - (scale * quad->mHeight / 2), scale*quad->mWidth, scale*quad->mHeight, ARGB(128,0,255,0)); } } PlayGuiObject::Render(); } JQuadPtr CardGui::AlternateThumbQuad(MTGCard * card) { JQuadPtr q; if (card->data->countColors() > 1) { q = WResourceManager::Instance()->RetrieveTempQuad("gold_thumb.jpg"); } else { switch (card->data->getColor()) { case Constants::MTG_COLOR_ARTIFACT: q = WResourceManager::Instance()->RetrieveTempQuad("artifact_thumb.jpg"); break; case Constants::MTG_COLOR_GREEN: q = WResourceManager::Instance()->RetrieveTempQuad("green_thumb.jpg"); break; case Constants::MTG_COLOR_BLUE: q = WResourceManager::Instance()->RetrieveTempQuad("blue_thumb.jpg"); break; case Constants::MTG_COLOR_RED: q = WResourceManager::Instance()->RetrieveTempQuad("red_thumb.jpg"); break; case Constants::MTG_COLOR_BLACK: q = WResourceManager::Instance()->RetrieveTempQuad("black_thumb.jpg"); break; case Constants::MTG_COLOR_WHITE: q = WResourceManager::Instance()->RetrieveTempQuad("white_thumb.jpg"); break; case Constants::MTG_COLOR_LAND: q = WResourceManager::Instance()->RetrieveTempQuad("land_thumb.jpg"); break; default: q = WResourceManager::Instance()->RetrieveTempQuad("gold_thumb.jpg"); break; } } if (q && q->mTex) q->SetHotSpot(static_cast (q->mTex->mWidth / 2), static_cast (q->mTex->mHeight / 2)); return q; } void CardGui::AlternateRender(MTGCard * card, const Pos& pos) { // Draw the "unknown" card model JRenderer * renderer = JRenderer::GetInstance(); JQuadPtr q; float x = pos.actX; if (card->data->countColors() > 1) { q = WResourceManager::Instance()->RetrieveTempQuad("gold.jpg", TEXTURE_SUB_5551); } else { switch (card->data->getColor()) { case Constants::MTG_COLOR_ARTIFACT: q = WResourceManager::Instance()->RetrieveTempQuad("artifact.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_GREEN: q = WResourceManager::Instance()->RetrieveTempQuad("green.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_BLUE: q = WResourceManager::Instance()->RetrieveTempQuad("blue.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_RED: q = WResourceManager::Instance()->RetrieveTempQuad("red.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_BLACK: q = WResourceManager::Instance()->RetrieveTempQuad("black.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_WHITE: q = WResourceManager::Instance()->RetrieveTempQuad("white.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_LAND: q = WResourceManager::Instance()->RetrieveTempQuad("land.jpg", TEXTURE_SUB_5551); break; default: q = WResourceManager::Instance()->RetrieveTempQuad("gold.jpg", TEXTURE_SUB_5551); break; } } if (q.get() && q->mTex) { q->SetHotSpot(static_cast (q->mTex->mWidth / 2), static_cast (q->mTex->mHeight / 2)); float scale = pos.actZ * 250 / q->mHeight; q->SetColor(ARGB((int)pos.actA,255,255,255)); renderer->RenderQuad(q.get(), x, pos.actY, pos.actT, scale, scale); } // Write the title WFont * font = WResourceManager::Instance()->GetWFont(Fonts::MAGIC_FONT); float backup_scale = font->GetScale(); font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); font->SetScale(kWidthScaleFactor * pos.actZ); { char name[4096]; sprintf(name, "%s", _(card->data->getName()).c_str()); float w = font->GetStringWidth(name) * kWidthScaleFactor * pos.actZ; if (w > BigWidth - 30) font->SetScale((BigWidth - 30) / w); font->DrawString(name, x + (22 - BigWidth / 2) * pos.actZ, pos.actY + (25 - BigHeight / 2) * pos.actZ); } // Write the description { font->SetScale(kWidthScaleFactor * pos.actZ); std::vector txt = card->data->getFormattedText(); unsigned i = 0; unsigned h = neofont ? 14 : 11; for (std::vector::const_iterator it = txt.begin(); it != txt.end(); ++it, ++i) font->DrawString(it->c_str(), x + (22 - BigWidth / 2) * pos.actZ, pos.actY + (-BigHeight / 2 + 80 + h * i) * pos.actZ); } // Write the strength if (card->data->isCreature()) { char buffer[32]; sprintf(buffer, "%i/%i", card->data->power, card->data->toughness); float w = font->GetStringWidth(buffer) * kWidthScaleFactor; font->DrawString(buffer, x + (65 - w / 2) * pos.actZ, pos.actY + (106) * pos.actZ); } // Mana { ManaCost* manacost = card->data->getManaCost(); ManaCostHybrid* h; unsigned int j = 0; unsigned char t = (JGE::GetInstance()->GetTime() / 3) & 0xFF; unsigned char v = t + 127; float yOffset = -112; while ((h = manacost->getHybridCost(j))) { float scale = pos.actZ * 0.05f * cosf(2 * M_PI * ((float) t) / 256.0f); if (scale < 0) { renderer->RenderQuad(manaIcons[h->color1].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) t)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) t)) * pos.actZ, 0, 0.4f + scale, 0.4f + scale); renderer->RenderQuad(manaIcons[h->color2].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) v)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) v)) * pos.actZ, 0, 0.4f - scale, 0.4f - scale); } else { renderer->RenderQuad(manaIcons[h->color2].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) v)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) v)) * pos.actZ, 0, 0.4f - scale, 0.4f - scale); renderer->RenderQuad(manaIcons[h->color1].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) t)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) t)) * pos.actZ, 0, 0.4f + scale, 0.4f + scale); } ++j; } for (int i = Constants::MTG_NB_COLORS - 2; i >= 1; --i) { for (int cost = manacost->getCost(i); cost > 0; --cost) { renderer->RenderQuad(manaIcons[i].get(), x + (-12 * j + 75) * pos.actZ, pos.actY + (yOffset) * pos.actZ, 0, 0.4f * pos.actZ, 0.4f * pos.actZ); ++j; } } // Colorless mana if (int cost = manacost->getCost(0)) { char buffer[10]; sprintf(buffer, "%d", cost); renderer->RenderQuad(manaIcons[0].get(), x + (-12 * j + 75) * pos.actZ, pos.actY + (yOffset) * pos.actZ, 0, 0.4f * pos.actZ, 0.4f * pos.actZ); float w = font->GetStringWidth(buffer); font->DrawString(buffer, x + (-12 * j + 76 - w / 2) * pos.actZ, pos.actY + (yOffset - 5) * pos.actZ); ++j; } //Has X? if (manacost->hasX()) { char buffer[10]; sprintf(buffer, "X"); renderer->RenderQuad(manaIcons[0].get(), x + (-12 * j + 75) * pos.actZ, pos.actY + (yOffset) * pos.actZ, 0, 0.4f * pos.actZ, 0.4f * pos.actZ); float w = font->GetStringWidth(buffer); font->DrawString(buffer, x + (-12 * j + 76 - w / 2) * pos.actZ, pos.actY + (yOffset - 5) * pos.actZ); } } //types { string s = ""; for (int i = card->data->types.size() - 1; i > 0; --i) { if (card->data->basicAbilities[(int)Constants::CHANGELING]) {// this avoids drawing the list of subtypes on changeling cards. s += _("Shapeshifter - "); break; } else { s += _(Subtypes::subtypesList->find(card->data->types[i])); s += _(" - "); } } if (card->data->types.size()) s += _(Subtypes::subtypesList->find(card->data->types[0])); else { DebugTrace("Typeless card: " << setlist[card->setId].c_str() << card->data->getName() << card->getId()); } font->DrawString(s.c_str(), x + (22 - BigWidth / 2)*pos.actZ, pos.actY + (49 - BigHeight / 2)*pos.actZ); } //expansion and rarity font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); { char buf[512]; switch(card->getRarity()) { case Constants::RARITY_M: sprintf(buf,_("%s Mythic").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_R: sprintf(buf,_("%s Rare").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_U: sprintf(buf,_("%s Uncommon").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_C: sprintf(buf,_("%s Common").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_L: sprintf(buf,_("%s Land").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_T: sprintf(buf,_("%s Token").c_str(),setlist[card->setId].c_str()); break; default: case Constants::RARITY_S: sprintf(buf,_("%s Special").c_str(),setlist[card->setId].c_str()); break; } switch(card->data->getColor()) { case Constants::MTG_COLOR_BLACK: case Constants::MTG_COLOR_GREEN: case Constants::MTG_COLOR_BLUE: case Constants::MTG_COLOR_LAND: font->SetColor(ARGB((int)pos.actA,255,255,255)); font->DrawString(buf, x + (22 - BigWidth / 2)*pos.actZ, pos.actY + (BigHeight / 2 - 30)*pos.actZ); break; default: font->DrawString(buf, x + (22 - BigWidth / 2)*pos.actZ, pos.actY + (BigHeight / 2 - 30)*pos.actZ); break; //Leave black } } font->SetScale(backup_scale); RenderCountersBig(card, pos, DrawMode::kText); } void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad) { if (!quad) return; JRenderer * renderer = JRenderer::GetInstance(); JQuadPtr q; float x = pos.actX; float displayScale = 250 / BigHeight; if (card->data->countColors() > 1) { q = WResourceManager::Instance()->RetrieveTempQuad("gold.jpg", TEXTURE_SUB_5551); } else { switch (card->data->getColor()) { case Constants::MTG_COLOR_ARTIFACT: q = WResourceManager::Instance()->RetrieveTempQuad("artifact.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_GREEN: q = WResourceManager::Instance()->RetrieveTempQuad("green.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_BLUE: q = WResourceManager::Instance()->RetrieveTempQuad("blue.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_RED: q = WResourceManager::Instance()->RetrieveTempQuad("red.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_BLACK: q = WResourceManager::Instance()->RetrieveTempQuad("black.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_WHITE: q = WResourceManager::Instance()->RetrieveTempQuad("white.jpg", TEXTURE_SUB_5551); break; case Constants::MTG_COLOR_LAND: q = WResourceManager::Instance()->RetrieveTempQuad("land.jpg", TEXTURE_SUB_5551); break; default: q = WResourceManager::Instance()->RetrieveTempQuad("gold.jpg", TEXTURE_SUB_5551); break; } } if (q.get() && q->mTex) { q->SetHotSpot(static_cast (q->mTex->mWidth / 2), static_cast (q->mTex->mHeight / 2)); float scale = pos.actZ * displayScale * BigHeight / q->mHeight; q->SetColor(ARGB((int)pos.actA,255,255,255)); renderer->RenderQuad(q.get(), x, pos.actY, pos.actT, scale, scale); } std::vector txt = card->data->getFormattedText(); size_t nbTextLines = txt.size(); //Render the image on top of that quad->SetColor(ARGB((int)pos.actA,255,255,255)); float imgScale = pos.actZ * (displayScale * (BigWidth - 15)) / quad->mWidth; float imgY = pos.actY - (20 * imgScale); if (nbTextLines > 6) { imgY -= 10 * imgScale; imgScale *= 0.75; } renderer->RenderQuad(quad, x, imgY, pos.actT, imgScale, imgScale); // Write the title WFont * font = WResourceManager::Instance()->GetWFont(Fonts::MAGIC_FONT); float backup_scale = font->GetScale(); font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); font->SetScale(kWidthScaleFactor * pos.actZ); { char name[4096]; sprintf(name, "%s", _(card->data->getName()).c_str()); float w = font->GetStringWidth(name) * kWidthScaleFactor * pos.actZ; if (w > BigWidth - 30) font->SetScale((BigWidth - 30) / w); font->DrawString(name, x + (22 - BigWidth / 2) * pos.actZ, pos.actY + (25 - BigHeight / 2) * pos.actZ); } // Write the description { font->SetScale(kWidthScaleFactor * pos.actZ); float imgBottom = imgY + (imgScale * quad->mHeight / 2); unsigned i = 0; unsigned h = neofont ? 14 : 11; for (std::vector::const_iterator it = txt.begin(); it != txt.end(); ++it, ++i) font->DrawString(it->c_str(), x + (22 - BigWidth / 2) * pos.actZ, imgBottom + (h * i * pos.actZ)); } // Write the strength if (card->data->isCreature()) { char buffer[32]; sprintf(buffer, "%i/%i", card->data->power, card->data->toughness); float w = font->GetStringWidth(buffer) * kWidthScaleFactor; font->DrawString(buffer, x + (65 - w / 2) * pos.actZ, pos.actY + (106) * pos.actZ); } // Mana { ManaCost* manacost = card->data->getManaCost(); ManaCostHybrid* h; unsigned int j = 0; unsigned char t = (JGE::GetInstance()->GetTime() / 3) & 0xFF; unsigned char v = t + 127; float yOffset = -112; while ((h = manacost->getHybridCost(j))) { float scale = pos.actZ * 0.05f * cosf(2 * M_PI * ((float) t) / 256.0f); if (scale < 0) { renderer->RenderQuad(manaIcons[h->color1].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) t)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) t)) * pos.actZ, 0, 0.4f + scale, 0.4f + scale); renderer->RenderQuad(manaIcons[h->color2].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) v)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) v)) * pos.actZ, 0, 0.4f - scale, 0.4f - scale); } else { renderer->RenderQuad(manaIcons[h->color2].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) v)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) v)) * pos.actZ, 0, 0.4f - scale, 0.4f - scale); renderer->RenderQuad(manaIcons[h->color1].get(), x + (-12 * j + 75 + 3 * SineHelperFunction((float) t)) * pos.actZ, pos.actY + (yOffset + 3 * CosineHelperFunction((float) t)) * pos.actZ, 0, 0.4f + scale, 0.4f + scale); } ++j; } for (int i = Constants::MTG_NB_COLORS - 2; i >= 1; --i) { for (int cost = manacost->getCost(i); cost > 0; --cost) { renderer->RenderQuad(manaIcons[i].get(), x + (-12 * j + 75) * pos.actZ, pos.actY + (yOffset) * pos.actZ, 0, 0.4f * pos.actZ, 0.4f * pos.actZ); ++j; } } // Colorless mana if (int cost = manacost->getCost(0)) { char buffer[10]; sprintf(buffer, "%d", cost); renderer->RenderQuad(manaIcons[0].get(), x + (-12 * j + 75) * pos.actZ, pos.actY + (yOffset) * pos.actZ, 0, 0.4f * pos.actZ, 0.4f * pos.actZ); float w = font->GetStringWidth(buffer); font->DrawString(buffer, x + (-12 * j + 76 - w / 2) * pos.actZ, pos.actY + (yOffset - 5) * pos.actZ); ++j; } //Has X? if (manacost->hasX()) { char buffer[10]; sprintf(buffer, "X"); renderer->RenderQuad(manaIcons[0].get(), x + (-12 * j + 75) * pos.actZ, pos.actY + (yOffset) * pos.actZ, 0, 0.4f * pos.actZ, 0.4f * pos.actZ); float w = font->GetStringWidth(buffer); font->DrawString(buffer, x + (-12 * j + 76 - w / 2) * pos.actZ, pos.actY + (yOffset - 5) * pos.actZ); } } //types { string s = ""; for (int i = card->data->types.size() - 1; i > 0; --i) { s += _(Subtypes::subtypesList->find(card->data->types[i])); s += _(" - "); } if (card->data->types.size()) s += _(Subtypes::subtypesList->find(card->data->types[0])); else { DebugTrace("Typeless card: " << setlist[card->setId].c_str() << card->data->getName() << card->getId()); } font->DrawString(s.c_str(), x + (22 - BigWidth / 2)*pos.actZ, pos.actY + (49 - BigHeight / 2)*pos.actZ); } //expansion and rarity font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); { char buf[512]; switch(card->getRarity()) { case Constants::RARITY_M: sprintf(buf,_("%s Mythic").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_R: sprintf(buf,_("%s Rare").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_U: sprintf(buf,_("%s Uncommon").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_C: sprintf(buf,_("%s Common").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_L: sprintf(buf,_("%s Land").c_str(),setlist[card->setId].c_str()); break; case Constants::RARITY_T: sprintf(buf,_("%s Token").c_str(),setlist[card->setId].c_str()); break; default: case Constants::RARITY_S: sprintf(buf,_("%s Special").c_str(),setlist[card->setId].c_str()); break; } switch(card->data->getColor()) { case Constants::MTG_COLOR_BLACK: case Constants::MTG_COLOR_GREEN: case Constants::MTG_COLOR_BLUE: case Constants::MTG_COLOR_LAND: font->SetColor(ARGB((int)pos.actA,255,255,255)); font->DrawString(buf, x + (22 - BigWidth / 2)*pos.actZ, pos.actY + (BigHeight / 2 - 30)*pos.actZ); break; default: font->DrawString(buf, x + (22 - BigWidth / 2)*pos.actZ, pos.actY + (BigHeight / 2 - 30)*pos.actZ); break; //Leave black } } font->SetScale(backup_scale); RenderCountersBig(card, pos); } //Renders a big card on screen. Defaults to the "alternate" rendering if no image is found void CardGui::RenderBig(MTGCard* card, const Pos& pos) { JRenderer * renderer = JRenderer::GetInstance(); //GameObserver * game = GameObserver::GetInstance(); //if((MTGCard*)game->mLayers->actionLayer()->currentActionCard != NULL) // card = (MTGCard*)game->mLayers->actionLayer()->currentActionCard; //i want this but ai targets cards so quickly that it can crash the game. float x = pos.actX; JQuadPtr quad = WResourceManager::Instance()->RetrieveCard(card); if (quad.get()) { if (quad->mHeight < quad->mWidth) { return TinyCropRender(card, pos, quad.get()); } quad->SetColor(ARGB(255,255,255,255)); float scale = pos.actZ * 250.f / quad->mHeight; renderer->RenderQuad(quad.get(), x, pos.actY, pos.actT, scale, scale); RenderCountersBig(card, pos); return; } //DebugTrace("Unable to fetch image: " << card->getImageName()); // If we come here, we do not have the picture. AlternateRender(card, pos); } void CardGui::RenderCountersBig(MTGCard * mtgcard, const Pos& pos, int drawMode) { MTGCardInstance * card = dynamic_cast (mtgcard); if (!card) return; if (!card->counters) return; if (!card->counters->mCount) return; // Write Named Counters WFont * font = WResourceManager::Instance()->GetWFont(Fonts::MAGIC_FONT); font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); font->SetScale(kWidthScaleFactor * pos.actZ); unsigned i = 0; if (drawMode == DrawMode::kText) { std::vector txt = card->data->getFormattedText(); i = txt.size() + 1; } for (size_t t = 0; t < card->counters->counters.size(); t++) { Counter * c = card->counters->counters[t]; if (!c || c->nb <= 0) continue; char buf[512]; bool renderText = true; string gfx = ""; //TODO cache the gfx fetch results? if (c->name.size()) { if (c->nb < 6) //we only render a counter's specific quad if there are 5 counters of this type or less. Otherwise we will use the generic one { if (counterGraphics.find(c->name) == counterGraphics.end()) { string gfxRelativeName = "counters/"; gfxRelativeName.append(c->name); gfxRelativeName.append(".png"); string _gfx = WResourceManager::Instance()->graphicsFile(gfxRelativeName); if (!fileExists(_gfx.c_str())) _gfx = ""; counterGraphics[c->name] = _gfx; } gfx = counterGraphics[c->name]; if (gfx.size()) renderText = false; } if (renderText) { std::string s = c->name; s[0] = toupper(s[0]); sprintf(buf, _("%s: %i").c_str(), s.c_str(), c->nb); } } else { sprintf(buf, _("%s%i/%s%i").c_str(), ((c->power > 0) ? "+": ""), c->power * c->nb, ((c->toughness > 0) ? "+": ""),c->toughness* c->nb); } if (!gfx.size()) { gfx = "counters/default.png"; } float x = pos.actX + (22 - BigWidth / 2) * pos.actZ; float y = pos.actY + (-BigHeight / 2 + 80 + 11 * i + 21 * t) * pos.actZ; if (y > pos.actY + 105) { y = (-BigHeight / 2 + 80 + 11 * i) * pos.actZ + (y - 105 - 21); x += (BigWidth / 2) * pos.actZ; } if (gfx.size()) { JQuadPtr q = WResourceManager::Instance()->RetrieveTempQuad(gfx); if (q.get() && q->mTex) { float scale = 20.f / q->mHeight; if (renderText) { float scaleX = (font->GetStringWidth(buf) + 20) / q->mWidth; JRenderer::GetInstance()->RenderQuad(q.get(), x, y, 0, scaleX, scale); } else { for (int j = 0; j < c->nb; ++j) { JRenderer::GetInstance()->RenderQuad(q.get(), x + (scale * q->mWidth * j), y, 0, scale, scale); } } } } if (renderText) { font->SetColor(ARGB(255,0,0,0)); font->DrawString(buf, x + 5, y + 5); } } } MTGCardInstance* CardView::getCard() { return card; } TransientCardView::TransientCardView(MTGCardInstance* card, float x, float y) : CardGui(card, x, y) { } TransientCardView::TransientCardView(MTGCardInstance* card, const Pos& ref) : CardGui(card, ref) { } ; ostream& CardView::toString(ostream& out) const { return (CardGui::toString(out) << " : CardView ::: card : " << card << "; actX,actY : " << actX << "," << actY << "; t : " << t << " ; actT : " << actT); } ostream& CardGui::toString(ostream& out) const { return (out << "CardGui ::: x,y " << x << "," << y); } SimpleCardEffectRotate::SimpleCardEffectRotate(float rotation): mRotation(rotation) { } void SimpleCardEffectRotate::doEffect(Pos * card) { card->t = mRotation; } void SimpleCardEffectRotate::undoEffect(Pos * card) { card->t = 0; } SimpleCardEffectMask::SimpleCardEffectMask(PIXEL_TYPE mask): mMask(mask) { } void SimpleCardEffectMask::doEffect(Pos * card) { card->mask = mMask; } void SimpleCardEffectMask::undoEffect(Pos * card) { card->mask = 0; }