#include "../include/debug.h" #include "../include/DamageResolverLayer.h" #include "../include/GameObserver.h" #include "../include/MTGCardInstance.h" #include "../include/DamagerDamaged.h" #include "../include/Damage.h" DamageResolverLayer::DamageResolverLayer(int id, GameObserver * _game):PlayGuiObjectController(id, _game){ currentPhase = -1; remainingDamageSteps = 0; damageStack = NULL; currentSource = NULL; buttonOk = 0; currentChoosingPlayer = NULL; } void DamageResolverLayer::Update(float dt){ int newPhase = game->getCurrentGamePhase(); if (newPhase == MTG_PHASE_COMBATDAMAGE){ if (!game->mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)){ if (newPhase != currentPhase){ init(); } if (remainingDamageSteps && empty()){ initResolve(); } } }else{ remainingDamageSteps = 0; } currentPhase = newPhase; PlayGuiObjectController::Update(dt); } Player * DamageResolverLayer::whoSelectsDamagesDealtBy(MTGCardInstance * card){ if (card->controller() == game->currentPlayer){ //Attacker MTGInPlay * defensers = game->opponent()->game->inPlay; int nbdefensers = defensers->nbDefensers(card); if (nbdefensers == 0) return NULL; if(nbdefensers == 1 && !card->has(TRAMPLE)) return NULL; MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card); while (defenser != NULL){ if (defenser->has(BANDING)) return game->opponent(); defenser = defensers->getNextDefenser(defenser, card); } return game->currentPlayer; }else{ //Defenser MTGInPlay * attackers = game->currentPlayer->game->inPlay; int nbattackers = attackers->nbPartners(card->isDefenser()); if(nbattackers <= 1) return NULL; if (card->isDefenser()->banding) return game->currentPlayer; return game->opponent(); } } int DamageResolverLayer::addAutoDamageToOpponents(MTGCardInstance * card){ if (card->controller() == game->currentPlayer){ //Attacker MTGInPlay * defensers = game->opponent()->game->inPlay; int nbdefensers = defensers->nbDefensers(card); if (nbdefensers == 0){ Damage * damage = NEW Damage (0, card, game->opponent()); damageStack->Add(damage); }else if (nbdefensers == 1){ Damage * damage = NEW Damage (0, card, defensers->getNextDefenser(NULL, card)); damageStack->Add(damage); }else{ //SHOULDN'T HAPPEN ! } }else{ //Defenser Damage * damage = NEW Damage (mCount,card, card->isDefenser()); damageStack->Add(damage); } return 1; } int DamageResolverLayer::addIfNotExists(MTGCardInstance * card, Player * selecter){ for (int i = 0; i < mCount; i++){ DamagerDamaged * item = (DamagerDamaged *)mObjects[i]; if (item->card == card) return 0; } CardGui * cardg = game->mLayers->playLayer()->getByCard(card); DamagerDamaged * item = NEW DamagerDamaged(cardg, selecter, mCount == 0); Add(item); mCurr = 0; return 1; } //Adds a card and all its opponents to the Damagers' list int DamageResolverLayer::addDamager(MTGCardInstance * card, Player * selecter){ addIfNotExists(card, selecter); if (card->controller() == game->currentPlayer){ //Attacker MTGInPlay * defensers = game->opponent()->game->inPlay; MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card); while (defenser != NULL){ addIfNotExists(defenser, whoSelectsDamagesDealtBy(defenser)); defenser = defensers->getNextDefenser(defenser, card); } }else{ //Defenser MTGInPlay * attackers = game->currentPlayer->game->inPlay; MTGCardInstance * attacker = card->isDefenser(); addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker)); MTGCardInstance * banding = attacker->banding; if (banding){ attacker = attackers->getNextAttacker(NULL); while (attacker != NULL){ if (attacker->banding == banding){ addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker)); } attacker = attackers->getNextAttacker(attacker); } } } return 1; } int DamageResolverLayer::initResolve(){ #if defined (WIN32) || defined (LINUX) char buf[4096]; sprintf(buf, "starting resolve, remainingDamagesStep = %i\n", remainingDamageSteps); OutputDebugString(buf); #endif if (damageStack) return 0; #if defined (WIN32) || defined (LINUX) sprintf(buf, "damageStack is NULL, we can resolve \n"); OutputDebugString(buf); #endif currentSource = NULL; currentChoosingPlayer = game->currentPlayer; damageStack = NEW DamageStack(mCount,game); int strike = 0; if (remainingDamageSteps == 2) strike = 1; MTGInPlay * attackers = game->currentPlayer->game->inPlay; MTGInPlay * defensers = game->opponent()->game->inPlay; MTGCardInstance * attacker = attackers->getNextAttacker(NULL); while (attacker != NULL){ #if defined (WIN32) || defined (LINUX) sprintf(buf, "attacker : %s \n", attacker->getName()); OutputDebugString(buf); #endif if ((!strike && !attacker->has(FIRSTSTRIKE)) || (strike && attacker->has(FIRSTSTRIKE)) || attacker->has(DOUBLESTRIKE)){ Player * selecter = whoSelectsDamagesDealtBy(attacker); if (!selecter){ addAutoDamageToOpponents(attacker); }else{ addDamager(attacker, selecter); } } MTGCardInstance * defenser = defensers->getNextDefenser(NULL, attacker); while (defenser != NULL){ if ((!strike && !defenser->has(FIRSTSTRIKE)) || (strike && defenser->has(FIRSTSTRIKE)) || defenser->has(DOUBLESTRIKE)){ Player * selecterb = whoSelectsDamagesDealtBy(defenser); if (!selecterb){ addAutoDamageToOpponents(defenser); }else{ addDamager(defenser, selecterb); } } defenser = defensers->getNextDefenser(defenser, attacker); } attacker = attackers->getNextAttacker(attacker); } if (empty()){ if (!damageStack->empty()){ game->mLayers->stackLayer()->addAction(damageStack); }else{ SAFE_DELETE(damageStack); } remainingDamageSteps--; damageStack = NULL; modal = remainingDamageSteps; }else{ if (canStopDealDamages()) currentChoosingPlayer = game->opponent(); } return 1; } int DamageResolverLayer::init(){ modal = 1; remainingDamageSteps = 2; return 1; } DamagerDamaged * DamageResolverLayer::findByCard(MTGCardInstance * card){ for (int i =0; i < mCount; i++){ DamagerDamaged * current = (DamagerDamaged *) mObjects[i]; if (current->card == card) return current; } return NULL; } //Returns 1 if all "compulsory" damages have been assigned for current player int DamageResolverLayer::canStopDealDamages(){ for (int i = 0; i < mCount ; i ++){ DamagerDamaged * current = (DamagerDamaged *) mObjects[i]; if (current->damageSelecter==currentChoosingPlayer && current->damageToDeal > 0){ MTGCardInstance * card = current->card; if (card->controller() == game->currentPlayer){ //Attacker if (card->has(TRAMPLE)){ MTGInPlay * defensers = game->opponent()->game->inPlay; MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card); while (defenser != NULL){ DamagerDamaged * _defenser = findByCard(defenser); if (!_defenser->hasLethalDamage()) return 0; defenser = defensers->getNextDefenser(defenser, card); } }else{ return 0; } }else{ //Defenser return 0; } } } return 1; } int DamageResolverLayer::trampleDamage(){ for (int i = 0; i < mCount ; i ++){ DamagerDamaged * current = (DamagerDamaged *) mObjects[i]; if (current->damageToDeal > 0){ MTGCardInstance * card = current->card; if (card->controller() == game->currentPlayer){ //Attacker if (card->has(TRAMPLE)){ Damage * damage = NEW Damage(0, card, game->opponent(), current->damageToDeal); damageStack->Add(damage); } } } } return 1; } int DamageResolverLayer::resolveDamages(){ trampleDamage(); for (int i = 0; i < mCount ; i++){ DamagerDamaged * current = (DamagerDamaged *) mObjects[i]; for (int j =0; j < current->mCount ; j++){ Damage * damage = NEW Damage(0, current->damages[j]->source, current->damages[j]->target, current->damages[j]->damage); damageStack->Add(damage); } } game->mLayers->stackLayer()->addAction(damageStack); remainingDamageSteps--; resetObjects(); damageStack = NULL; modal = remainingDamageSteps; return 1; } //a and b are opponents if b is blocking a band in which a belongs or blocking directly a int DamageResolverLayer::isOpponent(DamagerDamaged * a, DamagerDamaged * b){ MTGCardInstance * carda = a->card; MTGCardInstance * cardb = b->card; if (cardb->controller() == game->currentPlayer) {//if b is the attacker switch the cards carda = cardb; cardb = a->card; } if (cardb->controller() == game->currentPlayer || carda->controller() == game->opponent()) return 0; //Same team, idiot ! if (!carda->banding){ if (cardb->isDefenser() == carda) return 1; return 0; } if (cardb->isDefenser() && cardb->isDefenser()->banding == carda->banding) return 1; return 0; } void DamageResolverLayer::nextPlayer(){ if (currentChoosingPlayer == game->currentPlayer){ currentChoosingPlayer = game->opponent(); if (canStopDealDamages()) resolveDamages(); }else{ resolveDamages(); } } void DamageResolverLayer::CheckUserInput(float dt){ if (!mCount) return; if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)){ if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){ DamagerDamaged * current = (DamagerDamaged *) mObjects[mCurr]; if (!currentSource || !isOpponent(current,currentSource)){ for (int i = 0; i < mCount; i++){ DamagerDamaged * _current = (DamagerDamaged *) mObjects[i]; if (isOpponent(current,_current)){ currentSource = _current; break; } } } if (currentSource){ if (currentSource->damageSelecter == currentChoosingPlayer){ if (isOpponent(current,currentSource)){ if (!currentSource->dealOneDamage(current)){ currentSource->removeDamagesTo(current); } } } }else{ if (current->damageSelecter == currentChoosingPlayer){ currentSource = current; } } buttonOk = 0; if (canStopDealDamages()) buttonOk = 1; } }else if (mEngine->GetButtonClick(PSP_CTRL_CROSS)){ if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){ DamagerDamaged * current = (DamagerDamaged *) mObjects[mCurr]; if (current->damageSelecter == currentChoosingPlayer){ currentSource = current; } } }else if (mEngine->GetButtonClick(PSP_CTRL_SQUARE)){ if (canStopDealDamages()){ nextPlayer(); //switch to next player or end of selection } }else{ PlayGuiObjectController::CheckUserInput(dt); } } void DamageResolverLayer::Render(){ if (!mCount) return; JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT); mFont->SetBase(0); mFont->SetScale(0.75); JRenderer * renderer = JRenderer::GetInstance(); renderer->FillRect(0 ,0 , SCREEN_WIDTH , SCREEN_HEIGHT , ARGB(200,0,0,0)); if (currentChoosingPlayer == game->currentPlayer){ mFont->DrawString("Player 1", 0,0); }else{ mFont->DrawString("Player 2", 0,0); } if (currentSource){ currentSource->RenderBig(10, 20); mFont->DrawString("Current Damager:", 10, 5); } for (int i = 0; i < mCount; i++){ ((DamagerDamaged *)mObjects[i])->Render(currentChoosingPlayer); } if (mObjects[mCurr]){ ((DamagerDamaged *)mObjects[mCurr])->Render(currentChoosingPlayer); } if (buttonOk){ mFont->DrawString("Damages Assigned, Click Square to Continue", 250, 5); } }