#include "PrecompiledHeader.h" #include "CardSelector.h" #include "GameApp.h" #include "GuiPlay.h" #include "Subtypes.h" #include "Trash.h" #include "ModRules.h" #include "DuelLayers.h" #define CARD_WIDTH (31) const float GuiPlay::HORZWIDTH = 300.0f; const float GuiPlay::VERTHEIGHT = 80.0f; void GuiPlay::CardStack::reset(unsigned total, float x, float y) { this->total = total; this->x = 0; baseX = x; this->y = 0; baseY = y; } void GuiPlay::CardStack::RenderSpell(MTGCardInstance* card, iterator begin, iterator end, float x, float y) { while (begin != end) { if ((*begin)->card->target == card) { RenderSpell(card, begin + 1, end, x, y - 10); (*begin)->x = x; (*begin)->y = y; (*begin)->Render(); return; } ++begin; } } GuiPlay::HorzStack::HorzStack() { } GuiPlay::VertStack::VertStack() { } void GuiPlay::VertStack::reset(unsigned total, float x, float y) { GuiPlay::CardStack::reset(total, x - CARD_WIDTH, y); count = 0; } void GuiPlay::HorzStack::Render(CardView* card, iterator begin, iterator end) { RenderSpell(card->card, begin, end, card->x, card->y - 10); card->Render(); } void GuiPlay::HorzStack::Enstack(CardView* card) { card->x = x + baseX; card->y = y + baseY; if (total < 8) x += CARD_WIDTH; else if (total < 16) x += (SCREEN_WIDTH - 200 - baseX) / total; else x += (SCREEN_WIDTH - 50 - baseX) / total; } void GuiPlay::VertStack::Enstack(CardView* card) { int modulus = total < 10 ? 3 : 5; { if (0 == count % modulus) { x += CARD_WIDTH; y = 0; } } card->x = x + baseX; card->y = y + baseY; y += 12; if (++count == total - 1 && y == 12) y += 12; } void GuiPlay::VertStack::Render(CardView* card, iterator begin, iterator end) { RenderSpell(card->card, begin, end, card->x + 5, card->y - 10); card->Render(); } inline float GuiPlay::VertStack::nextX() { if (0 == count) return x + CARD_WIDTH; else return x; } GuiPlay::BattleField::BattleField() : attackers(0), height(0.0), red(0), colorFlow(0) { } const float GuiPlay::BattleField::HEIGHT = 80.0f; void GuiPlay::BattleField::addAttacker(MTGCardInstance*) { ++attackers; colorFlow = 1; } void GuiPlay::BattleField::removeAttacker(MTGCardInstance*) { --attackers; } void GuiPlay::BattleField::reset(float x, float y) { HorzStack::reset(0, x, y); currentAttacker = 1; } void GuiPlay::BattleField::EnstackAttacker(CardView* card) { card->x = CARD_WIDTH + 20 + (currentAttacker * (HORZWIDTH) / (attackers+1)); card->y = baseY + (card->card->getObserver()->getView()->getRenderedPlayer() == card->card->controller() ? 20 + y : -20 - y); ++currentAttacker; // JRenderer::GetInstance()->RenderQuad(WResourceManager::Instance()->GetQuad("BattleIcon"), card->actX, card->actY, 0, 0.5 + 0.1 * sinf(JGE::GetInstance()->GetTime()), 0.5 + 0.1 * sinf(JGE::GetInstance()->GetTime())); } void GuiPlay::BattleField::EnstackBlocker(CardView* card) { MTGCardInstance * c = card->card; if (!c) return; int offset = 0; if (c->defenser && c->defenser->view) { offset = c->defenser->getDefenserRank(c); card->x = c->defenser->view->x + 5 * offset; } card->y = baseY + (card->card->getObserver()->getView()->getRenderedPlayer() == card->card->controller() ? 20 + y + 6 * offset : -20 - y + 6 * offset); } void GuiPlay::BattleField::Update(float dt) { if (0 == attackers) height -= 10 * dt * height; else height += 10 * dt * (HEIGHT - height); if (colorFlow) { red += static_cast (colorFlow * 300 * dt); if (red < 0) red = 0; if (red > 70) red = 70; } } void GuiPlay::BattleField::Render() { if (height > 3) JRenderer::GetInstance()->FillRect(44, SCREEN_HEIGHT / 2 + 10 - height / 2, 318, height, ARGB(127, red, 0, 0)); } GuiPlay::GuiPlay(DuelLayers* view) : GuiLayer(view) { end_spells = cards.end(); } GuiPlay::~GuiPlay() { for (iterator it = cards.begin(); it != cards.end(); ++it) { delete (*it); } } bool isSpell(CardView* c) { return c->card->isSpell() && !c->card->isCreature() && !c->card->hasType(Subtypes::TYPE_PLANESWALKER); } void GuiPlay::Replace() { unsigned opponentSpellsN = 0, selfSpellsN = 0, opponentLandsN = 0, opponentCreaturesN = 0, battleFieldAttackersN = 0, battleFieldBlockersN = 0, selfCreaturesN = 0, selfLandsN = 0; end_spells = stable_partition(cards.begin(), cards.end(), &isSpell); for (iterator it = cards.begin(); it != end_spells; ++it) if (!(*it)->card->target) { if((!(*it)->card->hasSubtype(Subtypes::TYPE_AURA)|| ((*it)->card->hasSubtype(Subtypes::TYPE_AURA) && (*it)->card->playerTarget)) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) ++selfSpellsN; else ++opponentSpellsN; } } for (iterator it = end_spells; it != cards.end(); ++it) { if ((*it)->card->isCreature()) { if ((*it)->card->isAttacker()) ++battleFieldAttackersN; else if ((*it)->card->isDefenser()) ++battleFieldBlockersN; else if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) ++selfCreaturesN; else ++opponentCreaturesN; } else if ((*it)->card->isLand() || (*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) ++selfLandsN; else ++opponentLandsN; } } opponentSpells.reset(opponentSpellsN, 18, 60); selfSpells.reset(selfSpellsN, 18, 215); for (iterator it = cards.begin(); it != end_spells; ++it) if (!(*it)->card->target) { if((!(*it)->card->hasSubtype(Subtypes::TYPE_AURA)|| ((*it)->card->hasSubtype(Subtypes::TYPE_AURA) && (*it)->card->playerTarget)) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfSpells.Enstack(*it); else opponentSpells.Enstack(*it); } } float x = 24 + opponentSpells.nextX(); //seperated the variable X into 2 different variables. There are 2 players here!! //we should not be using a single variable to determine the positioning of cards!! float myx = 24 + selfSpells.nextX(); opponentLands.reset(opponentLandsN,x, 50); opponentCreatures.reset(opponentCreaturesN, x, 95); battleField.reset(x, 145);//what does this variable do? I can comment it out with no repercussions...is this being double handled? selfCreatures.reset(selfCreaturesN, myx, 195); selfLands.reset(selfLandsN, myx, 240); for (iterator it = end_spells; it != cards.end(); ++it) { if ((*it)->card->isCreature()) { if ((*it)->card->isAttacker()) battleField.EnstackAttacker(*it); else if ((*it)->card->isDefenser()) battleField.EnstackBlocker(*it); else if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfCreatures.Enstack(*it); else opponentCreatures.Enstack(*it); } else if ((*it)->card->isLand()) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfLands.Enstack(*it); else opponentLands.Enstack(*it); } } //rerun the iter reattaching planes walkers to the back of the lands. for (iterator it = end_spells; it != cards.end(); ++it) { if ((*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfLands.Enstack(*it); else opponentLands.Enstack(*it); } } } void GuiPlay::Render() { battleField.Render(); for (iterator it = cards.begin(); it != cards.end(); ++it) { if ((*it)->card->isLand()) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfLands.Render(*it, cards.begin(), end_spells); else opponentLands.Render(*it, cards.begin(), end_spells); } else if ((*it)->card->isCreature()) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfCreatures.Render(*it, cards.begin(), end_spells); else opponentCreatures.Render(*it, cards.begin(), end_spells); } else if(!(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER)) { if (!(*it)->card->target) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfSpells.Render(*it, cards.begin(), end_spells); else opponentSpells.Render(*it, cards.begin(), end_spells); } } else { if (!(*it)->card->target) { if (mpDuelLayers->getRenderedPlayer() == (*it)->card->controller()) selfPlaneswalker.Render(*it, cards.begin(), end_spells); else opponentPlaneswalker.Render(*it, cards.begin(), end_spells); } } } } void GuiPlay::Update(float dt) { battleField.Update(dt); for (iterator it = cards.begin(); it != cards.end(); ++it) (*it)->Update(dt); } int GuiPlay::receiveEventPlus(WEvent * e) { if (WEventZoneChange *event = dynamic_cast(e)) { if ((observer->players[0]->inPlay() == event->to) || (observer->players[1]->inPlay() == event->to)) { CardView * card; if (event->card->view) { //fix for http://code.google.com/p/wagic/issues/detail?id=462. // We don't want a card in the hand to have an alpha of 0 event->card->view->alpha = 255; card = NEW CardView(CardView::playZone, event->card, *(event->card->view)); } else card = NEW CardView(CardView::playZone, event->card, 0, 0); cards.push_back(card); if (event->card->isTapped()) gModRules.cards.activateEffect->doEffect(card); else gModRules.cards.activateEffect->undoEffect(card); card->alpha = 255; // Make sure that the card is repositioned before adding it to the CardSelector, as // the card's position is a cue for certain CardSelector variants as to what zone the card is placed in Replace(); observer->getCardSelector()->Add(card); return 1; } } else if (WEventCreatureAttacker* event = dynamic_cast(e)) { if (NULL != event->after) battleField.addAttacker(event->card); else if (NULL != event->before) battleField.removeAttacker(event->card); Replace(); } else if (dynamic_cast (e)) { Replace(); } else if (WEventCardTap* event = dynamic_cast(e)) { if (CardView* cv = dynamic_cast(event->card->view)) { if (event->after) gModRules.cards.activateEffect->doEffect(cv); else gModRules.cards.activateEffect->undoEffect(cv); //cv->t = event->after ? M_PI / 2 : 0; } else if (event->card->view != NULL) { if (event->after) gModRules.cards.activateEffect->doEffect(event->card->view); else gModRules.cards.activateEffect->undoEffect(event->card->view); //event->card->view->actT = event->after ? M_PI / 2 : 0; } else { // this should never happen, if you have a consistent repro case, ping Wil please assert(false); } return 1; } else if (WEventPhaseChange *event = dynamic_cast(e)) { if (MTG_PHASE_COMBATEND == event->to->id) battleField.colorFlow = -1; } else if (dynamic_cast (e)) Replace(); Replace(); return 0; } int GuiPlay::receiveEventMinus(WEvent * e) { if (WEventZoneChange *event = dynamic_cast(e)) { if ((observer->players[0]->inPlay() == event->from) || (observer->players[1]->inPlay() == event->from)) for (iterator it = cards.begin(); it != cards.end(); ++it) if (event->card->previous == (*it)->card || event->card == (*it)->card) { if (event->card->previous && event->card->previous->attacker) battleField.removeAttacker(event->card->previous); else if (event->card->attacker) battleField.removeAttacker(event->card); CardView* cv = *it; observer->getCardSelector()->Remove(cv); cards.erase(it); observer->mTrash->trash(cv); Replace(); return 1; } } return 0; }