diff --git a/projects/mtg/src/AIMomirPlayer.cpp b/projects/mtg/src/AIMomirPlayer.cpp index 0e4c949e8..a5ca2bdc5 100644 --- a/projects/mtg/src/AIMomirPlayer.cpp +++ b/projects/mtg/src/AIMomirPlayer.cpp @@ -6,116 +6,137 @@ #include "AIStats.h" #include "AllAbilities.h" - MTGAbility * AIMomirPlayer::momirAbility = NULL; -AIMomirPlayer::AIMomirPlayer(MTGDeck * deck, string file, string fileSmall, string avatarFile) : AIPlayerBaka(deck, file, fileSmall, avatarFile) { - momirAbility = NULL; - agressivity = 100; +AIMomirPlayer::AIMomirPlayer(MTGDeck * deck, string file, string fileSmall, string avatarFile) : + AIPlayerBaka(deck, file, fileSmall, avatarFile) +{ + momirAbility = NULL; + agressivity = 100; } -int AIMomirPlayer::getEfficiency(AIAction * action){ - MTGAbility * ability = action->ability; - if (ability->cost && !(ability->cost->isExtraPaymentSet())) return 0; //Does not handle abilities with sacrifice yet - int efficiency = AIPlayerBaka::getEfficiency(action); +int AIMomirPlayer::getEfficiency(AIAction * action) +{ + MTGAbility * ability = action->ability; + if (ability->cost && !(ability->cost->isExtraPaymentSet())) + return 0; //Does not handle abilities with sacrifice yet + int efficiency = AIPlayerBaka::getEfficiency(action); - GameObserver * g = GameObserver::GetInstance(); - if (g->getCurrentGamePhase() < Constants::MTG_PHASE_FIRSTMAIN) return 0; - return efficiency; + GameObserver * g = GameObserver::GetInstance(); + if (g->getCurrentGamePhase() < Constants::MTG_PHASE_FIRSTMAIN) + return 0; + return efficiency; } -MTGAbility * AIMomirPlayer::getMomirAbility(){ - if (momirAbility) return momirAbility; +MTGAbility * AIMomirPlayer::getMomirAbility() +{ + if (momirAbility) + return momirAbility; - GameObserver * g = GameObserver::GetInstance(); - momirAbility = g->mLayers->actionLayer()->getAbility(MTGAbility::MOMIR); - return momirAbility; + GameObserver * g = GameObserver::GetInstance(); + momirAbility = g->mLayers->actionLayer()->getAbility(MTGAbility::MOMIR); + return momirAbility; } -int AIMomirPlayer::momir(){ - if (!game->hand->nb_cards) return 0; //nothing to discard :/ - int result = 0; - int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES); - int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES ); - ManaCost * potentialMana = getPotentialMana(); - int converted = potentialMana->getConvertedCost(); - SAFE_DELETE(potentialMana); - int efficiency = 100; - int chance = 1 + (WRand() % 100); - if (converted == 5 && myCreatures > opponentCreatures && game->hand->nb_cards<4) efficiency = 5 ; //Strategy: skip 5 drop - if (converted == 7 && myCreatures > opponentCreatures && game->hand->nb_cards<2) efficiency = 50; //Strategy: 7 drops have bad upkeep costs and the AI doesn't handle those right now... - if (converted > 8 ) converted = 8; - if (converted == 8) efficiency = 100 - (myCreatures-opponentCreatures); +int AIMomirPlayer::momir() +{ + if (!game->hand->nb_cards) + return 0; //nothing to discard :/ + int result = 0; + int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES); + int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES ); + ManaCost * potentialMana = getPotentialMana(); + int converted = potentialMana->getConvertedCost(); + SAFE_DELETE(potentialMana); + int efficiency = 100; + int chance = 1 + (WRand() % 100); + if (converted == 5 && myCreatures > opponentCreatures && game->hand->nb_cards < 4) + efficiency = 5; //Strategy: skip 5 drop + if (converted == 7 && myCreatures > opponentCreatures && game->hand->nb_cards < 2) + efficiency = 50; //Strategy: 7 drops have bad upkeep costs and the AI doesn't handle those right now... + if (converted > 8) + converted = 8; + if (converted == 8) + efficiency = 100 - (myCreatures - opponentCreatures); - if (efficiency >= chance){ - int _cost[] = {Constants::MTG_COLOR_ARTIFACT,converted}; - ManaCost * cost = NEW ManaCost(_cost); - MTGAbility * ability = getMomirAbility(); - MTGCardInstance * card = game->hand->cards[0]; - if (ability->isReactingToClick(card,cost)){ - tapLandsForMana(cost); - AIAction * a = NEW AIAction(ability,card); - clickstream.push(a); - result = 1; - } - delete cost; - } - return result; -} - -int AIMomirPlayer::computeActions(){ -//Part of the strategy goes here. When should we put a land into play ? -/* -Another gift from Alex Majlaton on my first day playing Momir, and it has served me well ever since. It goes a little something like this: (a) if you are on the play, hit your Two through Four, skip your Five, and then hit all the way to Eight; (b) if you are on the draw and your opponent skips his One, you make Two through Eight; (c) if you are on the draw and your opponent hits a One, you match him drop-for-drop for the rest of the game. - -You skip your Five on the play because it is the weakest drop. There are plenty of serviceable guys there, but very few bombs compared to other drops -the general rule is this: if you want to get to Eight, you have to skip two drops on the play and one drop on the draw. -*/ - GameObserver * g = GameObserver::GetInstance(); - Player * p = g->currentPlayer; - if (!(g->currentlyActing() == this)) return 0; - if (chooseTarget()) return 1; - int currentGamePhase = g->getCurrentGamePhase(); - if (g->isInterrupting == this){ // interrupting - selectAbility(); - return 1; - }else if (p == this && g->mLayers->stackLayer()->count(0,NOT_RESOLVED) == 0){ //standard actions - CardDescriptor cd; - MTGCardInstance * card = NULL; - - - switch(currentGamePhase){ - case Constants::MTG_PHASE_FIRSTMAIN: - { - ManaCost * potentialMana = getPotentialMana(); - int converted = potentialMana->getConvertedCost(); - SAFE_DELETE(potentialMana); - if (canPutLandsIntoPlay && ( converted <8 || game->hand->nb_cards > 1) ){ - //Attempt to put land into play - cd.init(); - cd.setColor(Constants::MTG_COLOR_LAND); - card = cd.match(game->hand); - if (card){ - MTGAbility * putIntoPlay = g->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY); - AIAction * a = NEW AIAction(putIntoPlay,card); //TODO putinplay action - clickstream.push(a); - return 1; - } + if (efficiency >= chance) + { + int _cost[] = { Constants::MTG_COLOR_ARTIFACT, converted }; + ManaCost * cost = NEW ManaCost(_cost); + MTGAbility * ability = getMomirAbility(); + MTGCardInstance * card = game->hand->cards[0]; + if (ability->isReactingToClick(card, cost)) + { + tapLandsForMana(cost); + AIAction * a = NEW AIAction(ability, card); + clickstream.push(a); + result = 1; } - momir(); - return 1; - break; - } - case Constants::MTG_PHASE_SECONDMAIN: - selectAbility(); - return 1; - break; - default: - return AIPlayerBaka::computeActions(); - break; + delete cost; } - } - return AIPlayerBaka::computeActions(); + return result; } +int AIMomirPlayer::computeActions() +{ + //Part of the strategy goes here. When should we put a land into play ? + /* + Another gift from Alex Majlaton on my first day playing Momir, and it has served me well ever since. It goes a little something like this: (a) if you are on the play, hit your Two through Four, skip your Five, and then hit all the way to Eight; (b) if you are on the draw and your opponent skips his One, you make Two through Eight; (c) if you are on the draw and your opponent hits a One, you match him drop-for-drop for the rest of the game. + + You skip your Five on the play because it is the weakest drop. There are plenty of serviceable guys there, but very few bombs compared to other drops + the general rule is this: if you want to get to Eight, you have to skip two drops on the play and one drop on the draw. + */ + GameObserver * g = GameObserver::GetInstance(); + Player * p = g->currentPlayer; + if (!(g->currentlyActing() == this)) + return 0; + if (chooseTarget()) + return 1; + int currentGamePhase = g->getCurrentGamePhase(); + if (g->isInterrupting == this) + { // interrupting + selectAbility(); + return 1; + } + else if (p == this && g->mLayers->stackLayer()->count(0, NOT_RESOLVED) == 0) + { //standard actions + CardDescriptor cd; + MTGCardInstance * card = NULL; + + switch (currentGamePhase) + { + case Constants::MTG_PHASE_FIRSTMAIN: + { + ManaCost * potentialMana = getPotentialMana(); + int converted = potentialMana->getConvertedCost(); + SAFE_DELETE(potentialMana); + if (canPutLandsIntoPlay && (converted < 8 || game->hand->nb_cards > 1)) + { + //Attempt to put land into play + cd.init(); + cd.setColor(Constants::MTG_COLOR_LAND); + card = cd.match(game->hand); + if (card) + { + MTGAbility * putIntoPlay = g->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY); + AIAction * a = NEW AIAction(putIntoPlay, card); //TODO putinplay action + clickstream.push(a); + return 1; + } + } + momir(); + return 1; + break; + } + case Constants::MTG_PHASE_SECONDMAIN: + selectAbility(); + return 1; + break; + default: + return AIPlayerBaka::computeActions(); + break; + } + } + return AIPlayerBaka::computeActions(); +} diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index 98c825828..d3ad32440 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -8,932 +8,1161 @@ #include "GuiCombat.h" #include "GameStateDuel.h" -const char * const MTG_LAND_TEXTS[] = {"artifact","forest","island","mountain","swamp","plains","other lands"}; +const char * const MTG_LAND_TEXTS[] = { "artifact", "forest", "island", "mountain", "swamp", "plains", "other lands" }; int AIAction::currentId = 0; -int AIAction::Act(){ - GameObserver * g = GameObserver::GetInstance(); - if (player){ - g->cardClick(NULL, player); - return 1; - } - if (ability){ - g->mLayers->actionLayer()->reactToClick(ability,click); - if (target) g->cardClick(target); - return 1; - }else if (click){ //Shouldn't be used, really... - g->cardClick(click,click); - if (target) g->cardClick(target); - return 1; - } - return 0; -} - -AIPlayer::AIPlayer(MTGDeck * deck, string file, string fileSmall) : Player(deck, file, fileSmall) { - nextCardToPlay = NULL; - stats = NULL; - agressivity = 50; - forceBestAbilityUse = false; - Checked = false; - playMode = Player::MODE_AI; -} - -AIPlayer::~AIPlayer(){ - if (stats){ - stats->save(); - SAFE_DELETE(stats); - } - while(!clickstream.empty()){ - AIAction * action = clickstream.front(); - SAFE_DELETE(action); - clickstream.pop(); - } -} -MTGCardInstance * AIPlayer::chooseCard(TargetChooser * tc, MTGCardInstance * source, int random){ - for (int i = 0; i < game->hand->nb_cards; i++){ - MTGCardInstance * card = game->hand->cards[i]; - if (!tc->alreadyHasTarget(card) && tc->canTarget(card)){ - return card; +int AIAction::Act() +{ + GameObserver * g = GameObserver::GetInstance(); + if (player) + { + g->cardClick(NULL, player); + return 1; } - } - return NULL; -} - -int AIPlayer::Act(float dt){ - GameObserver * gameObs = GameObserver::GetInstance(); - if (gameObs->currentPlayer == this) - gameObs->userRequestNextGamePhase(); - return 1; -} - - -void AIPlayer::tapLandsForMana(ManaCost * cost,MTGCardInstance * target){ - if (!cost) return; - DebugTrace(" AI tapping land for mana"); - - ManaCost * pMana = getPotentialMana(target); - ManaCost * diff = pMana->Diff(cost); - delete(pMana); - GameObserver * g = GameObserver::GetInstance(); - - mapused; - for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish - //Make sure we can use the ability - MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]); - AManaProducer * amp = dynamic_cast(a); - if (amp && canHandleCost(amp)){ - MTGCardInstance * card = amp->source; - if (card == target) used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76 - if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){ - used[card] = true; - int doTap = 1; - for (int i=Constants::MTG_NB_COLORS-1; i>= 0; i--){ - if (diff->getCost(i) && amp->output->getCost(i) ){ - diff->remove(i,1); - doTap = 0; - break; - } - } - if (doTap){ - AIAction * action = NEW AIAction(amp,card); - clickstream.push(action); - } - } + if (ability) + { + g->mLayers->actionLayer()->reactToClick(ability, click); + if (target) + g->cardClick(target); + return 1; } - } - delete(diff); - -} - -ManaCost * AIPlayer::getPotentialMana(MTGCardInstance * target){ - ManaCost * result = NEW ManaCost(); - GameObserver * g = GameObserver::GetInstance(); - mapused; - for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish - //Make sure we can use the ability - MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]); - AManaProducer * amp = dynamic_cast(a); - if (amp && canHandleCost(amp)){ - MTGCardInstance * card = amp->source; - if (card == target) used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76 - if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){ - result->add(amp->output); - used[card] = true; - } + else if (click) + { //Shouldn't be used, really... + g->cardClick(click, click); + if (target) + g->cardClick(target); + return 1; } - } - return result; -} - - -int AIPlayer::getEfficiency(AIAction * action){ - return action->getEfficiency(); -} - -int AIPlayer::canHandleCost(MTGAbility * ability){ - //Can't handle sacrifice costs that require a target yet :( - if (ability->cost){ - ExtraCosts * ec = ability->cost->extraCosts; - if (ec){ - for (size_t i = 0; i < ec->costs.size(); i++){ - if (ec->costs[i]->tc) return 0; - } - } - } - return 1; -} - - - -int AIAction::getEfficiency(){ - //TODO add multiplier according to what the player wants - if (efficiency != -1) return efficiency; - if (!ability) return 0; - GameObserver * g = GameObserver::GetInstance(); - ActionStack * s = g->mLayers->stackLayer(); - Player * p = g->currentlyActing(); - if (s->has(ability)) return 0; - - MTGAbility * a = AbilityFactory::getCoreAbility(ability); - - if (!a){ - DebugTrace("FATAL: Ability is NULL in AIAction::getEfficiency()"); return 0; - } +} - if (!((AIPlayer *)p)->canHandleCost(ability)) return 0; - switch (a->aType){ - case MTGAbility::DAMAGER: - { - AADamager * aad = (AADamager *) a; - if (!target){ - Targetable * _t = aad->getTarget(); - if (_t == p->opponent()) efficiency = 90; - else efficiency = 0; - break; +AIPlayer::AIPlayer(MTGDeck * deck, string file, string fileSmall) : + Player(deck, file, fileSmall) +{ + nextCardToPlay = NULL; + stats = NULL; + agressivity = 50; + forceBestAbilityUse = false; + Checked = false; + playMode = Player::MODE_AI; +} + +AIPlayer::~AIPlayer() +{ + if (stats) + { + stats->save(); + SAFE_DELETE(stats); + } + while (!clickstream.empty()) + { + AIAction * action = clickstream.front(); + SAFE_DELETE(action); + clickstream.pop(); + } +} +MTGCardInstance * AIPlayer::chooseCard(TargetChooser * tc, MTGCardInstance * source, int random) +{ + for (int i = 0; i < game->hand->nb_cards; i++) + { + MTGCardInstance * card = game->hand->cards[i]; + if (!tc->alreadyHasTarget(card) && tc->canTarget(card)) + { + return card; } - if ( p == target->controller()){ - efficiency = 0; - }else if (aad->damage->getValue() >= target->toughness){ - efficiency = 100; - }else if (target->toughness){ - efficiency = (50 * aad->damage->getValue()) / target->toughness; - }else{ - efficiency = 0; + } + return NULL; +} + +int AIPlayer::Act(float dt) +{ + GameObserver * gameObs = GameObserver::GetInstance(); + if (gameObs->currentPlayer == this) + gameObs->userRequestNextGamePhase(); + return 1; +} + +void AIPlayer::tapLandsForMana(ManaCost * cost, MTGCardInstance * target) +{ + if (!cost) + return; DebugTrace(" AI tapping land for mana"); + + ManaCost * pMana = getPotentialMana(target); + ManaCost * diff = pMana->Diff(cost); + delete (pMana); + GameObserver * g = GameObserver::GetInstance(); + + map used; + for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++) + { //0 is not a mtgability...hackish + //Make sure we can use the ability + MTGAbility * a = ((MTGAbility *) g->mLayers->actionLayer()->mObjects[i]); + AManaProducer * amp = dynamic_cast (a); + if (amp && canHandleCost(amp)) + { + MTGCardInstance * card = amp->source; + if (card == target) + used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76 + if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() == 1) + { + used[card] = true; + int doTap = 1; + for (int i = Constants::MTG_NB_COLORS - 1; i >= 0; i--) + { + if (diff->getCost(i) && amp->output->getCost(i)) + { + diff->remove(i, 1); + doTap = 0; + break; + } + } + if (doTap) + { + AIAction * action = NEW AIAction(amp, card); + clickstream.push(action); + } + } + } + } + delete (diff); + +} + +ManaCost * AIPlayer::getPotentialMana(MTGCardInstance * target) +{ + ManaCost * result = NEW ManaCost(); + GameObserver * g = GameObserver::GetInstance(); + map used; + for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++) + { //0 is not a mtgability...hackish + //Make sure we can use the ability + MTGAbility * a = ((MTGAbility *) g->mLayers->actionLayer()->mObjects[i]); + AManaProducer * amp = dynamic_cast (a); + if (amp && canHandleCost(amp)) + { + MTGCardInstance * card = amp->source; + if (card == target) + used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76 + if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() == 1) + { + result->add(amp->output); + used[card] = true; + } + } + } + return result; +} + +int AIPlayer::getEfficiency(AIAction * action) +{ + return action->getEfficiency(); +} + +int AIPlayer::canHandleCost(MTGAbility * ability) +{ + //Can't handle sacrifice costs that require a target yet :( + if (ability->cost) + { + ExtraCosts * ec = ability->cost->extraCosts; + if (ec) + { + for (size_t i = 0; i < ec->costs.size(); i++) + { + if (ec->costs[i]->tc) + return 0; + } + } + } + return 1; +} + +int AIAction::getEfficiency() +{ + //TODO add multiplier according to what the player wants + if (efficiency != -1) + return efficiency; + if (!ability) + return 0; + GameObserver * g = GameObserver::GetInstance(); + ActionStack * s = g->mLayers->stackLayer(); + Player * p = g->currentlyActing(); + if (s->has(ability)) + return 0; + + MTGAbility * a = AbilityFactory::getCoreAbility(ability); + + if (!a) + { + DebugTrace("FATAL: Ability is NULL in AIAction::getEfficiency()"); + return 0; + } + + if (!((AIPlayer *) p)->canHandleCost(ability)) + return 0; + switch (a->aType) + { + case MTGAbility::DAMAGER: + { + AADamager * aad = (AADamager *) a; + if (!target) + { + Targetable * _t = aad->getTarget(); + if (_t == p->opponent()) + efficiency = 90; + else + efficiency = 0; + break; + } + if (p == target->controller()) + { + efficiency = 0; + } + else if (aad->damage->getValue() >= target->toughness) + { + efficiency = 100; + } + else if (target->toughness) + { + efficiency = (50 * aad->damage->getValue()) / target->toughness; + } + else + { + efficiency = 0; } break; - } + } case MTGAbility::STANDARD_REGENERATE: - { - MTGCardInstance * _target = (MTGCardInstance *)(a->target); + { + MTGCardInstance * _target = (MTGCardInstance *) (a->target); efficiency = 0; - if (!_target->regenerateTokens && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS && (_target->defenser || _target->blockers.size())){ - efficiency = 95; + if (!_target->regenerateTokens && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS && (_target->defenser + || _target->blockers.size())) + { + efficiency = 95; } //TODO If the card is the target of a damage spell break; - } - case MTGAbility::STANDARD_PREVENT: - { - MTGCardInstance * _target = (MTGCardInstance *)(a->target); + } + case MTGAbility::STANDARD_PREVENT: + { + MTGCardInstance * _target = (MTGCardInstance *) (a->target); efficiency = 0;//starts out low to avoid spamming it when its not needed. - bool NeedPreventing; - NeedPreventing = false; - if(g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS) - { - if((target->defenser || target->blockers.size()) && target->preventable < target->getNextOpponent()->power) NeedPreventing = true; - } - if (p == target->controller() && NeedPreventing == true && !(target->getNextOpponent()->has(Constants::DEATHTOUCH) || target->getNextOpponent()->has(Constants::WITHER))){ - efficiency = 20 * (target->DangerRanking());//increase this chance to be used in combat if the creature blocking/blocked could kill the creature this chance is taking into consideration how good the creature is, best creature will always be the first "saved".. - if(target->toughness == 1 && target->getNextOpponent()->power == 1) efficiency += 15; - //small bonus added for the poor 1/1s, if we can save them, we will unless something else took precidence. - } - //note is the target is being blocked or blocking a creature with wither or deathtouch, it is not even considered for preventing as it is a waste. + bool NeedPreventing; + NeedPreventing = false; + if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS) + { + if ((target->defenser || target->blockers.size()) && target->preventable < target->getNextOpponent()->power) + NeedPreventing = true; + } + if (p == target->controller() && NeedPreventing == true && !(target->getNextOpponent()->has(Constants::DEATHTOUCH) + || target->getNextOpponent()->has(Constants::WITHER))) + { + efficiency = 20 * (target->DangerRanking());//increase this chance to be used in combat if the creature blocking/blocked could kill the creature this chance is taking into consideration how good the creature is, best creature will always be the first "saved".. + if (target->toughness == 1 && target->getNextOpponent()->power == 1) + efficiency += 15; + //small bonus added for the poor 1/1s, if we can save them, we will unless something else took precidence. + } + //note is the target is being blocked or blocking a creature with wither or deathtouch, it is not even considered for preventing as it is a waste. //if its combat blockers, it is being blocked or blocking, and has less prevents the the amount of damage it will be taking, the effeincy is increased slightly and totalled by the danger rank multiplier for final result. //TODO If the card is the target of a damage spell break; - } - case MTGAbility::STANDARD_EQUIP: - { - MTGCardInstance * _target = (MTGCardInstance *)(a->target); - efficiency = 0; - if (p == target->controller() && target->equipment <= 1 && !a->source->target) - { - efficiency = 20 * (target->DangerRanking()); - if(target->hasColor(5)) efficiency += 20;//this is to encourage Ai to equip white creatures in a weenie deck. ultimately it will depend on what had the higher dangerranking. - if(target->power == 1 && target->toughness == 1 && target->isToken == 0) efficiency += 10; //small bonus to encourage equipping nontoken 1/1 creatures. - } - if (p == target->controller() && target->equipment > 2 && !a->source->target) - { - efficiency = 15 * (target->DangerRanking()); - } - break; - } + } + case MTGAbility::STANDARD_EQUIP: + { + MTGCardInstance * _target = (MTGCardInstance *) (a->target); + efficiency = 0; + if (p == target->controller() && target->equipment <= 1 && !a->source->target) + { + efficiency = 20 * (target->DangerRanking()); + if (target->hasColor(5)) + efficiency += 20;//this is to encourage Ai to equip white creatures in a weenie deck. ultimately it will depend on what had the higher dangerranking. + if (target->power == 1 && target->toughness == 1 && target->isToken == 0) + efficiency += 10; //small bonus to encourage equipping nontoken 1/1 creatures. + } + if (p == target->controller() && target->equipment > 2 && !a->source->target) + { + efficiency = 15 * (target->DangerRanking()); + } + break; + } - case MTGAbility::STANDARD_LEVELUP: - { - MTGCardInstance * _target = (MTGCardInstance *)(a->target); + case MTGAbility::STANDARD_LEVELUP: + { + MTGCardInstance * _target = (MTGCardInstance *) (a->target); efficiency = 0; Counter * targetCounter = NULL; - int currentlevel = 0; - if(_target) - { - if(_target->counters && _target->counters->hasCounter("level",0,0)) - { - targetCounter = _target->counters->hasCounter("level",0,0); - currentlevel = targetCounter->nb; - } - } - if (currentlevel < _target->MaxLevelUp){ - efficiency = 85; -//increase the efficeincy of leveling up by a small amount equal to current level. - efficiency += currentlevel; - } + int currentlevel = 0; + if (_target) + { + if (_target->counters && _target->counters->hasCounter("level", 0, 0)) + { + targetCounter = _target->counters->hasCounter("level", 0, 0); + currentlevel = targetCounter->nb; + } + } + if (currentlevel < _target->MaxLevelUp) + { + efficiency = 85; + //increase the efficeincy of leveling up by a small amount equal to current level. + efficiency += currentlevel; + } break; - } - case MTGAbility::STANDARD_PUMP:{ - MTGCardInstance * _target = (MTGCardInstance *)(a->target); -//i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does. - if(g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS) - { - if(_target && BAKA_EFFECT_GOOD) - { - if((_target->defenser || _target->blockers.size()) - && ((_target->power < _target->getNextOpponent()->toughness || _target->toughness < _target->getNextOpponent()->power) - || (_target->has(Constants::TRAMPLE)))){ -//this pump is based on a start eff. of 20 multiplied by how good the creature is. - efficiency = 20*_target->DangerRanking(); - } - if(_target->isAttacker() && !_target->blockers.size()){ -//this means im heading directly for the player, pump this creature as much as possible. + } + case MTGAbility::STANDARD_PUMP: + { + MTGCardInstance * _target = (MTGCardInstance *) (a->target); + //i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does. + if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS) + { + if (_target && BAKA_EFFECT_GOOD) + { + if ((_target->defenser || _target->blockers.size()) && ((_target->power < _target->getNextOpponent()->toughness + || _target->toughness < _target->getNextOpponent()->power) || (_target->has(Constants::TRAMPLE)))) + { + //this pump is based on a start eff. of 20 multiplied by how good the creature is. + efficiency = 20 * _target->DangerRanking(); + } + if (_target->isAttacker() && !_target->blockers.size()) + { + //this means im heading directly for the player, pump this creature as much as possible. + efficiency = 100; + } + } + } + break; + } + case MTGAbility::STANDARD_BECOMES: + { + MTGCardInstance * _target = (MTGCardInstance *) (a->target); + //nothing huge here, just ensuring that Ai makes his noncreature becomers into creatures during first main, so it can actually use them in combat. + if (_target && !_target->hasType("Creature") && g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN) + { efficiency = 100; - } - } - } - break; - } - case MTGAbility::STANDARD_BECOMES: - { - MTGCardInstance * _target = (MTGCardInstance *)(a->target); -//nothing huge here, just ensuring that Ai makes his noncreature becomers into creatures during first main, so it can actually use them in combat. - if(_target && !_target->hasType("Creature") && g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN) - { - efficiency = 100; - } - break; - } + } + break; + } case MTGAbility::MANA_PRODUCER: //can't use mana producers right now :/ - efficiency = 0; - break; + efficiency = 0; + break; default: - if (target){ - AbilityFactory af; - int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY); - if ((suggestion == BAKA_EFFECT_BAD && p==target->controller()) ||(suggestion == BAKA_EFFECT_GOOD && p!=target->controller())){ - efficiency =0; - }else{ - efficiency = WRand() % 5; //Small percentage of chance for unknown abilities + if (target) + { + AbilityFactory af; + int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY); + if ((suggestion == BAKA_EFFECT_BAD && p == target->controller()) || (suggestion == BAKA_EFFECT_GOOD && p + != target->controller())) + { + efficiency = 0; + } + else + { + efficiency = WRand() % 5; //Small percentage of chance for unknown abilities + } } - }else{ - efficiency = WRand() % 10; - } - break; - } - if (p->game->hand->nb_cards == 0) efficiency = (int) ((float) efficiency * 1.3); //increase chance of using ability if hand is empty - if (ability->cost){ - ExtraCosts * ec = ability->cost->extraCosts; - if (ec) efficiency = efficiency / 3; //Decrease chance of using ability if there is an extra cost to use the ability - } - return efficiency; + else + { + efficiency = WRand() % 10; + } + break; + } + if (p->game->hand->nb_cards == 0) + efficiency = (int) ((float) efficiency * 1.3); //increase chance of using ability if hand is empty + if (ability->cost) + { + ExtraCosts * ec = ability->cost->extraCosts; + if (ec) + efficiency = efficiency / 3; //Decrease chance of using ability if there is an extra cost to use the ability + } + return efficiency; } +int AIPlayer::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map * ranking) +{ + if (!a->tc) + { + AIAction * as = NEW AIAction(a, c, NULL); + (*ranking)[as] = 1; + return 1; + } + GameObserver * g = GameObserver::GetInstance(); + for (int i = 0; i < 2; i++) + { + Player * p = g->players[i]; + MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = playerZones[j]; + for (int k = 0; k < zone->nb_cards; k++) + { + MTGCardInstance * t = zone->cards[k]; + if (a->tc->canTarget(t)) + { - - -int AIPlayer::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map * ranking){ - if (!a->tc){ - AIAction * as = NEW AIAction(a,c,NULL); - (*ranking)[as] = 1; + AIAction * as = NEW AIAction(a, c, t); + (*ranking)[as] = 1; + } + } + } + } return 1; - } - GameObserver * g = GameObserver::GetInstance(); - for (int i = 0; i < 2; i++){ - Player * p = g->players[i]; - MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay}; - for (int j = 0; j < 4; j++){ - MTGGameZone * zone = playerZones[j]; - for (int k=0; k < zone->nb_cards; k++){ - MTGCardInstance * t = zone->cards[k]; - if (a->tc->canTarget(t)){ +} - AIAction * as = NEW AIAction(a,c,t); - (*ranking)[as] = 1; +int AIPlayer::selectAbility() +{ + map ranking; + list::iterator it; + GameObserver * g = GameObserver::GetInstance(); + //This loop is extrmely inefficient. TODO: optimize! + ManaCost * totalPotentialMana = getPotentialMana(); + for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++) + { //0 is not a mtgability...hackish + MTGAbility * a = ((MTGAbility *) g->mLayers->actionLayer()->mObjects[i]); + //Skip mana abilities for performance + if (dynamic_cast (a)) + continue; + //Make sure we can use the ability + for (int j = 0; j < game->inPlay->nb_cards; j++) + { + MTGCardInstance * card = game->inPlay->cards[j]; + if (a->isReactingToClick(card, totalPotentialMana)) + { //This test is to avod the huge call to getPotentialManaCost after that + ManaCost * pMana = getPotentialMana(card); + if (a->isReactingToClick(card, pMana)) + createAbilityTargets(a, card, &ranking); + delete (pMana); + } } - } } - } - return 1; + delete totalPotentialMana; + + if (ranking.size()) + { + AIAction * a = ranking.begin()->first; + int chance = 1; + if (!forceBestAbilityUse) + chance = 1 + WRand() % 100; + if (getEfficiency(a) < chance) + { + a = NULL; + } + else + { + DebugTrace("AIPlayer:Using Activated ability"); + tapLandsForMana(a->ability->cost, a->click); + clickstream.push(a); + } + map::iterator it2; + for (it2 = ranking.begin(); it2 != ranking.end(); it2++) + { + if (a != it2->first) + delete (it2->first); + } + } + return 1; } -int AIPlayer::selectAbility(){ - mapranking; - list::iterator it; - GameObserver * g = GameObserver::GetInstance(); - //This loop is extrmely inefficient. TODO: optimize! - ManaCost * totalPotentialMana = getPotentialMana(); - for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish - MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]); - //Skip mana abilities for performance - if (dynamic_cast(a)) continue; - //Make sure we can use the ability - for (int j=0; j < game->inPlay->nb_cards; j++){ - MTGCardInstance * card = game->inPlay->cards[j]; - if (a->isReactingToClick(card,totalPotentialMana)){ //This test is to avod the huge call to getPotentialManaCost after that - ManaCost * pMana = getPotentialMana(card); - if (a->isReactingToClick(card,pMana)) - createAbilityTargets(a, card, &ranking); - delete(pMana); - } - } - } - delete totalPotentialMana; +int AIPlayer::interruptIfICan() +{ + GameObserver * g = GameObserver::GetInstance(); - if (ranking.size()){ - AIAction * a = ranking.begin()->first; - int chance = 1; - if (!forceBestAbilityUse) chance = 1 + WRand() % 100; - if (getEfficiency(a) < chance){ - a = NULL; - }else{ - DebugTrace("AIPlayer:Using Activated ability"); - tapLandsForMana(a->ability->cost,a->click); - clickstream.push(a); + if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this) + { + if (!clickstream.empty()) + g->mLayers->stackLayer()->cancelInterruptOffer(); + else + g->mLayers->stackLayer()->setIsInterrupting(this); + return 1; } - map::iterator it2; - for (it2 = ranking.begin(); it2!=ranking.end(); it2++){ - if (a != it2->first) delete(it2->first); - } - } - return 1; + return 0; } - - -int AIPlayer::interruptIfICan(){ - GameObserver * g = GameObserver::GetInstance(); - - if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){ - if (!clickstream.empty()) g->mLayers->stackLayer()->cancelInterruptOffer(); - else g->mLayers->stackLayer()->setIsInterrupting(this); - return 1; - } - return 0; +int AIPlayer::effectBadOrGood(MTGCardInstance * card, int mode, TargetChooser * tc) +{ + int id = card->getMTGId(); + AbilityFactory af; + int autoGuess = af.magicText(id, NULL, card, mode, tc); + if (autoGuess) + return autoGuess; + return BAKA_EFFECT_DONTKNOW; } -int AIPlayer::effectBadOrGood(MTGCardInstance * card, int mode, TargetChooser * tc){ - int id = card->getMTGId(); - AbilityFactory af; - int autoGuess = af.magicText(id,NULL,card, mode, tc); - if (autoGuess) return autoGuess; - return BAKA_EFFECT_DONTKNOW; +int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget) +{ + vector potentialTargets; + TargetChooser * tc = _tc; + int nbtargets = 0; + GameObserver * gameObs = GameObserver::GetInstance(); + int checkOnly = 0; + if (tc) + { + checkOnly = 1; + } + else + { + tc = gameObs->getCurrentTargetChooser(); + } + if (!tc) + return 0; + if (!(gameObs->currentlyActing() == this)) + return 0; + Player * target = forceTarget; + + if (!target) + { + target = this; + int cardEffect = effectBadOrGood(tc->source, MODE_TARGET, tc); + if (cardEffect != BAKA_EFFECT_GOOD) + { + target = this->opponent(); + } + } + + if (!tc->alreadyHasTarget(target) && tc->canTarget(target) && nbtargets < 50) + { + for (int i = 0; i < 3; i++) + { //Increase probability to target a player when this is possible + potentialTargets.push_back(target); + nbtargets++; + } + if (checkOnly) + return 1; + } + MTGPlayerCards * playerZones = target->game; + MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = zones[j]; + for (int k = 0; k < zone->nb_cards; k++) + { + MTGCardInstance * card = zone->cards[k]; + if (!tc->alreadyHasTarget(card) && tc->canTarget(card) && nbtargets < 50) + { + if (checkOnly) + return 1; + int multiplier = 1; + if (getStats() && getStats()->isInTop(card, 10)) + { + multiplier++; + if (getStats()->isInTop(card, 5)) + { + multiplier++; + if (getStats()->isInTop(card, 3)) + { + multiplier++; + } + } + } + for (int l = 0; l < multiplier; l++) + { + potentialTargets.push_back(card); + nbtargets++; + } + } + } + } + if (nbtargets) + { + int i = WRand() % nbtargets; + int type = potentialTargets[i]->typeAsTarget(); + switch (type) + { + case TARGET_CARD: + { + MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]); + clickstream.push(NEW AIAction(card)); + return 1; + break; + } + case TARGET_PLAYER: + { + Player * player = ((Player *) potentialTargets[i]); + clickstream.push(NEW AIAction(player)); + return 1; + break; + } + } + } + //Couldn't find any valid target, + //usually that's because we played a card that has bad side effects (ex: when X comes into play, return target land you own to your hand) + //so we try again to choose a target in the other player's field... + if (checkOnly) + return 0; + int cancel = gameObs->cancelCurrentAction(); + if (!cancel && !forceTarget) + return chooseTarget(_tc, target->opponent()); + + //ERROR!!! + return 0; } - - -int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget){ - vectorpotentialTargets; - TargetChooser * tc = _tc; - int nbtargets = 0; - GameObserver * gameObs = GameObserver::GetInstance(); - int checkOnly = 0; - if (tc){ - checkOnly = 1; - }else{ - tc = gameObs->getCurrentTargetChooser(); - } - if (!tc) return 0; - if (!(gameObs->currentlyActing() == this)) return 0; - Player * target = forceTarget; - - if (!target){ - target = this; - int cardEffect = effectBadOrGood(tc->source, MODE_TARGET, tc); - if (cardEffect != BAKA_EFFECT_GOOD){ - target = this->opponent(); - } - } - - if (!tc->alreadyHasTarget(target) && tc->canTarget(target) && nbtargets < 50){ - for (int i = 0; i < 3; i++){ //Increase probability to target a player when this is possible - potentialTargets.push_back(target); - nbtargets++; - } - if (checkOnly) return 1; - } - MTGPlayerCards * playerZones = target->game; - MTGGameZone * zones[] = {playerZones->hand,playerZones->library,playerZones->inPlay, playerZones->graveyard}; - for (int j = 0; j < 4; j++){ - MTGGameZone * zone = zones[j]; - for (int k=0; k< zone->nb_cards; k++){ - MTGCardInstance * card = zone->cards[k]; - if (!tc->alreadyHasTarget(card) && tc->canTarget(card) && nbtargets < 50){ - if (checkOnly) return 1; - int multiplier = 1; - if (getStats() && getStats()->isInTop(card,10)){ - multiplier++; - if (getStats()->isInTop(card,5)){ - multiplier++; - if (getStats()->isInTop(card,3)){ - multiplier++; - } - } - } - for (int l=0; l < multiplier; l++){ - potentialTargets.push_back(card); - nbtargets++; - } - } - } - } - if (nbtargets){ - int i = WRand() % nbtargets; - int type = potentialTargets[i]->typeAsTarget(); - switch(type){ - case TARGET_CARD: - { - MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]); - clickstream.push(NEW AIAction(card)); - return 1; - break; - } - case TARGET_PLAYER: - { - Player * player = ((Player *) potentialTargets[i]); - clickstream.push(NEW AIAction(player)); - return 1; - break; - } - } - } - //Couldn't find any valid target, - //usually that's because we played a card that has bad side effects (ex: when X comes into play, return target land you own to your hand) - //so we try again to choose a target in the other player's field... - if (checkOnly) return 0; - int cancel = gameObs->cancelCurrentAction(); - if ( !cancel && !forceTarget) return chooseTarget(_tc,target->opponent()); - - //ERROR!!! - return 0; -} - -int AIPlayer::getCreaturesInfo(Player * player, int neededInfo , int untapMode, int canAttack){ - int result = 0; - CardDescriptor cd; - cd.init(); - cd.setType("Creature"); - cd.unsecureSetTapped(untapMode); - MTGCardInstance * card = NULL; - while((card = cd.nextmatch(player->game->inPlay, card))){ - if (!canAttack || card->canAttack()){ - if (neededInfo == INFO_NBCREATURES){ - result++; - }else{ - result+=card->power; - } - } - } - return result; -} - - - -int AIPlayer::chooseAttackers(){ - //Attack with all creatures - //How much damage can the other player do during his next Attack ? - int opponentForce = getCreaturesInfo(opponent(),INFO_CREATURESPOWER); - int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES); - int myForce = getCreaturesInfo(this,INFO_CREATURESPOWER,-1,1); - int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES, -1,1); - bool attack = ((myCreatures > opponentCreatures) || (myForce > opponentForce) || (myForce > 2*opponent()->life)); - if (agressivity > 80 && !attack && life > opponentForce) { - opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES,-1); - opponentForce = getCreaturesInfo(opponent(),INFO_CREATURESPOWER,-1); - attack = (myCreatures >= opponentCreatures && myForce > opponentForce) || (myForce > opponentForce) || (myForce > opponent()->life); - } - printf("Choose attackers : %i %i %i %i -> %i\n", opponentForce, opponentCreatures, myForce, myCreatures, attack); - if (attack){ +int AIPlayer::getCreaturesInfo(Player * player, int neededInfo, int untapMode, int canAttack) +{ + int result = 0; CardDescriptor cd; cd.init(); - cd.setType("creature"); + cd.setType("Creature"); + cd.unsecureSetTapped(untapMode); MTGCardInstance * card = NULL; - GameObserver * g = GameObserver::GetInstance(); - MTGAbility * a = g->mLayers->actionLayer()->getAbility(MTGAbility::MTG_ATTACK_RULE); - while((card = cd.nextmatch(game->inPlay, card))){ - g->mLayers->actionLayer()->reactToClick(a,card); + while ((card = cd.nextmatch(player->game->inPlay, card))) + { + if (!canAttack || card->canAttack()) + { + if (neededInfo == INFO_NBCREATURES) + { + result++; + } + else + { + result += card->power; + } + } } - } - return 1; + return result; +} + +int AIPlayer::chooseAttackers() +{ + //Attack with all creatures + //How much damage can the other player do during his next Attack ? + int opponentForce = getCreaturesInfo(opponent(), INFO_CREATURESPOWER); + int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES); + int myForce = getCreaturesInfo(this, INFO_CREATURESPOWER, -1, 1); + int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES, -1, 1); + bool attack = ((myCreatures > opponentCreatures) || (myForce > opponentForce) || (myForce > 2 * opponent()->life)); + if (agressivity > 80 && !attack && life > opponentForce) + { + opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES, -1); + opponentForce = getCreaturesInfo(opponent(), INFO_CREATURESPOWER, -1); + attack = (myCreatures >= opponentCreatures && myForce > opponentForce) || (myForce > opponentForce) || (myForce + > opponent()->life); + } + printf("Choose attackers : %i %i %i %i -> %i\n", opponentForce, opponentCreatures, myForce, myCreatures, attack); + if (attack) + { + CardDescriptor cd; + cd.init(); + cd.setType("creature"); + MTGCardInstance * card = NULL; + GameObserver * g = GameObserver::GetInstance(); + MTGAbility * a = g->mLayers->actionLayer()->getAbility(MTGAbility::MTG_ATTACK_RULE); + while ((card = cd.nextmatch(game->inPlay, card))) + { + g->mLayers->actionLayer()->reactToClick(a, card); + } + } + return 1; } /* Can I first strike my oponent and get away with murder ? */ -int AIPlayer::canFirstStrikeKill(MTGCardInstance * card, MTGCardInstance *ennemy){ - if (ennemy->has(Constants::FIRSTSTRIKE) || ennemy->has(Constants::DOUBLESTRIKE)) return 0; - if (!(card->has(Constants::FIRSTSTRIKE) || card->has(Constants::DOUBLESTRIKE))) return 0; - if (!(card->power >= ennemy->toughness)) return 0; - if (!(card->power >= ennemy->toughness + 1) && ennemy->has(Constants::FLANKING)) return 0; - return 1; +int AIPlayer::canFirstStrikeKill(MTGCardInstance * card, MTGCardInstance *ennemy) +{ + if (ennemy->has(Constants::FIRSTSTRIKE) || ennemy->has(Constants::DOUBLESTRIKE)) + return 0; + if (!(card->has(Constants::FIRSTSTRIKE) || card->has(Constants::DOUBLESTRIKE))) + return 0; + if (!(card->power >= ennemy->toughness)) + return 0; + if (!(card->power >= ennemy->toughness + 1) && ennemy->has(Constants::FLANKING)) + return 0; + return 1; } -int AIPlayer::chooseBlockers(){ - map opponentsToughness; - int opponentForce = getCreaturesInfo(opponent(),INFO_CREATURESPOWER); - //int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES, -1); - //int myForce = getCreaturesInfo(this,INFO_CREATURESPOWER); - //int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES, -1); - CardDescriptor cd; - cd.init(); - cd.setType("Creature"); - cd.unsecureSetTapped(-1); - MTGCardInstance * card = NULL; - GameObserver * g = GameObserver::GetInstance(); - MTGAbility * a = g->mLayers->actionLayer()->getAbility(MTGAbility::MTG_BLOCK_RULE); +int AIPlayer::chooseBlockers() +{ + map opponentsToughness; + int opponentForce = getCreaturesInfo(opponent(), INFO_CREATURESPOWER); + //int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES, -1); + //int myForce = getCreaturesInfo(this,INFO_CREATURESPOWER); + //int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES, -1); + CardDescriptor cd; + cd.init(); + cd.setType("Creature"); + cd.unsecureSetTapped(-1); + MTGCardInstance * card = NULL; + GameObserver * g = GameObserver::GetInstance(); + MTGAbility * a = g->mLayers->actionLayer()->getAbility(MTGAbility::MTG_BLOCK_RULE); - while((card = cd.nextmatch(game->inPlay, card))){ - g->mLayers->actionLayer()->reactToClick(a,card); - int set = 0; - while(!set){ - if (!card->defenser){ - set = 1; - }else{ - MTGCardInstance * attacker = card->defenser; - map::iterator it = opponentsToughness.find(attacker); - if ( it == opponentsToughness.end()){ - opponentsToughness[attacker] = attacker->toughness; - it = opponentsToughness.find(attacker); - } - if (opponentsToughness[attacker] > 0 && getStats() && getStats()->isInTop(attacker,3,false)){ - opponentsToughness[attacker]-= card->power; - set = 1; - }else{ - g->mLayers->actionLayer()->reactToClick(a,card); - } - } - } - } - card = NULL; - while((card = cd.nextmatch(game->inPlay, card))){ - if (card->defenser && opponentsToughness[card->defenser] > 0){ - while (card->defenser){ - - g->mLayers->actionLayer()->reactToClick(a,card); - } - } - } - card = NULL; - while((card = cd.nextmatch(game->inPlay, card))){ - if(!card->defenser){ - g->mLayers->actionLayer()->reactToClick(a,card); - int set = 0; - while(!set){ - if (!card->defenser){ - set = 1; - }else{ - MTGCardInstance * attacker = card->defenser; - if (opponentsToughness[attacker] <= 0 || - (card->toughness <= attacker->power && opponentForce*2 nbOpponents()>1){ - g->mLayers->actionLayer()->reactToClick(a,card); - }else{ - set = 1; - } - } - } - } - } - return 1; -} - -int AIPlayer::orderBlockers(){ - - GameObserver * g = GameObserver::GetInstance(); - if (ORDER == g->combatStep && g->currentPlayer==this) + while ((card = cd.nextmatch(game->inPlay, card))) { - DebugTrace("AIPLAYER: order blockers"); - g->userRequestNextGamePhase(); //TODO clever rank of blockers - return 1; + g->mLayers->actionLayer()->reactToClick(a, card); + int set = 0; + while (!set) + { + if (!card->defenser) + { + set = 1; + } + else + { + MTGCardInstance * attacker = card->defenser; + map::iterator it = opponentsToughness.find(attacker); + if (it == opponentsToughness.end()) + { + opponentsToughness[attacker] = attacker->toughness; + it = opponentsToughness.find(attacker); + } + if (opponentsToughness[attacker] > 0 && getStats() && getStats()->isInTop(attacker, 3, false)) + { + opponentsToughness[attacker] -= card->power; + set = 1; + } + else + { + g->mLayers->actionLayer()->reactToClick(a, card); + } + } + } } + card = NULL; + while ((card = cd.nextmatch(game->inPlay, card))) + { + if (card->defenser && opponentsToughness[card->defenser] > 0) + { + while (card->defenser) + { - return 0; + g->mLayers->actionLayer()->reactToClick(a, card); + } + } + } + card = NULL; + while ((card = cd.nextmatch(game->inPlay, card))) + { + if (!card->defenser) + { + g->mLayers->actionLayer()->reactToClick(a, card); + int set = 0; + while (!set) + { + if (!card->defenser) + { + set = 1; + } + else + { + MTGCardInstance * attacker = card->defenser; + if (opponentsToughness[attacker] <= 0 || (card->toughness <= attacker->power && opponentForce * 2 < life + && !canFirstStrikeKill(card, attacker)) || attacker->nbOpponents() > 1) + { + g->mLayers->actionLayer()->reactToClick(a, card); + } + else + { + set = 1; + } + } + } + } + } + return 1; } -int AIPlayer::affectCombatDamages(CombatStep step){ - GameObserver * g = GameObserver::GetInstance(); - GuiCombat * gc = g->mLayers->combatLayer(); - for (vector::iterator attacker = gc->attackers.begin(); attacker != gc->attackers.end(); ++attacker) - gc->autoaffectDamage(*attacker, step); - return 1; +int AIPlayer::orderBlockers() +{ + + GameObserver * g = GameObserver::GetInstance(); + if (ORDER == g->combatStep && g->currentPlayer == this) + { + DebugTrace("AIPLAYER: order blockers"); + g->userRequestNextGamePhase(); //TODO clever rank of blockers + return 1; + } + + return 0; +} + +int AIPlayer::affectCombatDamages(CombatStep step) +{ + GameObserver * g = GameObserver::GetInstance(); + GuiCombat * gc = g->mLayers->combatLayer(); + for (vector::iterator attacker = gc->attackers.begin(); attacker != gc->attackers.end(); ++attacker) + gc->autoaffectDamage(*attacker, step); + return 1; } //TODO: Deprecate combatDamages -int AIPlayer::combatDamages(){ - //int result = 0; - GameObserver * gameObs = GameObserver::GetInstance(); - int currentGamePhase = gameObs->getCurrentGamePhase(); +int AIPlayer::combatDamages() +{ + //int result = 0; + GameObserver * gameObs = GameObserver::GetInstance(); + int currentGamePhase = gameObs->getCurrentGamePhase(); - if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS) return orderBlockers(); + if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS) + return orderBlockers(); - if (currentGamePhase != Constants::MTG_PHASE_COMBATDAMAGE) return 0; + if (currentGamePhase != Constants::MTG_PHASE_COMBATDAMAGE) + return 0; - return 0; + return 0; } - -AIStats * AIPlayer::getStats(){ - if (!stats){ - char statFile[512]; - sprintf(statFile,JGE_GET_RES("ai/baka/stats/%s.stats").c_str(), opponent()->deckFileSmall.c_str()); - stats = NEW AIStats(this, statFile); - } - return stats; -} - -AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * opponent, int deckid){ - char deckFile[512]; - char avatarFile[512]; - char deckFileSmall[512]; - - if (deckid == GameStateDuel::MENUITEM_EVIL_TWIN){ //Evil twin - sprintf(deckFile, "%s", opponent->deckFile.c_str()); - DebugTrace(opponent->deckFile); - sprintf(avatarFile, "%s", "baka.jpg"); - sprintf(deckFileSmall, "%s", "ai_baka_eviltwin"); - }else{ - if (!deckid){ - int nbdecks = 0; - int found = 1; - while (found){ - found = 0; - char buffer[512]; - sprintf(buffer, JGE_GET_RES("ai/baka/deck%i.txt").c_str(),nbdecks+1); - std::ifstream file(buffer); - if(file){ - found = 1; - file.close(); - nbdecks++; - } - } - if (!nbdecks) return NULL; - deckid = 1 + WRand() % (nbdecks); - } - sprintf(deckFile, JGE_GET_RES("ai/baka/deck%i.txt").c_str(),deckid); - sprintf(avatarFile, "avatar%i.jpg",deckid); - sprintf(deckFileSmall, "ai_baka_deck%i",deckid); - } - - MTGDeck * tempDeck = NEW MTGDeck(deckFile, collection); - //MTGPlayerCards * deck = NEW MTGPlayerCards(tempDeck); - AIPlayerBaka * baka = NEW AIPlayerBaka(tempDeck,deckFile, deckFileSmall, avatarFile); - baka->deckId = deckid; - - delete tempDeck; - return baka; -} - - -MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * type){ - int maxCost = -1; - MTGCardInstance * nextCardToPlay = NULL; - MTGCardInstance * card = NULL; - CardDescriptor cd; - cd.init(); - cd.setType(type); - card = NULL; - while((card = cd.nextmatch(game->hand, card))){ - if (card->hasType(Subtypes::TYPE_CREATURE) && this->castrestrictedcreature < 0 && this->castrestrictedspell < 0) continue; - if (card->hasType(Subtypes::TYPE_ENCHANTMENT) && this->castrestrictedspell < 0) continue; - if (card->hasType(Subtypes::TYPE_ARTIFACT) && this->castrestrictedspell < 0) continue; - if (card->hasType(Subtypes::TYPE_SORCERY) && this->castrestrictedspell < 0) continue; - if (card->hasType(Subtypes::TYPE_INSTANT) && this->castrestrictedspell < 0) continue; - if (card->hasType(Subtypes::TYPE_LAND) && !this->canPutLandsIntoPlay) continue; - if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name)) continue; - int currentCost = card->getManaCost()->getConvertedCost(); - int hasX = card->getManaCost()->hasX(); - if ((currentCost > maxCost || hasX) && pMana->canAfford(card->getManaCost())){ - TargetChooserFactory tcf; - TargetChooser * tc = tcf.createTargetChooser(card); - int shouldPlayPercentage = 10; - if (tc){ - int hasTarget = (chooseTarget(tc)); - delete tc; - if (!hasTarget)continue; - shouldPlayPercentage = 90; - }else{ - int shouldPlay = effectBadOrGood(card); - if (shouldPlay == BAKA_EFFECT_GOOD){ - shouldPlayPercentage = 90; - }else if(BAKA_EFFECT_DONTKNOW == shouldPlay){ - shouldPlayPercentage = 80; - } - } - //Reduce the chances of playing a spell with X cost if available mana is low - if (hasX){ - int xDiff = pMana->getConvertedCost() - currentCost; - if (xDiff < 0) xDiff = 0; - shouldPlayPercentage = shouldPlayPercentage - static_cast((shouldPlayPercentage * 1.9f) / (1 + xDiff)); - } - - if (WRand() % 100 > shouldPlayPercentage) continue; - nextCardToPlay = card; - maxCost = currentCost; - if(hasX) maxCost = pMana->getConvertedCost(); - } - } - return nextCardToPlay; -} - -AIPlayerBaka::AIPlayerBaka(MTGDeck * deck, string file, string fileSmall, string avatarFile) : AIPlayer(deck, file, fileSmall) { - mAvatarTex = resources.RetrieveTexture(avatarFile,RETRIEVE_LOCK,TEXTURE_SUB_AVATAR); - - if(!mAvatarTex){ - avatarFile = "baka.jpg"; - mAvatarTex = resources.RetrieveTexture(avatarFile,RETRIEVE_LOCK,TEXTURE_SUB_AVATAR); - } - - if(mAvatarTex) - mAvatar = resources.RetrieveQuad(avatarFile, 0, 0, 35, 50,"bakaAvatar",RETRIEVE_NORMAL,TEXTURE_SUB_AVATAR); - else - mAvatar = NULL; - - initTimer(); -} - - -void AIPlayerBaka::initTimer(){ - timer = 0.1f; -} - -int AIPlayerBaka::computeActions(){ - GameObserver * g = GameObserver::GetInstance(); - Player * p = g->currentPlayer; - if (!(g->currentlyActing() == this)) return 0; - if (g->mLayers->actionLayer()->menuObject){ - g->mLayers->actionLayer()->doReactTo(0); - return 1; - } - if (chooseTarget()) return 1; - int currentGamePhase = g->getCurrentGamePhase(); - if (g->isInterrupting == this){ // interrupting - selectAbility(); - return 1; - }else if (p == this && g->mLayers->stackLayer()->count(0,NOT_RESOLVED) == 0){ //standard actions - CardDescriptor cd; - MTGCardInstance * card = NULL; - switch(currentGamePhase){ - case Constants::MTG_PHASE_FIRSTMAIN: - case Constants::MTG_PHASE_SECONDMAIN: +AIStats * AIPlayer::getStats() +{ + if (!stats) { - - bool potential = false; - ManaCost * currentMana = manaPool; - if (!currentMana->getConvertedCost()){ - currentMana = getPotentialMana(); - potential = true; - } - - nextCardToPlay = FindCardToPlay(currentMana, "land"); - //look for the most expensive creature we can afford - if(castrestrictedspell == 0 && nospellinstant == 0){ - if(onlyonecast == 0 || castcount < 2){ - if(onlyoneinstant == 0 || castcount < 2){ - if(castrestrictedcreature == 0 && nocreatureinstant == 0){ - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "creature"); - } - //Let's Try an enchantment maybe ? - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "enchantment"); - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "artifact"); - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "sorcery"); - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "instant"); - - } - } - } - if (potential) delete(currentMana); - if (nextCardToPlay){ - if (potential){ - ///////////////////////// - //had to force this on Ai other wise it would pay nothing but 1 color for a sunburst card. - //this does not teach it to use manaproducer more effectively, it simply allow it to use the manaproducers it does understand better on sunburst by force. - if(nextCardToPlay->has(Constants::SUNBURST)){ - ManaCost * SunCheck = manaPool; - SunCheck = getPotentialMana(); - for(int i = Constants::MTG_NB_COLORS - 1; i > 0 ;i--){ - //sunburst for Ai - if(SunCheck->hasColor(i)){ - if(nextCardToPlay->getManaCost()->hasColor(i) > 0){//do nothing if the card already has this color. - }else{ - if(nextCardToPlay->sunburst < nextCardToPlay->getManaCost()->getConvertedCost()){ - nextCardToPlay->getManaCost()->add(i,1); - nextCardToPlay->getManaCost()->remove(0,1); - nextCardToPlay->sunburst += 1; - } - } - } - } - delete(SunCheck); - } -///////////////////////// - tapLandsForMana(nextCardToPlay->getManaCost()); - } - AIAction * a = NEW AIAction(nextCardToPlay); - clickstream.push(a); - return 1; - } - else - { - selectAbility(); - } - if(p->getManaPool()->getConvertedCost() > 0 && Checked == false)//not the best thing ever, but allows the Ai a chance to double check if its mana pool has something before moving on, atleast one time. - { - Checked = true; - computeActions(); - } - break; + char statFile[512]; + sprintf(statFile, JGE_GET_RES("ai/baka/stats/%s.stats").c_str(), opponent()->deckFileSmall.c_str()); + stats = NEW AIStats(this, statFile); } - case Constants::MTG_PHASE_COMBATATTACKERS: - chooseAttackers(); - break; - case Constants::MTG_PHASE_ENDOFTURN: - Checked = false; - break; - default: - selectAbility(); - break; - } - }else{ - cout << "my turn" << endl; - switch(currentGamePhase){ - case Constants::MTG_PHASE_COMBATBLOCKERS: - chooseBlockers(); - break; - default: - break; - } - return 1; - } - return 1; -}; - -int AIPlayer::receiveEvent(WEvent * event){ - if (getStats()) return getStats()->receiveEvent(event); - return 0; + return stats; } -void AIPlayer::Render(){ +AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * opponent, int deckid) +{ + char deckFile[512]; + char avatarFile[512]; + char deckFileSmall[512]; + + if (deckid == GameStateDuel::MENUITEM_EVIL_TWIN) + { //Evil twin + sprintf(deckFile, "%s", opponent->deckFile.c_str()); + DebugTrace(opponent->deckFile); + sprintf(avatarFile, "%s", "baka.jpg"); + sprintf(deckFileSmall, "%s", "ai_baka_eviltwin"); + } + else + { + if (!deckid) + { + int nbdecks = 0; + int found = 1; + while (found) + { + found = 0; + char buffer[512]; + sprintf(buffer, JGE_GET_RES("ai/baka/deck%i.txt").c_str(), nbdecks + 1); + std::ifstream file(buffer); + if (file) + { + found = 1; + file.close(); + nbdecks++; + } + } + if (!nbdecks) + return NULL; + deckid = 1 + WRand() % (nbdecks); + } + sprintf(deckFile, JGE_GET_RES("ai/baka/deck%i.txt").c_str(), deckid); + sprintf(avatarFile, "avatar%i.jpg", deckid); + sprintf(deckFileSmall, "ai_baka_deck%i", deckid); + } + + MTGDeck * tempDeck = NEW MTGDeck(deckFile, collection); + //MTGPlayerCards * deck = NEW MTGPlayerCards(tempDeck); + AIPlayerBaka * baka = NEW AIPlayerBaka(tempDeck, deckFile, deckFileSmall, avatarFile); + baka->deckId = deckid; + + delete tempDeck; + return baka; +} + +MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * type) +{ + int maxCost = -1; + MTGCardInstance * nextCardToPlay = NULL; + MTGCardInstance * card = NULL; + CardDescriptor cd; + cd.init(); + cd.setType(type); + card = NULL; + while ((card = cd.nextmatch(game->hand, card))) + { + if (card->hasType(Subtypes::TYPE_CREATURE) && this->castrestrictedcreature < 0 && this->castrestrictedspell < 0) + continue; + if (card->hasType(Subtypes::TYPE_ENCHANTMENT) && this->castrestrictedspell < 0) + continue; + if (card->hasType(Subtypes::TYPE_ARTIFACT) && this->castrestrictedspell < 0) + continue; + if (card->hasType(Subtypes::TYPE_SORCERY) && this->castrestrictedspell < 0) + continue; + if (card->hasType(Subtypes::TYPE_INSTANT) && this->castrestrictedspell < 0) + continue; + if (card->hasType(Subtypes::TYPE_LAND) && !this->canPutLandsIntoPlay) + continue; + if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name)) + continue; + int currentCost = card->getManaCost()->getConvertedCost(); + int hasX = card->getManaCost()->hasX(); + if ((currentCost > maxCost || hasX) && pMana->canAfford(card->getManaCost())) + { + TargetChooserFactory tcf; + TargetChooser * tc = tcf.createTargetChooser(card); + int shouldPlayPercentage = 10; + if (tc) + { + int hasTarget = (chooseTarget(tc)); + delete tc; + if (!hasTarget) + continue; + shouldPlayPercentage = 90; + } + else + { + int shouldPlay = effectBadOrGood(card); + if (shouldPlay == BAKA_EFFECT_GOOD) + { + shouldPlayPercentage = 90; + } + else if (BAKA_EFFECT_DONTKNOW == shouldPlay) + { + shouldPlayPercentage = 80; + } + } + //Reduce the chances of playing a spell with X cost if available mana is low + if (hasX) + { + int xDiff = pMana->getConvertedCost() - currentCost; + if (xDiff < 0) + xDiff = 0; + shouldPlayPercentage = shouldPlayPercentage - static_cast ((shouldPlayPercentage * 1.9f) / (1 + xDiff)); + } + + if (WRand() % 100 > shouldPlayPercentage) + continue; + nextCardToPlay = card; + maxCost = currentCost; + if (hasX) + maxCost = pMana->getConvertedCost(); + } + } + return nextCardToPlay; +} + +AIPlayerBaka::AIPlayerBaka(MTGDeck * deck, string file, string fileSmall, string avatarFile) : + AIPlayer(deck, file, fileSmall) +{ + mAvatarTex = resources.RetrieveTexture(avatarFile, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR); + + if (!mAvatarTex) + { + avatarFile = "baka.jpg"; + mAvatarTex = resources.RetrieveTexture(avatarFile, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR); + } + + if (mAvatarTex) + mAvatar = resources.RetrieveQuad(avatarFile, 0, 0, 35, 50, "bakaAvatar", RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR); + else + mAvatar = NULL; + + initTimer(); +} + +void AIPlayerBaka::initTimer() +{ + timer = 0.1f; +} + +int AIPlayerBaka::computeActions() +{ + GameObserver * g = GameObserver::GetInstance(); + Player * p = g->currentPlayer; + if (!(g->currentlyActing() == this)) + return 0; + if (g->mLayers->actionLayer()->menuObject) + { + g->mLayers->actionLayer()->doReactTo(0); + return 1; + } + if (chooseTarget()) + return 1; + int currentGamePhase = g->getCurrentGamePhase(); + if (g->isInterrupting == this) + { // interrupting + selectAbility(); + return 1; + } + else if (p == this && g->mLayers->stackLayer()->count(0, NOT_RESOLVED) == 0) + { //standard actions + CardDescriptor cd; + MTGCardInstance * card = NULL; + switch (currentGamePhase) + { + case Constants::MTG_PHASE_FIRSTMAIN: + case Constants::MTG_PHASE_SECONDMAIN: + { + + bool potential = false; + ManaCost * currentMana = manaPool; + if (!currentMana->getConvertedCost()) + { + currentMana = getPotentialMana(); + potential = true; + } + + nextCardToPlay = FindCardToPlay(currentMana, "land"); + //look for the most expensive creature we can afford + if (castrestrictedspell == 0 && nospellinstant == 0) + { + if (onlyonecast == 0 || castcount < 2) + { + if (onlyoneinstant == 0 || castcount < 2) + { + if (castrestrictedcreature == 0 && nocreatureinstant == 0) + { + if (!nextCardToPlay) + nextCardToPlay = FindCardToPlay(currentMana, "creature"); + } + //Let's Try an enchantment maybe ? + if (!nextCardToPlay) + nextCardToPlay = FindCardToPlay(currentMana, "enchantment"); + if (!nextCardToPlay) + nextCardToPlay = FindCardToPlay(currentMana, "artifact"); + if (!nextCardToPlay) + nextCardToPlay = FindCardToPlay(currentMana, "sorcery"); + if (!nextCardToPlay) + nextCardToPlay = FindCardToPlay(currentMana, "instant"); + + } + } + } + if (potential) + delete (currentMana); + if (nextCardToPlay) + { + if (potential) + { + ///////////////////////// + //had to force this on Ai other wise it would pay nothing but 1 color for a sunburst card. + //this does not teach it to use manaproducer more effectively, it simply allow it to use the manaproducers it does understand better on sunburst by force. + if (nextCardToPlay->has(Constants::SUNBURST)) + { + ManaCost * SunCheck = manaPool; + SunCheck = getPotentialMana(); + for (int i = Constants::MTG_NB_COLORS - 1; i > 0; i--) + { + //sunburst for Ai + if (SunCheck->hasColor(i)) + { + if (nextCardToPlay->getManaCost()->hasColor(i) > 0) + {//do nothing if the card already has this color. + } + else + { + if (nextCardToPlay->sunburst < nextCardToPlay->getManaCost()->getConvertedCost()) + { + nextCardToPlay->getManaCost()->add(i, 1); + nextCardToPlay->getManaCost()->remove(0, 1); + nextCardToPlay->sunburst += 1; + } + } + } + } + delete (SunCheck); + } + ///////////////////////// + tapLandsForMana(nextCardToPlay->getManaCost()); + } + AIAction * a = NEW AIAction(nextCardToPlay); + clickstream.push(a); + return 1; + } + else + { + selectAbility(); + } + if (p->getManaPool()->getConvertedCost() > 0 && Checked == false)//not the best thing ever, but allows the Ai a chance to double check if its mana pool has something before moving on, atleast one time. + { + Checked = true; + computeActions(); + } + break; + } + case Constants::MTG_PHASE_COMBATATTACKERS: + chooseAttackers(); + break; + case Constants::MTG_PHASE_ENDOFTURN: + Checked = false; + break; + default: + selectAbility(); + break; + } + } + else + { + cout << "my turn" << endl; + switch (currentGamePhase) + { + case Constants::MTG_PHASE_COMBATBLOCKERS: + chooseBlockers(); + break; + default: + break; + } + return 1; + } + return 1; +} +; + +int AIPlayer::receiveEvent(WEvent * event) +{ + if (getStats()) + return getStats()->receiveEvent(event); + return 0; +} + +void AIPlayer::Render() +{ #ifdef RENDER_AI_STATS - if (getStats()) getStats()->Render(); + if (getStats()) getStats()->Render(); #endif } -int AIPlayerBaka::Act(float dt){ - GameObserver * g = GameObserver::GetInstance(); +int AIPlayerBaka::Act(float dt) +{ + GameObserver * g = GameObserver::GetInstance(); - if (!(g->currentlyActing() == this)){ - return 0; - } - - int currentGamePhase = g->getCurrentGamePhase(); - - oldGamePhase = currentGamePhase; - - timer-= dt; - if (timer>0){ - return 0; - } - initTimer(); - if (combatDamages()){ - return 0; - } - interruptIfICan(); - if (!(g->currentlyActing() == this)){ - DebugTrace("Cannot interrupt"); - return 0; - } - if (clickstream.empty()) computeActions(); - if (clickstream.empty()){ - if (g->isInterrupting == this){ - g->mLayers->stackLayer()->cancelInterruptOffer(); //endOfInterruption(); - }else{ - g->userRequestNextGamePhase(); + if (!(g->currentlyActing() == this)) + { + return 0; } - } else { - AIAction * action = clickstream.front(); - action->Act(); - SAFE_DELETE(action); - clickstream.pop(); - } - return 1; -}; + + int currentGamePhase = g->getCurrentGamePhase(); + + oldGamePhase = currentGamePhase; + + timer -= dt; + if (timer > 0) + { + return 0; + } + initTimer(); + if (combatDamages()) + { + return 0; + } + interruptIfICan(); + if (!(g->currentlyActing() == this)) + { + DebugTrace("Cannot interrupt"); + return 0; + } + if (clickstream.empty()) + computeActions(); + if (clickstream.empty()) + { + if (g->isInterrupting == this) + { + g->mLayers->stackLayer()->cancelInterruptOffer(); //endOfInterruption(); + } + else + { + g->userRequestNextGamePhase(); + } + } + else + { + AIAction * action = clickstream.front(); + action->Act(); + SAFE_DELETE(action); + clickstream.pop(); + } + return 1; +} +; diff --git a/projects/mtg/src/AIStats.cpp b/projects/mtg/src/AIStats.cpp index da6d7d154..d18900613 100644 --- a/projects/mtg/src/AIStats.cpp +++ b/projects/mtg/src/AIStats.cpp @@ -7,166 +7,209 @@ #include "WEvent.h" #include "AllAbilities.h" //TODO:better comments this is too cryptic to work on by anyone but original coder. -bool compare_aistats(AIStat * first, AIStat * second){ - float damage1 = static_cast(first->value / first->occurences); - float damage2 = static_cast(second->value / second->occurences); - return (damage1 > damage2); +bool compare_aistats(AIStat * first, AIStat * second) +{ + float damage1 = static_cast (first->value / first->occurences); + float damage2 = static_cast (second->value / second->occurences); + return (damage1 > damage2); } -AIStats::AIStats(Player * _player, char * _filename){ - filename = _filename; - load(_filename); - player = _player; +AIStats::AIStats(Player * _player, char * _filename) +{ + filename = _filename; + load(_filename); + player = _player; } -AIStats::~AIStats(){ - list::iterator it; - for ( it=stats.begin() ; it != stats.end(); it++ ){ - AIStat * stat = *it; - delete stat; - } +AIStats::~AIStats() +{ + list::iterator it; + for (it = stats.begin(); it != stats.end(); it++) + { + AIStat * stat = *it; + delete stat; + } } -void AIStats::updateStatsCard(MTGCardInstance * cardInstance, Damage * damage, float multiplier){ - MTGCard * card = cardInstance->model; - AIStat * stat = find(card); - if (!stat){ - stat = NEW AIStat(card->getMTGId(),0,1,0); - stats.push_back(stat); - } - if (damage->target == player){ - stat->value+= multiplier * STATS_PLAYER_MULTIPLIER * damage->damage; - }else if (damage->target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){ - MTGCardInstance * target = (MTGCardInstance *)damage->target; - if (target->controller() == player && !target->isInPlay()){ - //One of my creatures got lethal damage... - stat->value+= multiplier * STATS_CREATURE_MULTIPLIER * damage->damage; +void AIStats::updateStatsCard(MTGCardInstance * cardInstance, Damage * damage, float multiplier) +{ + MTGCard * card = cardInstance->model; + AIStat * stat = find(card); + if (!stat) + { + stat = NEW AIStat(card->getMTGId(), 0, 1, 0); + stats.push_back(stat); + } + if (damage->target == player) + { + stat->value += multiplier * STATS_PLAYER_MULTIPLIER * damage->damage; + } + else if (damage->target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) + { + MTGCardInstance * target = (MTGCardInstance *) damage->target; + if (target->controller() == player && !target->isInPlay()) + { + //One of my creatures got lethal damage... + stat->value += multiplier * STATS_CREATURE_MULTIPLIER * damage->damage; + } } - } } -int AIStats::receiveEvent(WEvent * event){ - WEventDamage * e = dynamic_cast(event); - if (!e) return 0; //we take only Damage events into accountright now - Damage * damage = e->damage; - MTGGameZone * opponentZone = player->opponent()->game->inPlay; +int AIStats::receiveEvent(WEvent * event) +{ + WEventDamage * e = dynamic_cast (event); + if (!e) + return 0; //we take only Damage events into accountright now + Damage * damage = e->damage; + MTGGameZone * opponentZone = player->opponent()->game->inPlay; - MTGCardInstance * card = damage->source; - updateStatsCard(card,damage); + MTGCardInstance * card = damage->source; + updateStatsCard(card, damage); - //Auras on damage source can be the cause - for (int i = 0; i < opponentZone->nb_cards; ++i){ - MTGCardInstance * aura = opponentZone->cards[i]; - if (aura->target == card){ - updateStatsCard(aura,damage, STATS_AURA_MULTIPLIER); + //Auras on damage source can be the cause + for (int i = 0; i < opponentZone->nb_cards; ++i) + { + MTGCardInstance * aura = opponentZone->cards[i]; + if (aura->target == card) + { + updateStatsCard(aura, damage, STATS_AURA_MULTIPLIER); + } } - } - GameObserver * g = GameObserver::GetInstance(); - //Lords - map lords; - for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish - MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]); - if (ALord * al = dynamic_cast(a)) { - if (al->cards.find(card)!= al->cards.end() && opponentZone->hasCard(al->source)){ - lords[al->source] = 1; - } + GameObserver * g = GameObserver::GetInstance(); + //Lords + map lords; + for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++) + { //0 is not a mtgability...hackish + MTGAbility * a = ((MTGAbility *) g->mLayers->actionLayer()->mObjects[i]); + if (ALord * al = dynamic_cast(a)) + { + if (al->cards.find(card) != al->cards.end() && opponentZone->hasCard(al->source)) + { + lords[al->source] = 1; + } + } } - } - if (size_t nb = lords.size()){ - for (map::iterator it = lords.begin();it !=lords.end();++it){ - updateStatsCard(it->first,damage, STATS_LORD_MULTIPLIER/nb); + if (size_t nb = lords.size()) + { + for (map::iterator it = lords.begin(); it != lords.end(); ++it) + { + updateStatsCard(it->first, damage, STATS_LORD_MULTIPLIER / nb); + } } - } - stats.sort(compare_aistats); //this could be slow, if it is, let's run it only at the end of the turn - return 1; //is this meant to return 0 or 1? + stats.sort(compare_aistats); //this could be slow, if it is, let's run it only at the end of the turn + return 1; //is this meant to return 0 or 1? } //TODO:what does this do? -bool AIStats::isInTop(MTGCardInstance * card, unsigned int max, bool tooSmallCountsForTrue ){ - if (stats.size()model; - int id = source->getMTGId(); - list::iterator it; - for ( it=stats.begin() ; it != stats.end(); it++ ){ - if (n >= max) return false; - AIStat * stat = *it; - if (stat->source == id){ - if ((stat->value + card->DangerRanking()) >=3) return true; - return false; - } - n++; - } - return false; -} - -AIStat * AIStats::find(MTGCard * source){ - int id = source->getMTGId(); - list::iterator it; - for ( it=stats.begin() ; it != stats.end(); it++ ){ - AIStat * stat = *it; - if (stat->source == id) return stat; - } - return NULL; -} - -void AIStats::load(char * filename){ - std::ifstream file(filename); - std::string s; - - if(file){ - while(std::getline(file,s)){ - int cardid = atoi(s.c_str()); - std::getline(file,s); - int value = atoi(s.c_str()); - std::getline(file,s); - int direct = atoi(s.c_str()); - AIStat * stat = NEW AIStat(cardid,value,1,direct); - stats.push_back(stat); - } - file.close(); - }else{ - //TODO Error management - } -} -void AIStats::save(){ - std::ofstream file(filename.c_str()); - char writer[128]; - if (file){ +bool AIStats::isInTop(MTGCardInstance * card, unsigned int max, bool tooSmallCountsForTrue) +{ + if (stats.size() < max) + return tooSmallCountsForTrue; + unsigned int n = 0; + MTGCard * source = card->model; + int id = source->getMTGId(); list::iterator it; - for ( it=stats.begin() ; it != stats.end(); it++ ){ - AIStat * stat = *it; - if (stat->value > 0){ - sprintf(writer,"%i\n%i\n%i\n", stat->source,stat->value/2,stat->direct); - file<= max) + return false; + AIStat * stat = *it; + if (stat->source == id) + { + if ((stat->value + card->DangerRanking()) >= 3) + return true; + return false; + } + n++; + } + return false; +} + +AIStat * AIStats::find(MTGCard * source) +{ + int id = source->getMTGId(); + list::iterator it; + for (it = stats.begin(); it != stats.end(); it++) + { + AIStat * stat = *it; + if (stat->source == id) + return stat; + } + return NULL; +} + +void AIStats::load(char * filename) +{ + std::ifstream file(filename); + std::string s; + + if (file) + { + while (std::getline(file, s)) + { + int cardid = atoi(s.c_str()); + std::getline(file, s); + int value = atoi(s.c_str()); + std::getline(file, s); + int direct = atoi(s.c_str()); + AIStat * stat = NEW AIStat(cardid, value, 1, direct); + stats.push_back(stat); + } + file.close(); + } + else + { + //TODO Error management + } +} +void AIStats::save() +{ + std::ofstream file(filename.c_str()); + char writer[128]; + if (file) + { + list::iterator it; + for (it = stats.begin(); it != stats.end(); it++) + { + AIStat * stat = *it; + if (stat->value > 0) + { + sprintf(writer, "%i\n%i\n%i\n", stat->source, stat->value / 2, stat->direct); + file << writer; + } + } + file.close(); } - file.close(); - } } -void AIStats::Render(){ - GameObserver * g = GameObserver::GetInstance(); - float x0 = 10; - if (player == g->players[1]) x0 = 280; - JRenderer::GetInstance()->FillRoundRect(x0,10,200,180,5,ARGB(50,0,0,0)); +void AIStats::Render() +{ + GameObserver * g = GameObserver::GetInstance(); + float x0 = 10; + if (player == g->players[1]) + x0 = 280; + JRenderer::GetInstance()->FillRoundRect(x0, 10, 200, 180, 5, ARGB(50,0,0,0)); - WFont * f = resources.GetWFont(Fonts::MAIN_FONT); - int i = 0; - char buffer[512]; - list::iterator it; - for (it = stats.begin(); it !=stats.end(); ++it){ - if (i>10) break; - AIStat * stat = *it; - if (stat->value > 0){ - MTGCard * card = GameApp::collection->getCardById(stat->source); - if (card) { - sprintf(buffer, "%s %i", card->data->getName().c_str(), stat->value); - f->DrawString(buffer,x0+5,10 + 16 *(float)i); - i++; - } + WFont * f = resources.GetWFont(Fonts::MAIN_FONT); + int i = 0; + char buffer[512]; + list::iterator it; + for (it = stats.begin(); it != stats.end(); ++it) + { + if (i > 10) + break; + AIStat * stat = *it; + if (stat->value > 0) + { + MTGCard * card = GameApp::collection->getCardById(stat->source); + if (card) + { + sprintf(buffer, "%s %i", card->data->getName().c_str(), stat->value); + f->DrawString(buffer, x0 + 5, 10 + 16 * (float) i); + i++; + } + } } - } } diff --git a/projects/mtg/src/ActionElement.cpp b/projects/mtg/src/ActionElement.cpp index 3f2ca33f9..0ba8c375d 100644 --- a/projects/mtg/src/ActionElement.cpp +++ b/projects/mtg/src/ActionElement.cpp @@ -5,34 +5,42 @@ #include "Targetable.h" #include "TargetChooser.h" -ActionElement::ActionElement(int id):JGuiObject(id){ - activeState = INACTIVE; - modal = 0; - waitingForAnswer = 0; - currentPhase = -1; - newPhase = -1; - tc = NULL; - isClone = 0; +ActionElement::ActionElement(int id) : + JGuiObject(id) +{ + activeState = INACTIVE; + modal = 0; + waitingForAnswer = 0; + currentPhase = -1; + newPhase = -1; + tc = NULL; + isClone = 0; } -ActionElement::~ActionElement(){ - if (!isClone){ - SAFE_DELETE(tc); - } +ActionElement::~ActionElement() +{ + if (!isClone) + { + SAFE_DELETE(tc); + } } -int ActionElement::getActivity(){ +int ActionElement::getActivity() +{ - return activeState; + return activeState; } - -int ActionElement::isReactingToTargetClick(Targetable * object){ - if (object && object->typeAsTarget() == TARGET_CARD) return isReactingToClick((MTGCardInstance *)object); - return 0; +int ActionElement::isReactingToTargetClick(Targetable * object) +{ + if (object && object->typeAsTarget() == TARGET_CARD) + return isReactingToClick((MTGCardInstance *) object); + return 0; } -int ActionElement::reactToTargetClick(Targetable * object){ - if (object->typeAsTarget() == TARGET_CARD) return reactToClick((MTGCardInstance *)object); - return 0; +int ActionElement::reactToTargetClick(Targetable * object) +{ + if (object->typeAsTarget() == TARGET_CARD) + return reactToClick((MTGCardInstance *) object); + return 0; } diff --git a/projects/mtg/src/ActionLayer.cpp b/projects/mtg/src/ActionLayer.cpp index 91940c883..bf14fefb5 100644 --- a/projects/mtg/src/ActionLayer.cpp +++ b/projects/mtg/src/ActionLayer.cpp @@ -5,270 +5,336 @@ #include "Targetable.h" #include "WEvent.h" -MTGAbility* ActionLayer::getAbility(int type){ - for (int i = 1; i < mCount; i++){ - MTGAbility * a = ((MTGAbility *)mObjects[i]); - if (a->aType == type){ - return a; - } - } - return NULL; +MTGAbility* ActionLayer::getAbility(int type) +{ + for (int i = 1; i < mCount; i++) + { + MTGAbility * a = ((MTGAbility *) mObjects[i]); + if (a->aType == type) + { + return a; + } + } + return NULL; } -int ActionLayer::moveToGarbage(ActionElement * e){ - int i = getIndexOf(e); - if (i != -1){ - if (isWaitingForAnswer() == e) setCurrentWaitingAction(NULL); - e->destroy(); - mObjects.erase(mObjects.begin()+i); - mCount--; - garbage.push_back(e); +int ActionLayer::moveToGarbage(ActionElement * e) +{ + int i = getIndexOf(e); + if (i != -1) + { + if (isWaitingForAnswer() == e) + setCurrentWaitingAction(NULL); + e->destroy(); + mObjects.erase(mObjects.begin() + i); + mCount--; + garbage.push_back(e); + return 1; + } + return 0; + +} + +int ActionLayer::cleanGarbage() +{ + for (size_t i = 0; i < garbage.size(); ++i) + { + delete (garbage[i]); + } + garbage.clear(); return 1; - } - return 0; - } -int ActionLayer::cleanGarbage(){ - for (size_t i = 0; i < garbage.size(); ++i){ - delete(garbage[i]); - } - garbage.clear(); - return 1; +int ActionLayer::reactToClick(ActionElement * ability, MTGCardInstance * card) +{ + int result = ability->reactToClick(card); + if (result) + stuffHappened = 1; + return result; } -int ActionLayer::reactToClick(ActionElement * ability, MTGCardInstance * card){ - int result = ability->reactToClick(card); - if (result) stuffHappened = 1; - return result; +int ActionLayer::reactToTargetClick(ActionElement* ability, Targetable * card) +{ + int result = ability->reactToTargetClick(card); + if (result) + stuffHappened = 1; + return result; } - -int ActionLayer::reactToTargetClick(ActionElement* ability, Targetable * card){ - int result = ability->reactToTargetClick(card); - if (result) stuffHappened = 1; - return result; -} - -bool ActionLayer::CheckUserInput(JButton key){ - GameObserver * g = GameObserver::GetInstance(); - if (g->waitForExtraPayment && key == JGE_BTN_SEC){ - g->waitForExtraPayment = NULL; - return 1; - } - if (menuObject){ +bool ActionLayer::CheckUserInput(JButton key) +{ + GameObserver * g = GameObserver::GetInstance(); + if (g->waitForExtraPayment && key == JGE_BTN_SEC) + { + g->waitForExtraPayment = NULL; + return 1; + } + if (menuObject) + { + return false; + } + for (int i = 0; i < mCount; i++) + { + if (mObjects[i] != NULL) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + if (currentAction->CheckUserInput(key)) + return true; + } + } return false; - } - for (int i=0;iCheckUserInput(key)) return true; - } - } - return false; } - -void ActionLayer::Update(float dt){ - stuffHappened = 0; - if (menuObject){ - abilitiesMenu->Update(dt); - return; - } - modal = 0; - GameObserver* game = GameObserver::GetInstance(); - for (int i=mCount -1 ;i>=0;i--){ - if (mObjects[i]!= NULL){ - ActionElement * currentAction = (ActionElement *)mObjects[i]; - if (currentAction->testDestroy()) - game->removeObserver(currentAction); +void ActionLayer::Update(float dt) +{ + stuffHappened = 0; + if (menuObject) + { + abilitiesMenu->Update(dt); + return; } - } - int newPhase = game->getCurrentGamePhase(); - for (int i=0;inewPhase = newPhase; - currentAction->Update(dt); - currentAction->currentPhase = newPhase; + modal = 0; + GameObserver* game = GameObserver::GetInstance(); + for (int i = mCount - 1; i >= 0; i--) + { + if (mObjects[i] != NULL) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + if (currentAction->testDestroy()) + game->removeObserver(currentAction); + } + } + int newPhase = game->getCurrentGamePhase(); + for (int i = 0; i < mCount; i++) + { + if (mObjects[i] != NULL) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + currentAction->newPhase = newPhase; + currentAction->Update(dt); + currentAction->currentPhase = newPhase; + } } - } - if (cantCancel){ + if (cantCancel) + { + ActionElement * ae = isWaitingForAnswer(); + if (ae && !ae->tc->validTargetsExist()) + { + cantCancel = 0; + cancelCurrentAction(); + } + } +} + +void ActionLayer::Render() +{ + if (menuObject) + { + abilitiesMenu->Render(); + return; + } + for (int i = 0; i < mCount; i++) + { + if (mObjects[i] != NULL) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + currentAction->Render(); + } + } +} + +void ActionLayer::setCurrentWaitingAction(ActionElement * ae) +{ + assert(!ae || !currentWaitingAction);//this assert causes crashes when may abilities overlap each other on ai. this conidiation is preexsiting. + currentWaitingAction = ae; + if (!ae) + cantCancel = 0; +} + +TargetChooser * ActionLayer::getCurrentTargetChooser() +{ + if (currentWaitingAction && currentWaitingAction->waitingForAnswer) + return currentWaitingAction->tc; + return NULL; +} + +int ActionLayer::cancelCurrentAction() +{ ActionElement * ae = isWaitingForAnswer(); - if (ae && !ae->tc->validTargetsExist()) { - cantCancel = 0; - cancelCurrentAction(); + if (!ae) + return 0; + if (cantCancel && ae->tc->validTargetsExist()) + return 0; + ae->waitingForAnswer = 0; //TODO MOVE THIS IN ActionElement + setCurrentWaitingAction(NULL); + return 1; +} + +ActionElement * ActionLayer::isWaitingForAnswer() +{ + if (currentWaitingAction && currentWaitingAction->waitingForAnswer) + return currentWaitingAction; + return NULL; +} + +int ActionLayer::stillInUse(MTGCardInstance * card) +{ + for (int i = 0; i < mCount; i++) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + if (currentAction->stillInUse(card)) + return 1; } - } + return 0; } -void ActionLayer::Render (){ - if (menuObject){ - abilitiesMenu->Render(); - return; - } - for (int i=0;iRender(); +int ActionLayer::receiveEventPlus(WEvent * event) +{ + int result = 0; + for (int i = 0; i < mCount; i++) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + result += currentAction->receiveEvent(event); } - } + return 0; } +int ActionLayer::isReactingToTargetClick(Targetable * card) +{ + int result = 0; -void ActionLayer::setCurrentWaitingAction(ActionElement * ae){ - assert(!ae || !currentWaitingAction);//this assert causes crashes when may abilities overlap each other on ai. this conidiation is preexsiting. - currentWaitingAction = ae; - if (!ae) cantCancel = 0; + if (isWaitingForAnswer()) + return -1; + + for (int i = 0; i < mCount; i++) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + result += currentAction->isReactingToTargetClick(card); + } + return result; } -TargetChooser * ActionLayer::getCurrentTargetChooser(){ - if (currentWaitingAction && currentWaitingAction->waitingForAnswer) - return currentWaitingAction->tc; - return NULL; -} +int ActionLayer::reactToTargetClick(Targetable * card) +{ + int result = 0; -int ActionLayer::cancelCurrentAction(){ - ActionElement * ae = isWaitingForAnswer(); - if (!ae) return 0; - if (cantCancel && ae->tc->validTargetsExist()) return 0; - ae->waitingForAnswer = 0; //TODO MOVE THIS IN ActionElement - setCurrentWaitingAction(NULL); - return 1; -} + ActionElement * ae = isWaitingForAnswer(); + if (ae) + return reactToTargetClick(ae, card); -ActionElement * ActionLayer::isWaitingForAnswer(){ - if (currentWaitingAction && currentWaitingAction->waitingForAnswer) - return currentWaitingAction; - return NULL; -} - -int ActionLayer::stillInUse(MTGCardInstance * card){ - for (int i=0;istillInUse(card)) return 1; - } - return 0; -} - -int ActionLayer::receiveEventPlus(WEvent * event){ - int result = 0; - for (int i=0;ireceiveEvent(event); - } - return 0; -} - -int ActionLayer::isReactingToTargetClick(Targetable * card){ - int result = 0; - - if (isWaitingForAnswer()) return -1; - - for (int i=0;iisReactingToTargetClick(card); - } - return result; -} - -int ActionLayer::reactToTargetClick(Targetable * card){ - int result = 0; - - ActionElement * ae = isWaitingForAnswer(); - if (ae) return reactToTargetClick(ae,card); - - for (int i=0;ireactToTargetClick(card); - } - return result; + for (int i = 0; i < mCount; i++) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + result += currentAction->reactToTargetClick(card); + } + return result; } //TODO Simplify with only object !!! -int ActionLayer::isReactingToClick(MTGCardInstance * card){ - int result = 0; +int ActionLayer::isReactingToClick(MTGCardInstance * card) +{ + int result = 0; - if (isWaitingForAnswer()) return -1; + if (isWaitingForAnswer()) + return -1; - for (int i=0;iisReactingToClick(card); - } - - return result; -} - -int ActionLayer::reactToClick(MTGCardInstance * card){ - int result = 0; - - ActionElement * ae = isWaitingForAnswer(); - if (ae) return reactToClick(ae,card); - - for (int i=0;igetDisplayName().c_str()); - - for (int i=0;iisReactingToTargetClick(object)){ - abilitiesMenu->Add(i,currentAction->getMenuText()); + for (int i = 0; i < mCount; i++) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + result += currentAction->isReactingToClick(card); } - } - if (!must) abilitiesMenu->Add(kCancelMenuID, "Cancel"); - else cantCancel = 1; - modal = 1; + + return result; } -void ActionLayer::doReactTo(int menuIndex){ +int ActionLayer::reactToClick(MTGCardInstance * card) +{ + int result = 0; - if (menuObject){ - int controlid = abilitiesMenu->mObjects[menuIndex]->GetId(); - DebugTrace("ActionLayer::doReactTo " << controlid); - ButtonPressed(0,controlid); - } + ActionElement * ae = isWaitingForAnswer(); + if (ae) + return reactToClick(ae, card); + + for (int i = 0; i < mCount; i++) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + result += reactToClick(currentAction, card); + if (result) + return result; + } + return result; } -void ActionLayer::ButtonPressed(int controllerid, int controlid){ - if (controlid != -1){ - ActionElement * currentAction = (ActionElement *)mObjects[controlid]; - currentAction->reactToTargetClick(menuObject); - }else{ - GameObserver::GetInstance()->mLayers->stackLayer()->endOfInterruption(); - } - menuObject = 0; +void ActionLayer::setMenuObject(Targetable * object, bool must) +{ + if (!object) + { + DebugTrace("FATAL: ActionLayer::setMenuObject"); + return; + } + menuObject = object; + + SAFE_DELETE(abilitiesMenu); + + abilitiesMenu = NEW SimpleMenu(10, this, Fonts::MAIN_FONT, 100, 100, object->getDisplayName().c_str()); + + for (int i = 0; i < mCount; i++) + { + ActionElement * currentAction = (ActionElement *) mObjects[i]; + if (currentAction->isReactingToTargetClick(object)) + { + abilitiesMenu->Add(i, currentAction->getMenuText()); + } + } + if (!must) + abilitiesMenu->Add(kCancelMenuID, "Cancel"); + else + cantCancel = 1; + modal = 1; +} + +void ActionLayer::doReactTo(int menuIndex) +{ + + if (menuObject) + { + int controlid = abilitiesMenu->mObjects[menuIndex]->GetId(); + DebugTrace("ActionLayer::doReactTo " << controlid); + ButtonPressed(0, controlid); + } +} + +void ActionLayer::ButtonPressed(int controllerid, int controlid) +{ + if (controlid != -1) + { + ActionElement * currentAction = (ActionElement *) mObjects[controlid]; + currentAction->reactToTargetClick(menuObject); + } + else + { + GameObserver::GetInstance()->mLayers->stackLayer()->endOfInterruption(); + } + menuObject = 0; } -ActionLayer::ActionLayer(){ - menuObject = NULL; - abilitiesMenu = NULL; - stuffHappened = 0; - currentWaitingAction = NULL; - cantCancel = 0; +ActionLayer::ActionLayer() +{ + menuObject = NULL; + abilitiesMenu = NULL; + stuffHappened = 0; + currentWaitingAction = NULL; + cantCancel = 0; } -ActionLayer::~ActionLayer(){ - for (int i=mCount-1;i>=0;i--){ - moveToGarbage((ActionElement *)mObjects[i]); - } - SAFE_DELETE(abilitiesMenu); - cleanGarbage(); +ActionLayer::~ActionLayer() +{ + for (int i = mCount - 1; i >= 0; i--) + { + moveToGarbage((ActionElement *) mObjects[i]); + } + SAFE_DELETE(abilitiesMenu); + cleanGarbage(); } diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 7c47adf72..a2cfcd9b3 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -1,6 +1,6 @@ /* - The Action Stack contains all information for Game Events that can be interrupted (Interruptible) -*/ + The Action Stack contains all information for Game Events that can be interrupted (Interruptible) + */ #include "PrecompiledHeader.h" #include "ActionStack.h" @@ -18,912 +18,1138 @@ #include /* - NextGamePhase requested by user -*/ + NextGamePhase requested by user + */ -int NextGamePhase::resolve(){ - GameObserver::GetInstance()->nextGamePhase(); - return 1; +int NextGamePhase::resolve() +{ + GameObserver::GetInstance()->nextGamePhase(); + return 1; } const string NextGamePhase::getDisplayName() const { - std::ostringstream stream; - stream << "NextGamePhase. (Current phase is: " << PhaseRing::phaseName(GameObserver::GetInstance()->getCurrentGamePhase()) << ")"; + std::ostringstream stream; + stream << "NextGamePhase. (Current phase is: " << PhaseRing::phaseName(GameObserver::GetInstance()->getCurrentGamePhase()) + << ")"; - return stream.str(); + return stream.str(); } -void NextGamePhase::Render(){ - GameObserver * g = GameObserver::GetInstance(); - int nextPhase = (g->getCurrentGamePhase() + 1) % Constants::MTG_PHASE_CLEANUP; - - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - char buffer[200]; - int playerId = 1; - if (g->currentActionPlayer == GameObserver::GetInstance()->players[1]) playerId = 2; - - sprintf(buffer, "%s %i : -> %s", _("Player").c_str(), playerId, _(PhaseRing::phaseName(nextPhase)).c_str()); - - mFont->DrawString(buffer, x + 30 , y, JGETEXT_LEFT); -} - -NextGamePhase::NextGamePhase(int id): Interruptible(id){ - mHeight = 40; - type = ACTION_NEXTGAMEPHASE; -} - -ostream& NextGamePhase::toString(ostream& out) const +void NextGamePhase::Render() { - out << "NextGamePhase ::: "; - return out; -} - -const string Interruptible::getDisplayName() const -{ - return typeid(*this).name(); -} - -void Interruptible::Render(MTGCardInstance * source, JQuad * targetQuad, string alt1, string alt2, string action, bool bigQuad){ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->DrawString(_(action).c_str(), x + 30 , y, JGETEXT_LEFT); - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * quad = resources.RetrieveCard(source,CACHE_THUMB); - if (!quad) - quad = CardGui::AlternateThumbQuad(source); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - float scale = mHeight / quad->mHeight; - renderer->RenderQuad(quad, x+10*scale , y+15*scale , 0,scale,scale); - }else if (alt1.size()){ - mFont->DrawString(_(alt1).c_str(),x,y-15); - } - - if (bigQuad) - { - Pos pos = Pos(CardGui::BigWidth / 2, CardGui::BigHeight / 2 - 10, 1.0, 0.0, 220); - CardGui::DrawCard(source, pos, CardSelectorSingleton::Instance()->GetDrawMode()); - } - - if (targetQuad){ - float backupX = targetQuad->mHotSpotX; - float backupY = targetQuad->mHotSpotY; - targetQuad->SetColor(ARGB(255,255,255,255)); - targetQuad->SetHotSpot(targetQuad->mWidth / 2, targetQuad->mHeight / 2); - float scale = mHeight / targetQuad->mHeight; - renderer->RenderQuad(targetQuad, x + 150 , y+15*scale , 0,scale,scale); - targetQuad->SetHotSpot(backupX, backupY); - }else if (alt2.size()){ - mFont->DrawString(_(alt2).c_str(),x+120,y); - } -} - -/* Ability */ -int StackAbility::resolve(){ - return (ability->resolve()); -} -void StackAbility::Render(){ - string action = ability->getMenuText(); - MTGCardInstance * source = ability->source; - string alt1 = source->getName(); - - Targetable * _target = ability->target; - if (ability->tc){ - Targetable * t = ability->tc->getNextTarget(); - if(t) _target = t; - } - Damageable * target = NULL; - if (_target!= ability->source && (_target->typeAsTarget() == TARGET_CARD || _target->typeAsTarget() == TARGET_PLAYER)){ - target = (Damageable *) _target; - } - - JQuad * quad = NULL; - string alt2 = ""; - if (target){ - quad = target->getIcon(); - if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) { - alt2 = ((MTGCardInstance *)target)->name; - } - } - - Interruptible::Render(source,quad,alt1,alt2,action); -} -StackAbility::StackAbility(int id,MTGAbility * _ability): Interruptible(id),ability(_ability){ - type=ACTION_ABILITY; -} - -ostream& StackAbility::toString(ostream& out) const -{ - out << "StackAbility ::: ability : " << ability; - return out; -} - -const string StackAbility::getDisplayName() const -{ - std::ostringstream stream; - stream << "StackAbility. (Source: " << ability->source->getDisplayName() << ")"; - - return stream.str(); -} - -/* Spell Cast */ - -Spell::Spell(MTGCardInstance * _source): Interruptible(0){ - source = _source; - mHeight= 40; - type = ACTION_SPELL; - cost = NEW ManaCost(); - tc = NULL; - from = _source->getCurrentZone(); -} - - -Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost, int payResult): Interruptible(id), tc(tc),cost(_cost), payResult(payResult){ - source = _source; - mHeight = 40; - type = ACTION_SPELL; - from = _source->getCurrentZone(); -} - -int Spell::computeX(MTGCardInstance * card){ - ManaCost * c = cost->Diff(card->getManaCost()); - int x = c->getCost(Constants::MTG_NB_COLORS); - delete c; - return x; -} - -int Spell::computeXX(MTGCardInstance * card){ - ManaCost * c = cost->Diff(card->getManaCost()); - int xx = c->getCost(Constants::MTG_NB_COLORS)/2; - delete c; - return xx; -} - - -bool Spell::FullfilledAlternateCost(const int &costType) -{ - bool hasFullfilledAlternateCost = false; - - switch(costType) - { - case ManaCost::MANA_PAID_WITH_KICKER: - hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_KICKER); - break; - case ManaCost::MANA_PAID_WITH_ALTERNATIVE: - hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_ALTERNATIVE); - break; - case ManaCost::MANA_PAID_WITH_BUYBACK: - hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_BUYBACK); - break; - case ManaCost::MANA_PAID_WITH_FLASHBACK: - hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_FLASHBACK); - break; - case ManaCost::MANA_PAID_WITH_RETRACE: - hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_RETRACE); - break; - } - - return hasFullfilledAlternateCost; -} - -const string Spell::getDisplayName() const { - return source->getName(); -} -Spell::~Spell(){ - SAFE_DELETE(cost); - SAFE_DELETE(tc); -} - -int Spell::resolve(){ - GameObserver * game = GameObserver::GetInstance(); - if (!source->hasType("instant") && !source->hasType("sorcery")){ - Player * p = source->controller(); - source = p->game->putInZone(source,from,p->game->battlefield); - from = p->game->battlefield; - } - - //Play SFX - if (options[Options::SFXVOLUME].number > 0){ - JSample * sample = source->getSample(); - if (sample){ - JSoundSystem::GetInstance()->PlaySample(sample); - } - } - - AbilityFactory af; - af.addAbilities(game->mLayers->actionLayer()->getMaxId(), this); - return 1; -} - -MTGCardInstance * Spell::getNextCardTarget(MTGCardInstance * previous){ - if (!tc) return NULL; - return tc->getNextCardTarget(previous); -} - Player * Spell::getNextPlayerTarget(Player * previous){ - if (!tc) return NULL; - return tc->getNextPlayerTarget(previous); -} - Damageable * Spell::getNextDamageableTarget(Damageable * previous){ - if (!tc) return NULL; - return tc->getNextDamageableTarget(previous); -} - Interruptible * Spell::getNextInterruptible(Interruptible * previous, int type){ - if (!tc) return NULL; - return tc->getNextInterruptible(previous,type); -} - Spell * Spell::getNextSpellTarget(Spell * previous){ - if (!tc) return NULL; - return tc->getNextSpellTarget(previous); -} - Damage * Spell::getNextDamageTarget(Damage * previous){ - if (!tc) return NULL; - return tc->getNextDamageTarget(previous); -} - Targetable * Spell::getNextTarget(Targetable * previous, int type ){ - if (!tc) return NULL; - return tc->getNextTarget(previous,type); -} - - int Spell::getNbTargets(){ - if (!tc) return 0; - return tc->cursor; - } - -void Spell::Render(){ - string action = source->getName(); - string alt1 = ""; - - JQuad * quad = NULL; - string alt2 = ""; - Damageable * target = getNextDamageableTarget(); - if (target){ - quad = target->getIcon(); - if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) { - alt2 = ((MTGCardInstance *)target)->name; - } - } - Interruptible::Render(source,quad,alt1,alt2,action, true); -} - -ostream& Spell::toString(ostream& out) const -{ - out << "Spell ::: cost : " << cost; - return out; -} - - -/* Put a card in graveyard */ - -PutInGraveyard::PutInGraveyard(int id, MTGCardInstance * _card):Interruptible(id){ - card = _card; - removeFromGame = 0; - type = ACTION_PUTINGRAVEYARD; -} - -int PutInGraveyard::resolve(){ - GameObserver * g = GameObserver::GetInstance(); - MTGGameZone * zone = card->getCurrentZone(); - if (zone == g->players[0]->game->inPlay || zone == g->players[1]->game->inPlay){ - card->owner->game->putInZone(card,zone,card->owner->game->graveyard); - return 1; - } - return 0; -} - -void PutInGraveyard::Render(){ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - if (!removeFromGame){ - mFont->DrawString(_("goes to graveyard").c_str(), x + 30 , y, JGETEXT_LEFT); - }else{ - mFont->DrawString(_("is exiled").c_str(), x + 30 , y, JGETEXT_LEFT); - } - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * quad = resources.RetrieveCard(card,CACHE_THUMB); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - float scale = 30 / quad->mHeight; - renderer->RenderQuad(quad, x , y , 0,scale,scale); - }else{ - mFont->DrawString(_(card->name).c_str(),x,y-15); - } -} - -ostream& PutInGraveyard::toString(ostream& out) const -{ - out << "PutInGraveyard ::: removeFromGame : " << removeFromGame; - return out; -} - -/* Draw a Card */ -DrawAction::DrawAction(int id, Player * _player, int _nbcards):Interruptible(id), nbcards(_nbcards), player(_player){ -} - -int DrawAction::resolve(){ - for (int i = 0 ; i < nbcards ; i++){ - player->game->drawFromLibrary(); - } - return 1; -} - -void DrawAction::Render(){ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - char buffer[200]; - int playerId = 1; - if (player == GameObserver::GetInstance()->players[1]) playerId = 2; - sprintf(buffer, _("Player %i draws %i card").c_str(), playerId, nbcards); - mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT); -} - -ostream& DrawAction::toString(ostream& out) const -{ - out << "DrawAction ::: nbcards : " << nbcards << " ; player : " << player; - return out; -} - -/* The Action Stack itself */ -int ActionStack::addPutInGraveyard(MTGCardInstance * card){ - PutInGraveyard * death = NEW PutInGraveyard(mCount,card); - addAction(death); - return 1; -} - -int ActionStack::addAbility(MTGAbility * ability){ - StackAbility * stackAbility = NEW StackAbility(mCount,ability); - int result = addAction(stackAbility); - if (!game->players[0]->isAI() && - ability->source->controller()==game->players[0] && - 0 == options[Options::INTERRUPTMYABILITIES].number) - interruptDecision[0] = DONT_INTERRUPT; - return result; -} - -int ActionStack::addDraw(Player * player, int nb_cards){ - DrawAction * draw = NEW DrawAction(mCount,player, nb_cards); - addAction(draw); - GameObserver *g = GameObserver::GetInstance(); - WEvent * e = NEW WEventcardDraw(player,nb_cards); - g->receiveEvent(e); - return 1; -} - -int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage){ - Damage * damage = NEW Damage(_source, _target, _damage); - addAction(damage); - return 1; -} - -int ActionStack::AddNextGamePhase(){ - if (getNext(NULL,NOT_RESOLVED)) return 0; - NextGamePhase * next = NEW NextGamePhase(mCount); - addAction(next); - int playerId = 0; - game->currentActionPlayer = game->GetInstance()->currentActionPlayer; - if (game->currentActionPlayer == game->players[1]){ playerId = 1;} - interruptDecision[playerId] = 1; - return 1; -} - -int ActionStack::AddNextCombatStep(){ - if (getNext(NULL,NOT_RESOLVED)) return 0; - NextGamePhase * next = NEW NextGamePhase(mCount); - addAction(next); - return 1; -} - -int ActionStack::setIsInterrupting(Player * player){ - if (player == game->players[0]){ - interruptDecision[0] = -1; - }else{ - interruptDecision[1] = -1; - } - game->isInterrupting = player; - askIfWishesToInterrupt = NULL; - return 1; -} - - -int ActionStack::addAction(Interruptible * action){ - for (int i=0; i<2; i++){ - interruptDecision[i] = 0; - } - Add(action); - DebugTrace("Action added to stack: " << action->getDisplayName()); - - return 1; -} - -Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana, int payResult,int storm){ - DebugTrace("ACTIONSTACK Add spell"); - if(storm > 0){ mana = NULL;} - if(mana < 0) {mana = 0;} - Spell * spell = NEW Spell(mCount,_source,tc, mana,payResult); - addAction(spell); - if (!game->players[0]->isAI() && - _source->controller()==game->players[0] && - 0 == options[Options::INTERRUPTMYSPELLS].number) - interruptDecision[0] = DONT_INTERRUPT; - return spell; -} - - -Interruptible * ActionStack::getAt(int id){ - if (id < 0) id = mCount + id; - if (id > mCount -1) return NULL; - return (Interruptible *)mObjects[id]; -} - -ActionStack::ActionStack(GameObserver* game) : game(game){ - for (int i=0; i<2; i++) - interruptDecision[i] = 0; - askIfWishesToInterrupt = NULL; - timer = -1; - currentState = -1; - mode = ACTIONSTACK_STANDARD; - checked = 0; - -} - -int ActionStack::has(MTGAbility * ability){ - for (int i = 0; i < mCount ; i++){ - if (((Interruptible *)mObjects[i])->type==ACTION_ABILITY){ - StackAbility * action = ((StackAbility *)mObjects[i]); - if (action->state == NOT_RESOLVED && action->ability == ability) return 1; - } - } - return 0; -} - -int ActionStack::has(Interruptible * action){ - for (int i = 0; i < mCount ; i++){ - if (mObjects[i] == action) return 1; - } - return 0; -} - -int ActionStack::resolve(){ - Interruptible * action = getLatest(NOT_RESOLVED); - - if (!action) - return 0; - - DebugTrace("Resolving Action on stack: " << action->getDisplayName()); - if (action->resolve()){ - action->state = RESOLVED_OK; - }else{ - action->state = RESOLVED_NOK; - } - if (action->type == ACTION_DAMAGE) ((Damage * )action)->target->afterDamage(); - - if (!getNext(NULL,NOT_RESOLVED)){ - for (int i = 0; i< 2 ; i++){ - interruptDecision[i] = 0; - } - }else{ - for (int i = 0; i< 2 ; i++){ - if (interruptDecision[i] != 2) interruptDecision[i] = 0; - } - } - - return 1; - -} - -Interruptible * ActionStack::getPrevious(Interruptible * next, int type, int state, int display){ - int n = getPreviousIndex( next, type, state, display); - if (n==-1) return NULL; - return ((Interruptible *) mObjects[n]); -} - -int ActionStack::getPreviousIndex(Interruptible * next, int type, int state, int display){ - int found = 0; - if (!next) found = 1; - for (int i = mCount -1; i >= 0 ; i--){ - Interruptible * current = (Interruptible *)mObjects[i]; - if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ - return i; - } - if (current == next) found = 1; - } - if (!found) return getPreviousIndex(NULL,type, state, display); - return -1; -} - -int ActionStack::count( int type, int state, int display){ - int result = 0; - for (int i = 0; i < mCount ; i++){ - Interruptible * current = (Interruptible *)mObjects[i]; - if((type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ - result++; - } - } - return result; -} - -Interruptible * ActionStack::getNext(Interruptible * previous, int type, int state, int display){ - int n = getNextIndex( previous, type, state, display); - if (n==-1) return NULL; - return ((Interruptible *) mObjects[n]); -} - -int ActionStack::getNextIndex(Interruptible * previous, int type, int state, int display){ - int found = 0; - if (!previous) found = 1; - for (int i = 0; i < mCount ; i++){ - Interruptible * current = (Interruptible *)mObjects[i]; - if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){ - return i; - } - if (current == previous) found = 1; - } - if (!found) return getNextIndex(NULL,type, state, display); - return -1; -} - - -Interruptible * ActionStack::getLatest(int state){ - for (int i = mCount-1; i >=0; i--){ - Interruptible * action = ((Interruptible *)mObjects[i]); - if (action->state == state) return action; - } - return NULL; -} - -int ActionStack::receiveEventPlus(WEvent * event) { - int result = 0; - for (int i = 0; i < mCount ; ++i){ - Interruptible * current = (Interruptible *)mObjects[i]; - result += current->receiveEvent(event); - } - return result; -} - -void ActionStack::Update(float dt){ - askIfWishesToInterrupt = NULL; - //modal = 0; - GameObserver * game = GameObserver::GetInstance(); - TargetChooser * tc = game->getCurrentTargetChooser(); - int newState = game->getCurrentGamePhase(); - currentState = newState; - if (!tc) checked = 0; - - //Select Stack's display mode - if (mode==ACTIONSTACK_STANDARD && tc && !checked){ - checked = 1; - for (int i = 0; i < mCount ; i++){ - Interruptible * current = (Interruptible *)mObjects[i]; - if (tc->canTarget(current)){ - if (mCurr < (int)mObjects.size() && mObjects[mCurr]) mObjects[mCurr]->Leaving(JGE_BTN_UP); - current->display = 1; - mCurr = i; - mObjects[mCurr]->Entering(); - mode=ACTIONSTACK_TARGET; - modal = 1; - }else{ - current->display = 0; - } - } - if (mode != ACTIONSTACK_TARGET){ - } - }else if (mode==ACTIONSTACK_TARGET && !tc){ - mode = ACTIONSTACK_STANDARD; - checked = 0; - } - - if (mode == ACTIONSTACK_STANDARD){ - modal = 0; - if (getLatest(NOT_RESOLVED)){ - int currentPlayerId = 0; - int otherPlayerId = 1; - if (game->currentlyActing() != game->players[0]){ - currentPlayerId = 1; - otherPlayerId = 0; - } - if (interruptDecision[currentPlayerId] == NOT_DECIDED){ - askIfWishesToInterrupt = game->players[currentPlayerId]; - game->isInterrupting = game->players[currentPlayerId]; - modal = 1; - }else if (interruptDecision[currentPlayerId] == INTERRUPT){ - game->isInterrupting = game->players[currentPlayerId]; - - }else{ - if (interruptDecision[otherPlayerId] == NOT_DECIDED){ - askIfWishesToInterrupt = game->players[otherPlayerId]; - game->isInterrupting = game->players[otherPlayerId]; - modal = 1; - }else if (interruptDecision[otherPlayerId] == INTERRUPT){ - game->isInterrupting = game->players[otherPlayerId]; - }else{ - resolve(); - } - } - } - }else if (mode == ACTIONSTACK_TARGET){ - GuiLayer::Update(dt); - } - if (askIfWishesToInterrupt){ - // WALDORF - added code to use a game option setting to determine how - // long the Interrupt timer should be. If it is set to zero (0), the - // game will wait for ever for the user to make a selection. - if (options[Options::INTERRUPT_SECONDS].number > 0) - { - if (timer < 0) timer = options[Options::INTERRUPT_SECONDS].number; - timer -= dt; - if (timer < 0) cancelInterruptOffer(); - } - } -} - -void ActionStack::cancelInterruptOffer(int cancelMode){ - if (game->isInterrupting == game->players[0]){ - interruptDecision[0] = cancelMode; - }else{ - interruptDecision[1] = cancelMode; - } - askIfWishesToInterrupt = NULL; - game->isInterrupting = NULL; - timer = -1; -} - -void ActionStack::endOfInterruption(){ - if (game->isInterrupting == game->players[0]){ - interruptDecision[0] = 0; - }else{ - interruptDecision[1] = 0; - } - game->isInterrupting = NULL; -} - - -bool ActionStack::CheckUserInput(JButton key){ - JButton trigger = (options[Options::REVERSETRIGGERS].number ? JGE_BTN_NEXT : JGE_BTN_PREV); - if (mode == ACTIONSTACK_STANDARD){ - if (askIfWishesToInterrupt){ - if (JGE_BTN_SEC == key){ - setIsInterrupting(askIfWishesToInterrupt); - return true; - }else if ((JGE_BTN_OK == key) || (trigger == key) ){ - cancelInterruptOffer(); - return true; - }else if ((JGE_BTN_PRI == key)){ - cancelInterruptOffer(2); - return true; - } - return true; - }else if (game->isInterrupting){ - if (JGE_BTN_SEC == key){ - endOfInterruption(); - return true; - } - } - }else if (mode == ACTIONSTACK_TARGET){ - if (modal){ - if (JGE_BTN_UP == key){ - if( mObjects[mCurr]){ - int n = getPreviousIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); - if (n != -1 && n != mCurr && mObjects[mCurr]->Leaving(JGE_BTN_UP)){ - mCurr = n; - mObjects[mCurr]->Entering(); - DebugTrace("ACTIONSTACK UP TO mCurr = " << mCurr); - } - } - return true; - }else if (JGE_BTN_DOWN == key){ - if( mObjects[mCurr]){ - int n = getNextIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); - if (n!= -1 && n != mCurr && mObjects[mCurr]->Leaving(JGE_BTN_DOWN)){ - mCurr = n; - mObjects[mCurr]->Entering(); - DebugTrace("ACTIONSTACK DOWN TO mCurr " << mCurr); - } - } - return true; - }else if (JGE_BTN_OK == key){ - DebugTrace("ACTIONSTACK CLICKED mCurr = " << mCurr); - - game->stackObjectClicked(((Interruptible *) mObjects[mCurr])); - return true; - } - return true; //Steal the input to other layers if we're visible - } - if (JGE_BTN_CANCEL == key){ - if (modal) modal = 0; else modal = 1; - return true; - } - } - return false; -} - - - -//Cleans history of last turn -int ActionStack::garbageCollect(){ -std::vector::iterator iter = mObjects.begin() ; - -while( iter != mObjects.end() ){ - Interruptible * current = ((Interruptible *) *iter); - if (current->state != NOT_RESOLVED){ - iter = mObjects.erase( iter ) ; - mCount--; - SAFE_DELETE(current); - } else - ++iter; -} - return 1; -} - -void ActionStack::Fizzle(Interruptible * action){ - if (!action){ - DebugTrace("ACTIONSTACK ==ERROR==: action is NULL in ActionStack::Fizzle"); - return; - } - if (action->type == ACTION_SPELL){ - Spell * spell = (Spell *) action; - spell->source->controller()->game->putInGraveyard(spell->source); - } - action->state = RESOLVED_NOK; -} - -void ActionStack::Render(){ - float x0 = 250; - float y0 = 30; - float width = 200; - float height = 90; - float currenty = y0 + 5 ; - - if (mode == ACTIONSTACK_STANDARD){ - if (!askIfWishesToInterrupt || !askIfWishesToInterrupt->displayStack()) return; - - - for (int i=0;istate==NOT_RESOLVED) height += current->mHeight; - } + GameObserver * g = GameObserver::GetInstance(); + int nextPhase = (g->getCurrentGamePhase() + 1) % Constants::MTG_PHASE_CLEANUP; WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); mFont->SetBase(0); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->SetColor(ARGB(255,255,255,255)); - JRenderer * renderer = JRenderer::GetInstance(); - - //JQuad * back = resources.GetQuad("interrupt"); - //float xScale = width / back->mWidth; - //float yScale = height / back->mHeight; - renderer->FillRoundRect(x0 + 16 ,y0 + 16 ,width +2 ,height +2 , 10, ARGB(128,0,0,0)); - renderer->FillRoundRect(x0 - 5 ,y0 - 5 ,width + 2,height +2 , 10, ARGB(200,0,0,0)); - //renderer->RenderQuad(back,x0,y0,0,xScale, yScale); - renderer->DrawRoundRect(x0 - 5 ,y0 - 5 ,width + 2,height +2 , 10, ARGB(255,255,255,255)); - - - for (int i=0;istate==NOT_RESOLVED){ - current->x = x0 + 5; - if (i != mCount -1){ - current->y = currenty; - currenty += current->mHeight; - }else{ - current->y = currenty + 40 ; - currenty += current->mHeight + 40; - } - current->Render(); - } - } - char buffer[200]; - // WALDORF - changed "interrupt ?" to "Interrupt?". Don't display count down - // seconds if the user disables auto progressing interrupts by setting the seconds - // value to zero in Options. - if (options[Options::INTERRUPT_SECONDS].number == 0) - sprintf(buffer, "%s", _("Interrupt?").c_str()); - else - sprintf(buffer, "%s %i", _("Interrupt?").c_str(),static_cast(timer)); + int playerId = 1; + if (g->currentActionPlayer == GameObserver::GetInstance()->players[1]) + playerId = 2; - //WALDORF - removed all the unnecessary math. just display the prompt at the - // top of the box. - mFont->DrawString(buffer, x0 + 5, y0); + sprintf(buffer, "%s %i : -> %s", _("Player").c_str(), playerId, _(PhaseRing::phaseName(nextPhase)).c_str()); + mFont->DrawString(buffer, x + 30, y, JGETEXT_LEFT); +} - if (mCount > 1) sprintf(buffer, "%s", _("X Interrupt - 0 No - [] No to All").c_str()); - else sprintf(buffer, "%s", _("X Interrupt - 0 No").c_str()); +NextGamePhase::NextGamePhase(int id) : + Interruptible(id) +{ + mHeight = 40; + type = ACTION_NEXTGAMEPHASE; +} - // WALDORF - puts the button legend right under the prompt. the stack - // will be displayed below it now. no more need to do wierd currY math. - mFont->DrawString(buffer, x0 + 5, y0 + 14); - }else if (mode == ACTIONSTACK_TARGET && modal){ - for (int i=0;idisplay) height += current->mHeight; +ostream& NextGamePhase::toString(ostream& out) const +{ + out << "NextGamePhase ::: "; + return out; +} + +const string Interruptible::getDisplayName() const +{ + return typeid(*this).name(); + } + + void Interruptible::Render(MTGCardInstance * source, JQuad * targetQuad, string alt1, string alt2, string action, + bool bigQuad) + { + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->DrawString(_(action).c_str(), x + 30, y, JGETEXT_LEFT); + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * quad = resources.RetrieveCard(source, CACHE_THUMB); + if (!quad) + quad = CardGui::AlternateThumbQuad(source); + if (quad) + { + quad->SetColor(ARGB(255,255,255,255)); + float scale = mHeight / quad->mHeight; + renderer->RenderQuad(quad, x + 10 * scale, y + 15 * scale, 0, scale, scale); + } + else if (alt1.size()) + { + mFont->DrawString(_(alt1).c_str(), x, y - 15); + } + + if (bigQuad) + { + Pos pos = Pos(CardGui::BigWidth / 2, CardGui::BigHeight / 2 - 10, 1.0, 0.0, 220); + CardGui::DrawCard(source, pos, CardSelectorSingleton::Instance()->GetDrawMode()); + } + + if (targetQuad) + { + float backupX = targetQuad->mHotSpotX; + float backupY = targetQuad->mHotSpotY; + targetQuad->SetColor(ARGB(255,255,255,255)); + targetQuad->SetHotSpot(targetQuad->mWidth / 2, targetQuad->mHeight / 2); + float scale = mHeight / targetQuad->mHeight; + renderer->RenderQuad(targetQuad, x + 150, y + 15 * scale, 0, scale, scale); + targetQuad->SetHotSpot(backupX, backupY); + } + else if (alt2.size()) + { + mFont->DrawString(_(alt2).c_str(), x + 120, y); + } + } + + /* Ability */ + int StackAbility::resolve() + { + return (ability->resolve()); + } + void StackAbility::Render() + { + string action = ability->getMenuText(); + MTGCardInstance * source = ability->source; + string alt1 = source->getName(); + + Targetable * _target = ability->target; + if (ability->tc) + { + Targetable * t = ability->tc->getNextTarget(); + if (t) + _target = t; + } + Damageable * target = NULL; + if (_target != ability->source && (_target->typeAsTarget() == TARGET_CARD || _target->typeAsTarget() + == TARGET_PLAYER)) + { + target = (Damageable *) _target; + } + + JQuad * quad = NULL; + string alt2 = ""; + if (target) + { + quad = target->getIcon(); + if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) + { + alt2 = ((MTGCardInstance *) target)->name; + } + } + + Interruptible::Render(source, quad, alt1, alt2, action); + } + StackAbility::StackAbility(int id, MTGAbility * _ability) : + Interruptible(id), ability(_ability) + { + type = ACTION_ABILITY; + } + + ostream& StackAbility::toString(ostream& out) const + { + out << "StackAbility ::: ability : " << ability; + return out; + } + + const string StackAbility::getDisplayName() const + { + std::ostringstream stream; + stream << "StackAbility. (Source: " << ability->source->getDisplayName() << ")"; + + return stream.str(); + } + + /* Spell Cast */ + + Spell::Spell(MTGCardInstance * _source) : + Interruptible(0) + { + source = _source; + mHeight = 40; + type = ACTION_SPELL; + cost = NEW ManaCost(); + tc = NULL; + from = _source->getCurrentZone(); + } + + Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost, int payResult) : + Interruptible(id), tc(tc), cost(_cost), payResult(payResult) + { + source = _source; + mHeight = 40; + type = ACTION_SPELL; + from = _source->getCurrentZone(); + } + + int Spell::computeX(MTGCardInstance * card) + { + ManaCost * c = cost->Diff(card->getManaCost()); + int x = c->getCost(Constants::MTG_NB_COLORS); + delete c; + return x; + } + + int Spell::computeXX(MTGCardInstance * card) + { + ManaCost * c = cost->Diff(card->getManaCost()); + int xx = c->getCost(Constants::MTG_NB_COLORS) / 2; + delete c; + return xx; + } + + bool Spell::FullfilledAlternateCost(const int &costType) + { + bool hasFullfilledAlternateCost = false; + + switch (costType) + { + case ManaCost::MANA_PAID_WITH_KICKER: + hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_KICKER); + break; + case ManaCost::MANA_PAID_WITH_ALTERNATIVE: + hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_ALTERNATIVE); + break; + case ManaCost::MANA_PAID_WITH_BUYBACK: + hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_BUYBACK); + break; + case ManaCost::MANA_PAID_WITH_FLASHBACK: + hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_FLASHBACK); + break; + case ManaCost::MANA_PAID_WITH_RETRACE: + hasFullfilledAlternateCost = (payResult == ManaCost::MANA_PAID_WITH_RETRACE); + break; + } + + return hasFullfilledAlternateCost; + } + + const string Spell::getDisplayName() const + { + return source->getName(); + } + Spell::~Spell() + { + SAFE_DELETE(cost); + SAFE_DELETE(tc); + } + + int Spell::resolve() + { + GameObserver * game = GameObserver::GetInstance(); + if (!source->hasType("instant") && !source->hasType("sorcery")) + { + Player * p = source->controller(); + source = p->game->putInZone(source, from, p->game->battlefield); + from = p->game->battlefield; + } + + //Play SFX + if (options[Options::SFXVOLUME].number > 0) + { + JSample * sample = source->getSample(); + if (sample) + { + JSoundSystem::GetInstance()->PlaySample(sample); + } + } + + AbilityFactory af; + af.addAbilities(game->mLayers->actionLayer()->getMaxId(), this); + return 1; + } + + MTGCardInstance * Spell::getNextCardTarget(MTGCardInstance * previous) + { + if (!tc) + return NULL; + return tc->getNextCardTarget(previous); + } + Player * Spell::getNextPlayerTarget(Player * previous) + { + if (!tc) + return NULL; + return tc->getNextPlayerTarget(previous); + } + Damageable * Spell::getNextDamageableTarget(Damageable * previous) + { + if (!tc) + return NULL; + return tc->getNextDamageableTarget(previous); + } + Interruptible * Spell::getNextInterruptible(Interruptible * previous, int type) + { + if (!tc) + return NULL; + return tc->getNextInterruptible(previous, type); + } + Spell * Spell::getNextSpellTarget(Spell * previous) + { + if (!tc) + return NULL; + return tc->getNextSpellTarget(previous); + } + Damage * Spell::getNextDamageTarget(Damage * previous) + { + if (!tc) + return NULL; + return tc->getNextDamageTarget(previous); + } + Targetable * Spell::getNextTarget(Targetable * previous, int type) + { + if (!tc) + return NULL; + return tc->getNextTarget(previous, type); + } + + int Spell::getNbTargets() + { + if (!tc) + return 0; + return tc->cursor; + } + + void Spell::Render() + { + string action = source->getName(); + string alt1 = ""; + + JQuad * quad = NULL; + string alt2 = ""; + Damageable * target = getNextDamageableTarget(); + if (target) + { + quad = target->getIcon(); + if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) + { + alt2 = ((MTGCardInstance *) target)->name; + } + } + Interruptible::Render(source, quad, alt1, alt2, action, true); + } + + ostream& Spell::toString(ostream& out) const + { + out << "Spell ::: cost : " << cost; + return out; + } + + /* Put a card in graveyard */ + + PutInGraveyard::PutInGraveyard(int id, MTGCardInstance * _card) : + Interruptible(id) + { + card = _card; + removeFromGame = 0; + type = ACTION_PUTINGRAVEYARD; + } + + int PutInGraveyard::resolve() + { + GameObserver * g = GameObserver::GetInstance(); + MTGGameZone * zone = card->getCurrentZone(); + if (zone == g->players[0]->game->inPlay || zone == g->players[1]->game->inPlay) + { + card->owner->game->putInZone(card, zone, card->owner->game->graveyard); + return 1; + } + return 0; + } + + void PutInGraveyard::Render() + { + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + if (!removeFromGame) + { + mFont->DrawString(_("goes to graveyard").c_str(), x + 30, y, JGETEXT_LEFT); + } + else + { + mFont->DrawString(_("is exiled").c_str(), x + 30, y, JGETEXT_LEFT); + } + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * quad = resources.RetrieveCard(card, CACHE_THUMB); + if (quad) + { + quad->SetColor(ARGB(255,255,255,255)); + float scale = 30 / quad->mHeight; + renderer->RenderQuad(quad, x, y, 0, scale, scale); + } + else + { + mFont->DrawString(_(card->name).c_str(), x, y - 15); + } + } + + ostream& PutInGraveyard::toString(ostream& out) const + { + out << "PutInGraveyard ::: removeFromGame : " << removeFromGame; + return out; + } + + /* Draw a Card */ + DrawAction::DrawAction(int id, Player * _player, int _nbcards) : + Interruptible(id), nbcards(_nbcards), player(_player) + { + } + + int DrawAction::resolve() + { + for (int i = 0; i < nbcards; i++) + { + player->game->drawFromLibrary(); + } + return 1; + } + + void DrawAction::Render() + { + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + char buffer[200]; + int playerId = 1; + if (player == GameObserver::GetInstance()->players[1]) + playerId = 2; + sprintf(buffer, _("Player %i draws %i card").c_str(), playerId, nbcards); + mFont->DrawString(buffer, x + 20, y, JGETEXT_LEFT); + } + + ostream& DrawAction::toString(ostream& out) const + { + out << "DrawAction ::: nbcards : " << nbcards << " ; player : " << player; + return out; + } + + /* The Action Stack itself */ + int ActionStack::addPutInGraveyard(MTGCardInstance * card) + { + PutInGraveyard * death = NEW PutInGraveyard(mCount, card); + addAction(death); + return 1; + } + + int ActionStack::addAbility(MTGAbility * ability) + { + StackAbility * stackAbility = NEW StackAbility(mCount, ability); + int result = addAction(stackAbility); + if (!game->players[0]->isAI() && ability->source->controller() == game->players[0] && 0 + == options[Options::INTERRUPTMYABILITIES].number) + interruptDecision[0] = DONT_INTERRUPT; + return result; + } + + int ActionStack::addDraw(Player * player, int nb_cards) + { + DrawAction * draw = NEW DrawAction(mCount, player, nb_cards); + addAction(draw); + GameObserver *g = GameObserver::GetInstance(); + WEvent * e = NEW WEventcardDraw(player, nb_cards); + g->receiveEvent(e); + return 1; + } + + int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage) + { + Damage * damage = NEW Damage(_source, _target, _damage); + addAction(damage); + return 1; + } + + int ActionStack::AddNextGamePhase() + { + if (getNext(NULL, NOT_RESOLVED)) + return 0; + NextGamePhase * next = NEW NextGamePhase(mCount); + addAction(next); + int playerId = 0; + game->currentActionPlayer = game->GetInstance()->currentActionPlayer; + if (game->currentActionPlayer == game->players[1]) + { + playerId = 1; + } + interruptDecision[playerId] = 1; + return 1; + } + + int ActionStack::AddNextCombatStep() + { + if (getNext(NULL, NOT_RESOLVED)) + return 0; + NextGamePhase * next = NEW NextGamePhase(mCount); + addAction(next); + return 1; + } + + int ActionStack::setIsInterrupting(Player * player) + { + if (player == game->players[0]) + { + interruptDecision[0] = -1; + } + else + { + interruptDecision[1] = -1; + } + game->isInterrupting = player; + askIfWishesToInterrupt = NULL; + return 1; + } + + int ActionStack::addAction(Interruptible * action) + { + for (int i = 0; i < 2; i++) + { + interruptDecision[i] = 0; + } + Add(action); + DebugTrace("Action added to stack: " << action->getDisplayName()); + + return 1; + } + + Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana, int payResult, + int storm) + { + DebugTrace("ACTIONSTACK Add spell"); + if (storm > 0) + { + mana = NULL; + } + if (mana < 0) + { + mana = 0; + } + Spell * spell = NEW Spell(mCount, _source, tc, mana, payResult); + addAction(spell); + if (!game->players[0]->isAI() && _source->controller() == game->players[0] && 0 + == options[Options::INTERRUPTMYSPELLS].number) + interruptDecision[0] = DONT_INTERRUPT; + return spell; + } + + Interruptible * ActionStack::getAt(int id) + { + if (id < 0) + id = mCount + id; + if (id > mCount - 1) + return NULL; + return (Interruptible *) mObjects[id]; + } + + ActionStack::ActionStack(GameObserver* game) : + game(game) + { + for (int i = 0; i < 2; i++) + interruptDecision[i] = 0; + askIfWishesToInterrupt = NULL; + timer = -1; + currentState = -1; + mode = ACTIONSTACK_STANDARD; + checked = 0; + + } + + int ActionStack::has(MTGAbility * ability) + { + for (int i = 0; i < mCount; i++) + { + if (((Interruptible *) mObjects[i])->type == ACTION_ABILITY) + { + StackAbility * action = ((StackAbility *) mObjects[i]); + if (action->state == NOT_RESOLVED && action->ability == ability) + return 1; + } + } + return 0; + } + + int ActionStack::has(Interruptible * action) + { + for (int i = 0; i < mCount; i++) + { + if (mObjects[i] == action) + return 1; + } + return 0; + } + + int ActionStack::resolve() + { + Interruptible * action = getLatest(NOT_RESOLVED); + + if (!action) + return 0; + + DebugTrace("Resolving Action on stack: " << action->getDisplayName()); + if (action->resolve()) + { + action->state = RESOLVED_OK; + } + else + { + action->state = RESOLVED_NOK; + } + if (action->type == ACTION_DAMAGE) + ((Damage *) action)->target->afterDamage(); + + if (!getNext(NULL, NOT_RESOLVED)) + { + for (int i = 0; i < 2; i++) + { + interruptDecision[i] = 0; + } + } + else + { + for (int i = 0; i < 2; i++) + { + if (interruptDecision[i] != 2) + interruptDecision[i] = 0; + } + } + + return 1; + + } + + Interruptible * ActionStack::getPrevious(Interruptible * next, int type, int state, int display) + { + int n = getPreviousIndex(next, type, state, display); + if (n == -1) + return NULL; + return ((Interruptible *) mObjects[n]); + } + + int ActionStack::getPreviousIndex(Interruptible * next, int type, int state, int display) + { + int found = 0; + if (!next) + found = 1; + for (int i = mCount - 1; i >= 0; i--) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display + == -1 || current->display == display)) + { + return i; + } + if (current == next) + found = 1; + } + if (!found) + return getPreviousIndex(NULL, type, state, display); + return -1; + } + + int ActionStack::count(int type, int state, int display) + { + int result = 0; + for (int i = 0; i < mCount; i++) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if ((type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 + || current->display == display)) + { + result++; + } + } + return result; + } + + Interruptible * ActionStack::getNext(Interruptible * previous, int type, int state, int display) + { + int n = getNextIndex(previous, type, state, display); + if (n == -1) + return NULL; + return ((Interruptible *) mObjects[n]); + } + + int ActionStack::getNextIndex(Interruptible * previous, int type, int state, int display) + { + int found = 0; + if (!previous) + found = 1; + for (int i = 0; i < mCount; i++) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display + == -1 || current->display == display)) + { + return i; + } + if (current == previous) + found = 1; + } + if (!found) + return getNextIndex(NULL, type, state, display); + return -1; + } + + Interruptible * ActionStack::getLatest(int state) + { + for (int i = mCount - 1; i >= 0; i--) + { + Interruptible * action = ((Interruptible *) mObjects[i]); + if (action->state == state) + return action; + } + return NULL; + } + + int ActionStack::receiveEventPlus(WEvent * event) + { + int result = 0; + for (int i = 0; i < mCount; ++i) + { + Interruptible * current = (Interruptible *) mObjects[i]; + result += current->receiveEvent(event); + } + return result; + } + + void ActionStack::Update(float dt) + { + askIfWishesToInterrupt = NULL; + //modal = 0; + GameObserver * game = GameObserver::GetInstance(); + TargetChooser * tc = game->getCurrentTargetChooser(); + int newState = game->getCurrentGamePhase(); + currentState = newState; + if (!tc) + checked = 0; + + //Select Stack's display mode + if (mode == ACTIONSTACK_STANDARD && tc && !checked) + { + checked = 1; + for (int i = 0; i < mCount; i++) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if (tc->canTarget(current)) + { + if (mCurr < (int) mObjects.size() && mObjects[mCurr]) + mObjects[mCurr]->Leaving(JGE_BTN_UP); + current->display = 1; + mCurr = i; + mObjects[mCurr]->Entering(); + mode = ACTIONSTACK_TARGET; + modal = 1; + } + else + { + current->display = 0; + } + } + if (mode != ACTIONSTACK_TARGET) + { + } + } + else if (mode == ACTIONSTACK_TARGET && !tc) + { + mode = ACTIONSTACK_STANDARD; + checked = 0; + } + + if (mode == ACTIONSTACK_STANDARD) + { + modal = 0; + if (getLatest(NOT_RESOLVED)) + { + int currentPlayerId = 0; + int otherPlayerId = 1; + if (game->currentlyActing() != game->players[0]) + { + currentPlayerId = 1; + otherPlayerId = 0; + } + if (interruptDecision[currentPlayerId] == NOT_DECIDED) + { + askIfWishesToInterrupt = game->players[currentPlayerId]; + game->isInterrupting = game->players[currentPlayerId]; + modal = 1; + } + else if (interruptDecision[currentPlayerId] == INTERRUPT) + { + game->isInterrupting = game->players[currentPlayerId]; + + } + else + { + if (interruptDecision[otherPlayerId] == NOT_DECIDED) + { + askIfWishesToInterrupt = game->players[otherPlayerId]; + game->isInterrupting = game->players[otherPlayerId]; + modal = 1; + } + else if (interruptDecision[otherPlayerId] == INTERRUPT) + { + game->isInterrupting = game->players[otherPlayerId]; + } + else + { + resolve(); + } + } + } + } + else if (mode == ACTIONSTACK_TARGET) + { + GuiLayer::Update(dt); + } + if (askIfWishesToInterrupt) + { + // WALDORF - added code to use a game option setting to determine how + // long the Interrupt timer should be. If it is set to zero (0), the + // game will wait for ever for the user to make a selection. + if (options[Options::INTERRUPT_SECONDS].number > 0) + { + if (timer < 0) + timer = options[Options::INTERRUPT_SECONDS].number; + timer -= dt; + if (timer < 0) + cancelInterruptOffer(); + } + } + } + + void ActionStack::cancelInterruptOffer(int cancelMode) + { + if (game->isInterrupting == game->players[0]) + { + interruptDecision[0] = cancelMode; + } + else + { + interruptDecision[1] = cancelMode; + } + askIfWishesToInterrupt = NULL; + game->isInterrupting = NULL; + timer = -1; + } + + void ActionStack::endOfInterruption() + { + if (game->isInterrupting == game->players[0]) + { + interruptDecision[0] = 0; + } + else + { + interruptDecision[1] = 0; + } + game->isInterrupting = NULL; + } + + bool ActionStack::CheckUserInput(JButton key) + { + JButton trigger = (options[Options::REVERSETRIGGERS].number ? JGE_BTN_NEXT : JGE_BTN_PREV); + if (mode == ACTIONSTACK_STANDARD) + { + if (askIfWishesToInterrupt) + { + if (JGE_BTN_SEC == key) + { + setIsInterrupting(askIfWishesToInterrupt); + return true; + } + else if ((JGE_BTN_OK == key) || (trigger == key)) + { + cancelInterruptOffer(); + return true; + } + else if ((JGE_BTN_PRI == key)) + { + cancelInterruptOffer(2); + return true; + } + return true; + } + else if (game->isInterrupting) + { + if (JGE_BTN_SEC == key) + { + endOfInterruption(); + return true; + } + } + } + else if (mode == ACTIONSTACK_TARGET) + { + if (modal) + { + if (JGE_BTN_UP == key) + { + if (mObjects[mCurr]) + { + int n = getPreviousIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); + if (n != -1 && n != mCurr && mObjects[mCurr]->Leaving(JGE_BTN_UP)) + { + mCurr = n; + mObjects[mCurr]->Entering(); +DebugTrace ("ACTIONSTACK UP TO mCurr = " << mCurr); + } + } + return true; + } + else if (JGE_BTN_DOWN == key) + { + if( mObjects[mCurr]) + { + int n = getNextIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1); + if (n!= -1 && n != mCurr && mObjects[mCurr]->Leaving(JGE_BTN_DOWN)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + DebugTrace("ACTIONSTACK DOWN TO mCurr " << mCurr); + } + } + return true; + } + else if (JGE_BTN_OK == key) + { + DebugTrace("ACTIONSTACK CLICKED mCurr = " << mCurr); + + game->stackObjectClicked(((Interruptible *) mObjects[mCurr])); + return true; + } + return true; //Steal the input to other layers if we're visible + } + if (JGE_BTN_CANCEL == key) + { + if (modal) modal = 0; + else modal = 1; + return true; + } + } + return false; + } + + //Cleans history of last turn +int ActionStack::garbageCollect() +{ + std::vector::iterator iter = mObjects.begin(); + + while (iter != mObjects.end()) + { + Interruptible * current = ((Interruptible *) *iter); + if (current->state != NOT_RESOLVED) + { + iter = mObjects.erase(iter); + mCount--; + SAFE_DELETE(current); + } + else + ++iter; } + return 1; +} - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->SetColor(ARGB(255,255,255,255)); - - JRenderer * renderer = JRenderer::GetInstance(); - renderer->FillRect(x0 ,y0 , width ,height , ARGB(200,0,0,0)); - renderer->DrawRect(x0 - 1 ,y0 - 1 ,width + 2 ,height +2 , ARGB(255,255,255,255)); - - - for (int i=0;idisplay){ - ((Interruptible *)mObjects[i])->x = x0 + 5; - if (i != mCount -1){ - ((Interruptible *)mObjects[i])->y = currenty; - currenty += ((Interruptible *)mObjects[i])->mHeight; - }else{ - ((Interruptible *)mObjects[i])->y = currenty + 40 ; - currenty += ((Interruptible *)mObjects[i])->mHeight + 40; - } - mObjects[i]->Render(); - } +void ActionStack::Fizzle(Interruptible * action) +{ + if (!action) + { + DebugTrace("ACTIONSTACK ==ERROR==: action is NULL in ActionStack::Fizzle"); + return; + } + if (action->type == ACTION_SPELL) + { + Spell * spell = (Spell *) action; + spell->source->controller()->game->putInGraveyard(spell->source); + } + action->state = RESOLVED_NOK; +} + +void ActionStack::Render() +{ + float x0 = 250; + float y0 = 30; + float width = 200; + float height = 90; + float currenty = y0 + 5; + + if (mode == ACTIONSTACK_STANDARD) + { + if (!askIfWishesToInterrupt || !askIfWishesToInterrupt->displayStack()) + return; + + for (int i = 0; i < mCount; i++) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if (current->state == NOT_RESOLVED) + height += current->mHeight; + } + + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(255,255,255,255)); + JRenderer * renderer = JRenderer::GetInstance(); + + //JQuad * back = resources.GetQuad("interrupt"); + //float xScale = width / back->mWidth; + //float yScale = height / back->mHeight; + renderer->FillRoundRect(x0 + 16, y0 + 16, width + 2, height + 2, 10, ARGB(128,0,0,0)); + renderer->FillRoundRect(x0 - 5, y0 - 5, width + 2, height + 2, 10, ARGB(200,0,0,0)); + //renderer->RenderQuad(back,x0,y0,0,xScale, yScale); + renderer->DrawRoundRect(x0 - 5, y0 - 5, width + 2, height + 2, 10, ARGB(255,255,255,255)); + + for (int i = 0; i < mCount; i++) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if (current && current->state == NOT_RESOLVED) + { + current->x = x0 + 5; + if (i != mCount - 1) + { + current->y = currenty; + currenty += current->mHeight; + } + else + { + current->y = currenty + 40; + currenty += current->mHeight + 40; + } + current->Render(); + } + } + + char buffer[200]; + // WALDORF - changed "interrupt ?" to "Interrupt?". Don't display count down + // seconds if the user disables auto progressing interrupts by setting the seconds + // value to zero in Options. + if (options[Options::INTERRUPT_SECONDS].number == 0) + sprintf(buffer, "%s", _("Interrupt?").c_str()); + else + sprintf(buffer, "%s %i", _("Interrupt?").c_str(), static_cast (timer)); + + //WALDORF - removed all the unnecessary math. just display the prompt at the + // top of the box. + mFont->DrawString(buffer, x0 + 5, y0); + + if (mCount > 1) + sprintf(buffer, "%s", _("X Interrupt - 0 No - [] No to All").c_str()); + else + sprintf(buffer, "%s", _("X Interrupt - 0 No").c_str()); + + // WALDORF - puts the button legend right under the prompt. the stack + // will be displayed below it now. no more need to do wierd currY math. + mFont->DrawString(buffer, x0 + 5, y0 + 14); + } + else if (mode == ACTIONSTACK_TARGET && modal) + { + for (int i = 0; i < mCount; i++) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if (current->display) + height += current->mHeight; + } + + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(255,255,255,255)); + + JRenderer * renderer = JRenderer::GetInstance(); + renderer->FillRect(x0, y0, width, height, ARGB(200,0,0,0)); + renderer->DrawRect(x0 - 1, y0 - 1, width + 2, height + 2, ARGB(255,255,255,255)); + + for (int i = 0; i < mCount; i++) + { + Interruptible * current = (Interruptible *) mObjects[i]; + if (mObjects[i] != NULL && current->display) + { + ((Interruptible *) mObjects[i])->x = x0 + 5; + if (i != mCount - 1) + { + ((Interruptible *) mObjects[i])->y = currenty; + currenty += ((Interruptible *) mObjects[i])->mHeight; + } + else + { + ((Interruptible *) mObjects[i])->y = currenty + 40; + currenty += ((Interruptible *) mObjects[i])->mHeight + 40; + } + mObjects[i]->Render(); + } + } } - } } #if defined (WIN32) || defined (LINUX) -void Interruptible::Dump(){ - string stype, sstate, sdisplay = ""; - switch (type){ - case ACTION_SPELL: - stype = "spell"; - break; - case ACTION_DAMAGE: - stype = "damage"; - break; - case ACTION_DAMAGES: - stype = "damages"; - break; - case ACTION_NEXTGAMEPHASE: - stype = "next phase"; - break; - case ACTION_DRAW: - stype = "draw"; - break; - case ACTION_PUTINGRAVEYARD: - stype = "put in graveyard"; - break; - case ACTION_ABILITY: - stype = "ability"; - break; - default: - stype = "unknown"; - break; - } +void Interruptible::Dump() +{ + string stype, sstate, sdisplay = ""; + switch (type) + { + case ACTION_SPELL: + stype = "spell"; + break; + case ACTION_DAMAGE: + stype = "damage"; + break; + case ACTION_DAMAGES: + stype = "damages"; + break; + case ACTION_NEXTGAMEPHASE: + stype = "next phase"; + break; + case ACTION_DRAW: + stype = "draw"; + break; + case ACTION_PUTINGRAVEYARD: + stype = "put in graveyard"; + break; + case ACTION_ABILITY: + stype = "ability"; + break; + default: + stype = "unknown"; + break; + } - switch(state){ - case NOT_RESOLVED: - sstate = "not resolved"; - break; - case RESOLVED_OK: - sstate = "resolved"; - break; - case RESOLVED_NOK: - sstate = "fizzled"; - break; - default: - sstate = "unknown"; - break; - } - DebugTrace("type: " << stype << " " << type << " - state: " << sstate << " " << state << " - display: " << display); + switch(state) + { + case NOT_RESOLVED: + sstate = "not resolved"; + break; + case RESOLVED_OK: + sstate = "resolved"; + break; + case RESOLVED_NOK: + sstate = "fizzled"; + break; + default: + sstate = "unknown"; + break; + } + DebugTrace("type: " << stype << " " << type << " - state: " << sstate << " " << state << " - display: " << display); } -void ActionStack::Dump(){ - DebugTrace("=====\nDumping Action Stack====="); - for (int i=0;iDump(); - } +void ActionStack::Dump() +{ + DebugTrace("=====\nDumping Action Stack====="); + for (int i=0;iDump(); + } } - #endif diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 588711bcf..0d1a5ccb5 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -3,162 +3,209 @@ // BanishCard implementations -AABanishCard::AABanishCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost=NULL, int _banishmentType = -1):ActivatedAbility(_id, _source,_cost),banishmentType(_banishmentType) { - if (_target) target = _target; +AABanishCard::AABanishCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, int _banishmentType = -1) : + ActivatedAbility(_id, _source, _cost), banishmentType(_banishmentType) +{ + if (_target) + target = _target; } -const char * AABanishCard::getMenuText() +const char * AABanishCard::getMenuText() { - return "Send to graveyard"; + return "Send to graveyard"; } int AABanishCard::resolve() { - DebugTrace("This is not implemented!"); - return 0; + DebugTrace("This is not implemented!"); + return 0; } -AABanishCard * AABanishCard::clone() const{ - AABanishCard * a = NEW AABanishCard(*this); - a->isClone = 1; - return a; +AABanishCard * AABanishCard::clone() const +{ + AABanishCard * a = NEW AABanishCard(*this); + a->isClone = 1; + return a; } // Bury -AABuryCard::AABuryCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL , int _banishmentType = 0):AABanishCard(_id, _source, _target, _cost, AABanishCard::BURY) -{} - -int AABuryCard::resolve(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(_target){ - return _target->bury(); - } - return 0; +AABuryCard::AABuryCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, int _banishmentType = + 0) : + AABanishCard(_id, _source, _target, _cost, AABanishCard::BURY) +{ } -const char * AABuryCard::getMenuText(){ - return "Bury"; +int AABuryCard::resolve() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (_target) + { + return _target->bury(); + } + return 0; } -AABuryCard * AABuryCard::clone() const{ - AABuryCard * a = NEW AABuryCard(*this); - a->isClone = 1; - return a; +const char * AABuryCard::getMenuText() +{ + return "Bury"; } +AABuryCard * AABuryCard::clone() const +{ + AABuryCard * a = NEW AABuryCard(*this); + a->isClone = 1; + return a; +} // Destroy -AADestroyCard::AADestroyCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, int _banishmentType = 0):AABanishCard(_id, _source, _target, _cost, AABanishCard::DESTROY) -{} +AADestroyCard::AADestroyCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, int _banishmentType = 0) : + AABanishCard(_id, _source, _target, _cost, AABanishCard::DESTROY) +{ +} -int AADestroyCard::resolve(){ +int AADestroyCard::resolve() +{ MTGCardInstance * _target = (MTGCardInstance *) target; - if(_target){ - return _target->destroy(); - } - return 0; + if (_target) + { + return _target->destroy(); + } + return 0; } -const char * AADestroyCard::getMenuText(){ - return "Destroy"; +const char * AADestroyCard::getMenuText() +{ + return "Destroy"; } -AADestroyCard * AADestroyCard::clone() const{ - AADestroyCard * a = NEW AADestroyCard(*this); - a->isClone = 1; - return a; +AADestroyCard * AADestroyCard::clone() const +{ + AADestroyCard * a = NEW AADestroyCard(*this); + a->isClone = 1; + return a; } // Sacrifice -AASacrificeCard::AASacrificeCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, int _banishmentType = 0):AABanishCard(_id, _source, _target, _cost, AABanishCard::SACRIFICE) { +AASacrificeCard::AASacrificeCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, int _banishmentType = 0) : + AABanishCard(_id, _source, _target, _cost, AABanishCard::SACRIFICE) +{ } -int AASacrificeCard::resolve(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(_target){ - Player * p = _target->controller(); - WEvent * e = NEW WEventCardSacrifice(_target); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); - p->game->putInGraveyard(_target); - return 1; - } - return 0; +int AASacrificeCard::resolve() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (_target) + { + Player * p = _target->controller(); + WEvent * e = NEW WEventCardSacrifice(_target); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); + p->game->putInGraveyard(_target); + return 1; + } + return 0; } -const char * AASacrificeCard::getMenuText(){ - return "Sacrifice"; +const char * AASacrificeCard::getMenuText() +{ + return "Sacrifice"; } -AASacrificeCard * AASacrificeCard::clone() const{ - AASacrificeCard * a = NEW AASacrificeCard(*this); - a->isClone = 1; - return a; +AASacrificeCard * AASacrificeCard::clone() const +{ + AASacrificeCard * a = NEW AASacrificeCard(*this); + a->isClone = 1; + return a; } // Discard -AADiscardCard::AADiscardCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, int _banishmentType = 0):AABanishCard(_id, _source, _target, _cost, AABanishCard::DISCARD) { +AADiscardCard::AADiscardCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL, + int _banishmentType = 0) : + AABanishCard(_id, _source, _target, _cost, AABanishCard::DISCARD) +{ } -int AADiscardCard::resolve(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(_target){ - Player * p = _target->controller(); - WEvent * e = NEW WEventCardDiscard(_target); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); - p->game->putInGraveyard(_target); - return 1; - } - return 0; +int AADiscardCard::resolve() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (_target) + { + Player * p = _target->controller(); + WEvent * e = NEW WEventCardDiscard(_target); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); + p->game->putInGraveyard(_target); + return 1; + } + return 0; } -const char * AADiscardCard::getMenuText(){ - return "Discard"; +const char * AADiscardCard::getMenuText() +{ + return "Discard"; } -AADiscardCard * AADiscardCard::clone() const{ - AADiscardCard * a = NEW AADiscardCard(*this); - a->isClone = 1; - return a; +AADiscardCard * AADiscardCard::clone() const +{ + AADiscardCard * a = NEW AADiscardCard(*this); + a->isClone = 1; + return a; } - //Mana Redux -AManaRedux::AManaRedux(int id, MTGCardInstance * source, MTGCardInstance * target,int amount,int type):MTGAbility(id,source,target),amount(amount),type(type) { - MTGCardInstance * _target = (MTGCardInstance *)target; +AManaRedux::AManaRedux(int id, MTGCardInstance * source, MTGCardInstance * target, int amount, int type) : + MTGAbility(id, source, target), amount(amount), type(type) +{ + MTGCardInstance * _target = (MTGCardInstance *) target; } -int AManaRedux::addToGame(){ - MTGCardInstance * _target = (MTGCardInstance *)target; - if(amount < 0){ - amount = abs(amount); - if(_target->getManaCost()->hasColor(type)){ - if(_target->getManaCost()->getConvertedCost() >= 1){ - _target->getManaCost()->remove(type,amount); - if(_target->getManaCost()->alternative > 0){ - _target->getManaCost()->alternative->remove(type,amount);} - if(_target->getManaCost()->BuyBack > 0){ - _target->getManaCost()->BuyBack->remove(type,amount);} - } +int AManaRedux::addToGame() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (amount < 0) + { + amount = abs(amount); + if (_target->getManaCost()->hasColor(type)) + { + if (_target->getManaCost()->getConvertedCost() >= 1) + { + _target->getManaCost()->remove(type, amount); + if (_target->getManaCost()->alternative > 0) + { + _target->getManaCost()->alternative->remove(type, amount); + } + if (_target->getManaCost()->BuyBack > 0) + { + _target->getManaCost()->BuyBack->remove(type, amount); + } + } + } } - }else{ - _target->getManaCost()->add(type,amount); - if(_target->getManaCost()->alternative > 0){ - _target->getManaCost()->alternative->add(type,amount);} - if(_target->getManaCost()->BuyBack > 0){ - _target->getManaCost()->BuyBack->add(type,amount);} - } - return MTGAbility::addToGame(); + else + { + _target->getManaCost()->add(type, amount); + if (_target->getManaCost()->alternative > 0) + { + _target->getManaCost()->alternative->add(type, amount); + } + if (_target->getManaCost()->BuyBack > 0) + { + _target->getManaCost()->BuyBack->add(type, amount); + } + } + return MTGAbility::addToGame(); } -AManaRedux * AManaRedux::clone() const { - AManaRedux * a = NEW AManaRedux(*this); - a->isClone = 1; - return a; +AManaRedux * AManaRedux::clone() const +{ + AManaRedux * a = NEW AManaRedux(*this); + a->isClone = 1; + return a; } -AManaRedux::~AManaRedux(){} +AManaRedux::~AManaRedux() +{ +} diff --git a/projects/mtg/src/CardDescriptor.cpp b/projects/mtg/src/CardDescriptor.cpp index c752d22d0..3a459d254 100644 --- a/projects/mtg/src/CardDescriptor.cpp +++ b/projects/mtg/src/CardDescriptor.cpp @@ -4,229 +4,313 @@ #include "Subtypes.h" #include "Counters.h" - -CardDescriptor::CardDescriptor(): MTGCardInstance(){ - init(); - counterName = ""; - counterPower = 0; - counterToughness = 0; - counterNB = 0; - mode = CD_AND; - powerComparisonMode = COMPARISON_NONE; - toughnessComparisonMode = COMPARISON_NONE; - manacostComparisonMode = COMPARISON_NONE; - counterComparisonMode = COMPARISON_NONE; - convertedManacost = -1; +CardDescriptor::CardDescriptor() : MTGCardInstance() +{ + init(); + counterName = ""; + counterPower = 0; + counterToughness = 0; + counterNB = 0; + mode = CD_AND; + powerComparisonMode = COMPARISON_NONE; + toughnessComparisonMode = COMPARISON_NONE; + manacostComparisonMode = COMPARISON_NONE; + counterComparisonMode = COMPARISON_NONE; + convertedManacost = -1; } -int CardDescriptor::init(){ - int result = MTGCardInstance::init(); - attacker = 0; - defenser = NULL; - banding = NULL; - anyCounter = 0; - //Remove unnecessary pointers - SAFE_DELETE(counters); - SAFE_DELETE(previous); - return result; +int CardDescriptor::init() +{ + int result = MTGCardInstance::init(); + attacker = 0; + defenser = NULL; + banding = NULL; + anyCounter = 0; + //Remove unnecessary pointers + SAFE_DELETE(counters); + SAFE_DELETE(previous); + return result; } -void CardDescriptor::unsecureSetTapped(int i){ - tapped = i; +void CardDescriptor::unsecureSetTapped(int i) +{ + tapped = i; } -void CardDescriptor::unsecuresetfresh(int k){ - fresh = k; +void CardDescriptor::unsecuresetfresh(int k) +{ + fresh = k; } -void CardDescriptor::setNegativeSubtype( string value){ - int id = Subtypes::subtypesList->find(value); - addType(-id); -} +void CardDescriptor::setNegativeSubtype(string value) +{ + int id = Subtypes::subtypesList->find(value); + addType(-id); +} // Very generic function to compare a value to a criterion. // Should be easily transferable to a more generic class if desired. -bool CardDescriptor::valueInRange(int comparisonMode, int value, int criterion){ - switch (comparisonMode){ +bool CardDescriptor::valueInRange(int comparisonMode, int value, int criterion) +{ + switch (comparisonMode) + { case COMPARISON_AT_MOST: - return (value <= criterion); + return (value <= criterion); case COMPARISON_AT_LEAST: - return (value >= criterion); + return (value >= criterion); case COMPARISON_EQUAL: - return (value == criterion); + return (value == criterion); case COMPARISON_GREATER: - return (value > criterion); + return (value > criterion); case COMPARISON_LESS: - return (value < criterion); + return (value < criterion); case COMPARISON_UNEQUAL: - return (value != criterion); - } - return false; + return (value != criterion); + } + return false; } -MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card){ - int found = 1; - for (size_t i = 0; i< types.size(); i++){ - found = 0; - if (types[i] >= 0){ +MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card) +{ + int found = 1; + for (size_t i = 0; i < types.size(); i++) + { + found = 0; + if (types[i] >= 0) + { - if (card->hasSubtype(types[i]) || (Subtypes::subtypesList->find(card->getLCName(),false) == types[i])){ - found = 1; - break; - } - }else{ - if (!card->hasSubtype(-types[i]) && (Subtypes::subtypesList->find(card->getLCName(), false) != -types[i])){ - found = 1; - break; - } + if (card->hasSubtype(types[i]) || (Subtypes::subtypesList->find(card->getLCName(), false) == types[i])) + { + found = 1; + break; + } + } + else + { + if (!card->hasSubtype(-types[i]) && (Subtypes::subtypesList->find(card->getLCName(), false) != -types[i])) + { + found = 1; + break; + } + } } - } - if (!found) return NULL; + if (!found) + return NULL; - for (int i = 0; i< Constants::MTG_NB_COLORS; i++){ - if (colors[i] == 1){ - found = 0; - if(card->hasColor(i)){ - found = 1; - break; - } + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + if (colors[i] == 1) + { + found = 0; + if (card->hasColor(i)) + { + found = 1; + break; + } + } + else if (colors[i] == -1) + { + found = 0; + if (!card->hasColor(i)) + { + found = 1; + break; + } + } } - else if (colors[i] == -1){ - found = 0; - if(!card->hasColor(i)){ - found = 1; - break; - } - } - } - if (!found) return NULL; + if (!found) + return NULL; - // Quantified restrictions are always AND-ed: - if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power) ) return NULL; - if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness) ) return NULL; - if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost) ) return NULL; + // Quantified restrictions are always AND-ed: + if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power)) + return NULL; + if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness)) + return NULL; + if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost)) + return NULL; - return card; + return card; } -MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card){ - MTGCardInstance * match = card; - for (size_t i = 0; i< types.size(); i++){ - if (types[i] >= 0){ - if (!card->hasSubtype(types[i]) && !(Subtypes::subtypesList->find(card->getLCName(),false) == types[i])){ +MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card) +{ + MTGCardInstance * match = card; + for (size_t i = 0; i < types.size(); i++) + { + if (types[i] >= 0) + { + if (!card->hasSubtype(types[i]) && !(Subtypes::subtypesList->find(card->getLCName(), false) == types[i])) + { + match = NULL; + } + } + else + { + if (card->hasSubtype(-types[i]) || (Subtypes::subtypesList->find(card->getLCName(), false) == -types[i])) + { + match = NULL; + } + } + } + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + if ((colors[i] == 1 && !card->hasColor(i)) || (colors[i] == -1 && card->hasColor(i))) + { + match = NULL; + } + } + + if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power)) match = NULL; - } - }else{ - if(card->hasSubtype(-types[i]) || (Subtypes::subtypesList->find(card->getLCName(),false) == -types[i])){ + if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness)) + match = NULL; + if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost)) match = NULL; - } - } - } - for (int i = 0; i< Constants::MTG_NB_COLORS; i++){ - if ((colors[i] == 1 && !card->hasColor(i))||(colors[i] == -1 && card->hasColor(i))){ - match = NULL; - } - } - if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power) ) match = NULL; - if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness) ) match = NULL; - if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost) ) match = NULL; - - return match; + return match; } -MTGCardInstance * CardDescriptor::match(MTGCardInstance * card){ +MTGCardInstance * CardDescriptor::match(MTGCardInstance * card) +{ - MTGCardInstance * match = card; - if (mode == CD_AND){ - match = match_and(card); - }else{ - match=match_or(card); - } - - - - - //Abilities - for(map::const_iterator it = basicAbilities.begin(); it != basicAbilities.end(); ++it){ - int j = it->first; - if ((basicAbilities[j] == 1 && !card->basicAbilities[j]) || (basicAbilities[j] == -1 && card->basicAbilities[j])){ - match = NULL; + MTGCardInstance * match = card; + if (mode == CD_AND) + { + match = match_and(card); } - } - - if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped())){ - match = NULL; - } - - if ((fresh == -1 && card->fresh) || (fresh == 1 && !card->fresh)){ - match = NULL; - } - - if ((isToken== -1 && card->isToken) || (isToken == 1 && !card->isToken)){ - match = NULL; - } - if (attacker == 1){ - if (defenser == &AnyCard){ - if (!card->attacker && !card->defenser) match = NULL; - }else{ - if (!card->attacker) match = NULL; + else + { + match = match_or(card); } - }else if (attacker == -1){ - if (defenser == &NoCard){ - if (card->attacker || card->defenser) match = NULL; - }else{ - if (card->attacker) match = NULL; - } - }else{ - if (defenser == &NoCard){ - if (card->defenser) match = NULL; - }else if (defenser == &AnyCard){ - if (!card->defenser) match = NULL; - }else{ - // we don't care about the attack/blocker state - } - } - //Counters - if (anyCounter) { - if (!(card->counters->mCount)) { - match = NULL; - }else{ - int hasCounter = 0; - for (int i = 0; i < card->counters->mCount; i++) { - if (card->counters->counters[i]->nb > 0) hasCounter = 1; - } - if (!hasCounter) match = NULL; + //Abilities + for (map::const_iterator it = basicAbilities.begin(); it != basicAbilities.end(); ++it) + { + int j = it->first; + if ((basicAbilities[j] == 1 && !card->basicAbilities[j]) || (basicAbilities[j] == -1 && card->basicAbilities[j])) + { + match = NULL; + } } - }else{ - if (counterComparisonMode) { - Counter * targetCounter = card->counters->hasCounter(counterName.c_str(),counterPower,counterToughness); - if (targetCounter) { - if (!valueInRange(counterComparisonMode,targetCounter->nb,counterNB)) match = NULL; - } else { - if (counterComparisonMode != COMPARISON_LESS && counterComparisonMode != COMPARISON_AT_MOST) match = NULL; - } - } - } - return match; + if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped())) + { + match = NULL; + } + + if ((fresh == -1 && card->fresh) || (fresh == 1 && !card->fresh)) + { + match = NULL; + } + + if ((isToken == -1 && card->isToken) || (isToken == 1 && !card->isToken)) + { + match = NULL; + } + if (attacker == 1) + { + if (defenser == &AnyCard) + { + if (!card->attacker && !card->defenser) + match = NULL; + } + else + { + if (!card->attacker) + match = NULL; + } + } + else if (attacker == -1) + { + if (defenser == &NoCard) + { + if (card->attacker || card->defenser) + match = NULL; + } + else + { + if (card->attacker) + match = NULL; + } + } + else + { + if (defenser == &NoCard) + { + if (card->defenser) + match = NULL; + } + else if (defenser == &AnyCard) + { + if (!card->defenser) + match = NULL; + } + else + { + // we don't care about the attack/blocker state + } + } + + //Counters + if (anyCounter) + { + if (!(card->counters->mCount)) + { + match = NULL; + } + else + { + int hasCounter = 0; + for (int i = 0; i < card->counters->mCount; i++) + { + if (card->counters->counters[i]->nb > 0) + hasCounter = 1; + } + if (!hasCounter) + match = NULL; + } + } + else + { + if (counterComparisonMode) + { + Counter * targetCounter = card->counters->hasCounter(counterName.c_str(), counterPower, counterToughness); + if (targetCounter) + { + if (!valueInRange(counterComparisonMode, targetCounter->nb, counterNB)) + match = NULL; + } + else + { + if (counterComparisonMode != COMPARISON_LESS && counterComparisonMode != COMPARISON_AT_MOST) + match = NULL; + } + } + } + + return match; } -MTGCardInstance * CardDescriptor::match(MTGGameZone * zone){ - return (nextmatch(zone, NULL)); +MTGCardInstance * CardDescriptor::match(MTGGameZone * zone) +{ + return (nextmatch(zone, NULL)); } -MTGCardInstance * CardDescriptor::nextmatch(MTGGameZone * zone, MTGCardInstance * previous){ - int found = 0; - if (NULL == previous) found = 1; - for(int i=0; i < zone->nb_cards; i++){ - if(found && match(zone->cards[i])){ - return zone->cards[i]; +MTGCardInstance * CardDescriptor::nextmatch(MTGGameZone * zone, MTGCardInstance * previous) +{ + int found = 0; + if (NULL == previous) + found = 1; + for (int i = 0; i < zone->nb_cards; i++) + { + if (found && match(zone->cards[i])) + { + return zone->cards[i]; + } + if (zone->cards[i] == previous) + { + found = 1; + } } - if (zone->cards[i] == previous){ - found = 1; - } - } - return NULL; + return NULL; } diff --git a/projects/mtg/src/CardDisplay.cpp b/projects/mtg/src/CardDisplay.cpp index cec604c2f..2850835f5 100644 --- a/projects/mtg/src/CardDisplay.cpp +++ b/projects/mtg/src/CardDisplay.cpp @@ -7,235 +7,278 @@ #include "MTGGameZones.h" #include "GameObserver.h" -CardDisplay::CardDisplay() : mId(0), game(GameObserver::GetInstance()) { - tc = NULL; - listener = NULL; - nb_displayed_items = 7; - start_item = 0; - x = 0; - y = 0; - zone = NULL; +CardDisplay::CardDisplay() : + mId(0), game(GameObserver::GetInstance()) +{ + tc = NULL; + listener = NULL; + nb_displayed_items = 7; + start_item = 0; + x = 0; + y = 0; + zone = NULL; } -CardDisplay::CardDisplay(int id, GameObserver* game, int _x, int _y, JGuiListener * _listener, TargetChooser * _tc, int _nb_displayed_items ) : mId(id), game(game), x(_x), y(_y) { - tc = _tc; - listener = _listener; - nb_displayed_items = _nb_displayed_items; - start_item = 0; - if (x + nb_displayed_items * 30 + 25 > SCREEN_WIDTH) x = SCREEN_WIDTH - (nb_displayed_items * 30 + 25); - if (y + 55 > SCREEN_HEIGHT) y = SCREEN_HEIGHT - 55; - zone = NULL; +CardDisplay::CardDisplay(int id, GameObserver* game, int _x, int _y, JGuiListener * _listener, TargetChooser * _tc, + int _nb_displayed_items) : + mId(id), game(game), x(_x), y(_y) +{ + tc = _tc; + listener = _listener; + nb_displayed_items = _nb_displayed_items; + start_item = 0; + if (x + nb_displayed_items * 30 + 25 > SCREEN_WIDTH) x = SCREEN_WIDTH - (nb_displayed_items * 30 + 25); + if (y + 55 > SCREEN_HEIGHT) y = SCREEN_HEIGHT - 55; + zone = NULL; } -void CardDisplay::AddCard(MTGCardInstance * _card){ - CardGui * card = NEW CardView(CardView::nullZone, _card, static_cast(x + 20 + (mCount - start_item) * 30), static_cast(y + 25)); - Add(card); +void CardDisplay::AddCard(MTGCardInstance * _card) +{ + CardGui * card = NEW CardView(CardView::nullZone, _card, static_cast (x + 20 + (mCount - start_item) * 30), + static_cast (y + 25)); + Add(card); } -void CardDisplay::init(MTGGameZone * zone){ - resetObjects(); - if (!zone) return; - start_item = 0; - for (int i= 0; i< zone->nb_cards; i++){ - AddCard(zone->cards[i]); - } - if (mCount) mObjects[0]->Entering(); -} - -void CardDisplay::rotateLeft(){ - if (start_item==0) return; - for (int i = 0; ix+=30; - } - start_item --; -} - -void CardDisplay::rotateRight(){ - if (start_item==mCount-1) return; - for (int i= 0; ix-=30; - } - start_item ++; -} - -void CardDisplay::Update(float dt){ - bool update = false; - - if (zone){ - int size = zone->cards.size(); - for (int i = start_item; i< start_item + nb_displayed_items && i < mCount; i++){ - if (i > size - 1) {update = true; break;} - CardGui * cardg = (CardGui *)mObjects[i]; - if (cardg->card != zone->cards[i]) update = true; - } - } - PlayGuiObjectController::Update(dt); - if (update) init(zone); -} - -bool CardDisplay::CheckUserInput(int x, int y) { - unsigned int distance2; - unsigned int minDistance2 = -1; - int n = mCurr; - JButton key; - if(JGE::GetInstance()->GetLeftClickCoordinates(x, y)) - { - for(int i = 0; i < mCount; i++) +void CardDisplay::init(MTGGameZone * zone) +{ + resetObjects(); + if (!zone) return; + start_item = 0; + for (int i = 0; i < zone->nb_cards; i++) { - int top, left; - if(mObjects[i]->getTopLeft(top, left)) - { - distance2 = (top-y)*(top-y) + (left-x)*(left-x); - if(distance2 < minDistance2) + AddCard(zone->cards[i]); + } + if (mCount) mObjects[0]->Entering(); +} + +void CardDisplay::rotateLeft() +{ + if (start_item == 0) return; + for (int i = 0; i < mCount; i++) + { + CardGui * cardg = (CardGui *) mObjects[i]; + cardg->x += 30; + } + start_item--; +} + +void CardDisplay::rotateRight() +{ + if (start_item == mCount - 1) return; + for (int i = 0; i < mCount; i++) + { + CardGui * cardg = (CardGui *) mObjects[i]; + cardg->x -= 30; + } + start_item++; +} + +void CardDisplay::Update(float dt) +{ + bool update = false; + + if (zone) + { + int size = zone->cards.size(); + for (int i = start_item; i < start_item + nb_displayed_items && i < mCount; i++) { - minDistance2 = distance2; - n = i; + if (i > size - 1) + { + update = true; + break; + } + CardGui * cardg = (CardGui *) mObjects[i]; + if (cardg->card != zone->cards[i]) update = true; } - } } - - if(n < mCurr) - key = JGE_BTN_LEFT; - else - key = JGE_BTN_RIGHT; - - if (n= mCount) { - n = mCount-1; - } - if (n>= start_item + nb_displayed_items) { - rotateRight(); - } - - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(key)) - { - mCurr = n; - mObjects[mCurr]->Entering(); - } - JGE::GetInstance()->LeftClickedProcessed(); - return true; - } - - return false; + PlayGuiObjectController::Update(dt); + if (update) init(zone); } +bool CardDisplay::CheckUserInput(int x, int y) +{ + unsigned int distance2; + unsigned int minDistance2 = -1; + int n = mCurr; + JButton key; + if (JGE::GetInstance()->GetLeftClickCoordinates(x, y)) + { + for (int i = 0; i < mCount; i++) + { + int top, left; + if (mObjects[i]->getTopLeft(top, left)) + { + distance2 = (top - y) * (top - y) + (left - x) * (left - x); + if (distance2 < minDistance2) + { + minDistance2 = distance2; + n = i; + } + } + } -bool CardDisplay::CheckUserInput(JButton key){ - if (JGE_BTN_SEC == key || JGE_BTN_PRI == key || JGE_BTN_UP == key || JGE_BTN_DOWN == key) - { - if (listener){ - listener->ButtonPressed(mId, 0); - return true; + if (n < mCurr) + key = JGE_BTN_LEFT; + else + key = JGE_BTN_RIGHT; + + if (n < start_item) + { + rotateLeft(); + } + else if (n >= mCount) + { + n = mCount - 1; + } + if (n >= start_item + nb_displayed_items) + { + rotateRight(); + } + + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(key)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + JGE::GetInstance()->LeftClickedProcessed(); + return true; } - } - if (!mCount) + return false; - - if (mActionButton == key) - { - if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){ - CardGui * cardg = (CardGui *)mObjects[mCurr]; - if (tc) { - tc->toggleTarget(cardg->card); - return true; - } else { - if (game) game->ButtonPressed(cardg); - return true; - } - } - return true; - } - - - switch(key) - { - case JGE_BTN_LEFT : - { - int n = mCurr; - n--; - if (nLeaving(JGE_BTN_LEFT)){ - mCurr = n; - mObjects[mCurr]->Entering(); - } - return true; - } - case JGE_BTN_RIGHT : - { - int n = mCurr; - n++; - if (n>= mCount) { - n = mCount-1; - } - if (n>= start_item + nb_displayed_items) { - rotateRight(); - } - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(JGE_BTN_RIGHT)){ - mCurr = n; - mObjects[mCurr]->Entering(); - } - } - return true; - default: - ; - } - return false; } - -void CardDisplay::Render(){ - - JRenderer * r = JRenderer::GetInstance(); - r->DrawRect(static_cast(x), static_cast(y), static_cast(nb_displayed_items * 30 + 20), 50, ARGB(255,255,255,255)); - if (!mCount) return; - for (int i = start_item; i< start_item + nb_displayed_items && i < mCount; i++){ - if (mObjects[i]){ - mObjects[i]->Render(); - if (tc){ - CardGui * cardg = (CardGui *)mObjects[i]; - if( tc->alreadyHasTarget(cardg->card)){ - r->DrawCircle(cardg->x + 5, cardg->y+5,5, ARGB(255,255,0,0)); - }else if (!tc->canTarget(cardg->card)){ - r->FillRect(cardg->x,cardg->y,30,40,ARGB(200,0,0,0)); - } - } - } - } - - //TODO: CardSelector should handle the graveyard and the library in the future... - if (mCount && mObjects[mCurr] != NULL) - { - mObjects[mCurr]->Render(); - CardGui * cardg = ((CardGui *)mObjects[mCurr]); - Pos pos = Pos(CardGui::BigWidth / 2, CardGui::BigHeight / 2 - 10, 1.0, 0.0, 220); - int drawMode = DrawMode::kNormal; - if (game) +bool CardDisplay::CheckUserInput(JButton key) +{ + if (JGE_BTN_SEC == key || JGE_BTN_PRI == key || JGE_BTN_UP == key || JGE_BTN_DOWN == key) { - pos.actY = 150; - if (x < (CardGui::BigWidth / 2)) pos.actX = SCREEN_WIDTH - 10 - CardGui::BigWidth / 2; - drawMode = CardSelectorSingleton::Instance()->GetDrawMode(); + if (listener) + { + listener->ButtonPressed(mId, 0); + return true; + } + } + if (!mCount) return false; + + if (mActionButton == key) + { + if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()) + { + CardGui * cardg = (CardGui *) mObjects[mCurr]; + if (tc) + { + tc->toggleTarget(cardg->card); + return true; + } + else + { + if (game) game->ButtonPressed(cardg); + return true; + } + } + return true; } - cardg->DrawCard(pos, drawMode); - } + switch (key) + { + case JGE_BTN_LEFT: + { + int n = mCurr; + n--; + if (n < start_item) + { + if (n < 0) + { + n = 0; + } + else + { + rotateLeft(); + } + } + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(JGE_BTN_LEFT)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + return true; + } + case JGE_BTN_RIGHT: + { + int n = mCurr; + n++; + if (n >= mCount) + { + n = mCount - 1; + } + if (n >= start_item + nb_displayed_items) + { + rotateRight(); + } + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(JGE_BTN_RIGHT)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + } + return true; + default: + ; + } + return false; +} + +void CardDisplay::Render() +{ + + JRenderer * r = JRenderer::GetInstance(); + r->DrawRect(static_cast (x), static_cast (y), static_cast (nb_displayed_items * 30 + 20), 50, + ARGB(255,255,255,255)); + if (!mCount) return; + for (int i = start_item; i < start_item + nb_displayed_items && i < mCount; i++) + { + if (mObjects[i]) + { + mObjects[i]->Render(); + if (tc) + { + CardGui * cardg = (CardGui *) mObjects[i]; + if (tc->alreadyHasTarget(cardg->card)) + { + r->DrawCircle(cardg->x + 5, cardg->y + 5, 5, ARGB(255,255,0,0)); + } + else if (!tc->canTarget(cardg->card)) + { + r->FillRect(cardg->x, cardg->y, 30, 40, ARGB(200,0,0,0)); + } + } + } + } + + //TODO: CardSelector should handle the graveyard and the library in the future... + if (mCount && mObjects[mCurr] != NULL) + { + mObjects[mCurr]->Render(); + CardGui * cardg = ((CardGui *) mObjects[mCurr]); + Pos pos = Pos(CardGui::BigWidth / 2, CardGui::BigHeight / 2 - 10, 1.0, 0.0, 220); + int drawMode = DrawMode::kNormal; + if (game) + { + pos.actY = 150; + if (x < (CardGui::BigWidth / 2)) pos.actX = SCREEN_WIDTH - 10 - CardGui::BigWidth / 2; + drawMode = CardSelectorSingleton::Instance()->GetDrawMode(); + } + + cardg->DrawCard(pos, drawMode); + } } ostream& CardDisplay::toString(ostream& out) const { - return (out << "CardDisplay ::: x,y : " << x << "," << y << " ; start_item : " << start_item << " ; nb_displayed_items " << nb_displayed_items << " ; tc : " << tc << " ; listener : " << listener); + return (out << "CardDisplay ::: x,y : " << x << "," << y << " ; start_item : " << start_item << " ; nb_displayed_items " + << nb_displayed_items << " ; tc : " << tc << " ; listener : " << listener); } - std::ostream& operator<<(std::ostream& out, const CardDisplay& m) { - return m.toString(out); + return m.toString(out); } diff --git a/projects/mtg/src/CardEffect.cpp b/projects/mtg/src/CardEffect.cpp index efca7a397..12afd8bb2 100644 --- a/projects/mtg/src/CardEffect.cpp +++ b/projects/mtg/src/CardEffect.cpp @@ -3,7 +3,8 @@ #include "../include/GameOptions.h" #include "../include/CardEffect.h" -CardEffect::CardEffect(CardGui* target) : target(target) +CardEffect::CardEffect(CardGui* target) : + target(target) { } @@ -15,5 +16,5 @@ CardEffect::~CardEffect() void CardEffect::Render() { - // std::cout << "Rendering effect" << std::endl; + // std::cout << "Rendering effect" << std::endl; } diff --git a/projects/mtg/src/CardGui.cpp b/projects/mtg/src/CardGui.cpp index 5ff8f57bf..6d685c071 100644 --- a/projects/mtg/src/CardGui.cpp +++ b/projects/mtg/src/CardGui.cpp @@ -24,660 +24,796 @@ const float kWidthScaleFactor = 0.8f; 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, false), card(card) {} -CardGui::CardGui(MTGCardInstance* card, const Pos& ref) : PlayGuiObject(Height, ref, false), card(card) {} - -CardView::CardView(const SelectorZone owner, MTGCardInstance* card, float x, float y) : CardGui(card, x, y), owner(owner) { - const Pos* ref = card->view; - while (card) + inline float SineHelperFunction(const float& value) { - if (ref == card->view) card->view = this; - card = card->next; + return sinf(2 * M_PI * (value) / 256.0f); + } + + inline float CosineHelperFunction(const float& value) + { + return cosf(2 * M_PI * (value - 35) / 256.0f); } } -CardView::CardView(const SelectorZone owner, MTGCardInstance* card, const Pos& ref) : CardGui(card, ref), owner(owner) { - const Pos* r = card->view; - while (card) +CardGui::CardGui(MTGCardInstance* card, float x, float y) : + PlayGuiObject(Height, x, y, false), card(card) +{ +} +CardGui::CardGui(MTGCardInstance* card, const Pos& ref) : + PlayGuiObject(Height, ref, false), card(card) +{ +} + +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 (r == card->view) card->view = this; - card = card->next; + 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; } } void CardGui::Update(float dt) { - PlayGuiObject::Update(dt); + PlayGuiObject::Update(dt); } void CardGui::DrawCard(const Pos& inPosition, int inMode) { - DrawCard(card, inPosition, inMode); - RenderCountersBig(inPosition); + DrawCard(card, inPosition, inMode); + RenderCountersBig(inPosition); } 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; - } + switch (inMode) + { + case DrawMode::kNormal: + RenderBig(inCard, inPosition); + break; + case DrawMode::kText: + AlternateRender(inCard, inPosition); + break; + default: + break; + } } - void CardGui::Render() { - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - JRenderer * renderer = JRenderer::GetInstance(); - GameObserver * game = GameObserver::GetInstance(); + JRenderer * renderer = JRenderer::GetInstance(); + GameObserver * game = GameObserver::GetInstance(); - TargetChooser * tc = NULL; - if (game) tc = game->getCurrentTargetChooser(); + TargetChooser * tc = NULL; + if (game) + tc = game->getCurrentTargetChooser(); - bool alternate = true; - JQuad * quad = resources.RetrieveCard(card,CACHE_THUMB); + bool alternate = true; + JQuad * quad = resources.RetrieveCard(card, CACHE_THUMB); #if defined (WIN32) || defined (LINUX) - //On pcs we render the big image if the thumbnail is not available - if (!quad) quad = resources.RetrieveCard(card); + //On pcs we render the big image if the thumbnail is not available + if (!quad) quad = resources.RetrieveCard(card); #endif - if (quad) alternate = false; - else quad = AlternateThumbQuad(card); + if (quad) + alternate = false; + else + quad = AlternateThumbQuad(card); - float cardScale = quad ? 40 / quad->mHeight : 1; - float scale = actZ * cardScale; + float cardScale = quad ? 40 / quad->mHeight : 1; + float scale = actZ * cardScale; - JQuad* shadow = NULL; - if (actZ > 1) { - shadow = resources.GetQuad("shadow"); - shadow->SetColor(ARGB(static_cast(actA)/2,255,255,255)); - renderer->RenderQuad(shadow, actX + (actZ-1)*15, actY + (actZ-1)*15, actT, 28*actZ/16, 40*actZ/16); - } - - if (quad) { - quad->SetColor(ARGB(static_cast(actA),255,255,255)); - renderer->RenderQuad(quad, 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); - - JQuad * icon = NULL; - if (card->hasSubtype("plains")) - icon = resources.GetQuad("c_white"); - else if (card->hasSubtype("swamp")) - icon = resources.GetQuad("c_black"); - else if (card->hasSubtype("forest")) - icon = resources.GetQuad("c_green"); - else if (card->hasSubtype("mountain")) - icon = resources.GetQuad("c_red"); - else if (card->hasSubtype("island")) - icon = resources.GetQuad("c_blue"); - - - if (icon){ - icon->SetColor(ARGB(static_cast(actA),255,255,255)); - renderer->RenderQuad(icon, actX, actY, 0); - icon->SetColor(ARGB(255,255,255,255)); //Putting color back as this quad is shared - } - - } -//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 = resources.GetQuad("shadow"); - shadow->SetColor(ARGB(200,255,255,255)); - renderer->RenderQuad(shadow, actX, actY, actT, (28*actZ + 1)/16 , 40*actZ/16); - } - - PlayGuiObject::Render(); -} - - - -JQuad * CardGui::AlternateThumbQuad(MTGCard * card){ - JQuad * q; - - if(card->data->countColors() > 1){ - q = resources.RetrieveTempQuad("gold_thumb.jpg"); - } - else{ - switch(card->data->getColor()) - { - case Constants::MTG_COLOR_ARTIFACT : q = resources.RetrieveTempQuad("artifact_thumb.jpg");break; - case Constants::MTG_COLOR_GREEN: q = resources.RetrieveTempQuad("green_thumb.jpg");break; - case Constants::MTG_COLOR_BLUE : q = resources.RetrieveTempQuad("blue_thumb.jpg");break; - case Constants::MTG_COLOR_RED : q = resources.RetrieveTempQuad("red_thumb.jpg");break; - case Constants::MTG_COLOR_BLACK: q = resources.RetrieveTempQuad("black_thumb.jpg");break; - case Constants::MTG_COLOR_WHITE: q = resources.RetrieveTempQuad("white_thumb.jpg");break; - case Constants::MTG_COLOR_LAND : q = resources.RetrieveTempQuad("land_thumb.jpg");break; - default: q = resources.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(); - JQuad * q; - - float x = pos.actX; - - if(card->data->countColors() > 1) { - q = resources.RetrieveTempQuad("gold.jpg"); - } else { - switch(card->data->getColor()) - { - case Constants::MTG_COLOR_ARTIFACT: q = resources.RetrieveTempQuad("artifact.jpg");break; - case Constants::MTG_COLOR_GREEN: q = resources.RetrieveTempQuad("green.jpg");break; - case Constants::MTG_COLOR_BLUE : q = resources.RetrieveTempQuad("blue.jpg");break; - case Constants::MTG_COLOR_RED : q = resources.RetrieveTempQuad("red.jpg");break; - case Constants::MTG_COLOR_BLACK: q = resources.RetrieveTempQuad("black.jpg");break; - case Constants::MTG_COLOR_WHITE: q = resources.RetrieveTempQuad("white.jpg");break; - case Constants::MTG_COLOR_LAND: q = resources.RetrieveTempQuad("land.jpg");break; - default: q = resources.RetrieveTempQuad("gold.jpg");break; - } - } - if(q && 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, x, pos.actY, pos.actT, scale, scale); - } - // Write the title - WFont * font = resources.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); - const std::vector txt = card->data->formattedText(); - 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()) + JQuad* shadow = NULL; + if (actZ > 1) { - 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); - } + shadow = resources.GetQuad("shadow"); + shadow->SetColor(ARGB(static_cast(actA)/2,255,255,255)); + renderer->RenderQuad(shadow, actX + (actZ - 1) * 15, actY + (actZ - 1) * 15, actT, 28 * actZ / 16, 40 * actZ / 16); + } - // 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 (quad) + { + quad->SetColor(ARGB(static_cast(actA),255,255,255)); + renderer->RenderQuad(quad, actX, actY, actT, scale, scale); + } - if (scale < 0) + 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); + + JQuad * icon = NULL; + if (card->hasSubtype("plains")) + icon = resources.GetQuad("c_white"); + else if (card->hasSubtype("swamp")) + icon = resources.GetQuad("c_black"); + else if (card->hasSubtype("forest")) + icon = resources.GetQuad("c_green"); + else if (card->hasSubtype("mountain")) + icon = resources.GetQuad("c_red"); + else if (card->hasSubtype("island")) + icon = resources.GetQuad("c_blue"); + + if (icon) { - renderer->RenderQuad(manaIcons[h->color1], 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], 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); + icon->SetColor(ARGB(static_cast(actA),255,255,255)); + renderer->RenderQuad(icon, actX, actY, 0); + icon->SetColor(ARGB(255,255,255,255)); //Putting color back as this quad is shared } + + } + //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 = resources.GetQuad("shadow"); + shadow->SetColor(ARGB(200,255,255,255)); + renderer->RenderQuad(shadow, actX, actY, actT, (28 * actZ + 1) / 16, 40 * actZ / 16); + } + + PlayGuiObject::Render(); +} + +JQuad * CardGui::AlternateThumbQuad(MTGCard * card) +{ + JQuad * q; + + if (card->data->countColors() > 1) + { + q = resources.RetrieveTempQuad("gold_thumb.jpg"); + } + else + { + switch (card->data->getColor()) + { + case Constants::MTG_COLOR_ARTIFACT: + q = resources.RetrieveTempQuad("artifact_thumb.jpg"); + break; + case Constants::MTG_COLOR_GREEN: + q = resources.RetrieveTempQuad("green_thumb.jpg"); + break; + case Constants::MTG_COLOR_BLUE: + q = resources.RetrieveTempQuad("blue_thumb.jpg"); + break; + case Constants::MTG_COLOR_RED: + q = resources.RetrieveTempQuad("red_thumb.jpg"); + break; + case Constants::MTG_COLOR_BLACK: + q = resources.RetrieveTempQuad("black_thumb.jpg"); + break; + case Constants::MTG_COLOR_WHITE: + q = resources.RetrieveTempQuad("white_thumb.jpg"); + break; + case Constants::MTG_COLOR_LAND: + q = resources.RetrieveTempQuad("land_thumb.jpg"); + break; + default: + q = resources.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(); + JQuad * q; + + float x = pos.actX; + + if (card->data->countColors() > 1) + { + q = resources.RetrieveTempQuad("gold.jpg"); + } + else + { + switch (card->data->getColor()) + { + case Constants::MTG_COLOR_ARTIFACT: + q = resources.RetrieveTempQuad("artifact.jpg"); + break; + case Constants::MTG_COLOR_GREEN: + q = resources.RetrieveTempQuad("green.jpg"); + break; + case Constants::MTG_COLOR_BLUE: + q = resources.RetrieveTempQuad("blue.jpg"); + break; + case Constants::MTG_COLOR_RED: + q = resources.RetrieveTempQuad("red.jpg"); + break; + case Constants::MTG_COLOR_BLACK: + q = resources.RetrieveTempQuad("black.jpg"); + break; + case Constants::MTG_COLOR_WHITE: + q = resources.RetrieveTempQuad("white.jpg"); + break; + case Constants::MTG_COLOR_LAND: + q = resources.RetrieveTempQuad("land.jpg"); + break; + default: + q = resources.RetrieveTempQuad("gold.jpg"); + break; + } + } + if (q && 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, x, pos.actY, pos.actT, scale, scale); + } + // Write the title + WFont * font = resources.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); + const std::vector txt = card->data->formattedText(); + 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], 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], 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], 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], 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], 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], 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 (int cost = manacost->hasX()) + { + char buffer[10]; + sprintf(buffer, "X"); + renderer->RenderQuad(manaIcons[0], 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[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 { - renderer->RenderQuad(manaIcons[h->color2], 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], 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); +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); +} + +void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad) +{ + + if (!quad) + return; + + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * q; + + float x = pos.actX; + float displayScale = 250 / BigHeight; + + if (card->data->countColors() > 1) + { + q = resources.RetrieveTempQuad("gold.jpg"); + } + else + { + switch (card->data->getColor()) + { + case Constants::MTG_COLOR_ARTIFACT: + q = resources.RetrieveTempQuad("artifact.jpg"); + break; + case Constants::MTG_COLOR_GREEN: + q = resources.RetrieveTempQuad("green.jpg"); + break; + case Constants::MTG_COLOR_BLUE: + q = resources.RetrieveTempQuad("blue.jpg"); + break; + case Constants::MTG_COLOR_RED: + q = resources.RetrieveTempQuad("red.jpg"); + break; + case Constants::MTG_COLOR_BLACK: + q = resources.RetrieveTempQuad("black.jpg"); + break; + case Constants::MTG_COLOR_WHITE: + q = resources.RetrieveTempQuad("white.jpg"); + break; + case Constants::MTG_COLOR_LAND: + q = resources.RetrieveTempQuad("land.jpg"); + break; + default: + q = resources.RetrieveTempQuad("gold.jpg"); + break; } - ++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], 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], 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 (int cost = manacost->hasX()) - { - char buffer[10]; - sprintf(buffer, "X"); - renderer->RenderQuad(manaIcons[0], 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[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 + } + if (q && q->mTex) { - 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); - } + q->SetHotSpot(static_cast (q->mTex->mWidth / 2), static_cast (q->mTex->mHeight / 2)); - //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; + float scale = pos.actZ * displayScale * BigHeight / q->mHeight; + q->SetColor(ARGB((int)pos.actA,255,255,255)); + renderer->RenderQuad(q, x, pos.actY, pos.actT, scale, scale); } - - switch(card->data->getColor()) + + const std::vector txt = card->data->formattedText(); + 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) { - 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 + imgY -= 10 * imgScale; + imgScale *= 0.75; } - - } + renderer->RenderQuad(quad, x, imgY, pos.actT, imgScale, imgScale); - font->SetScale(backup_scale); -} - - -void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad) { - - if (!quad) return; - - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * q; - - float x = pos.actX; - float displayScale = 250 / BigHeight; - - if(card->data->countColors() > 1) { - q = resources.RetrieveTempQuad("gold.jpg"); - } else { - switch(card->data->getColor()) - { - case Constants::MTG_COLOR_ARTIFACT: q = resources.RetrieveTempQuad("artifact.jpg");break; - case Constants::MTG_COLOR_GREEN: q = resources.RetrieveTempQuad("green.jpg");break; - case Constants::MTG_COLOR_BLUE : q = resources.RetrieveTempQuad("blue.jpg");break; - case Constants::MTG_COLOR_RED : q = resources.RetrieveTempQuad("red.jpg");break; - case Constants::MTG_COLOR_BLACK: q = resources.RetrieveTempQuad("black.jpg");break; - case Constants::MTG_COLOR_WHITE: q = resources.RetrieveTempQuad("white.jpg");break; - case Constants::MTG_COLOR_LAND: q = resources.RetrieveTempQuad("land.jpg");break; - default: q = resources.RetrieveTempQuad("gold.jpg");break; - } - } - if(q && 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, x, pos.actY, pos.actT, scale, scale); - } - - const std::vector txt = card->data->formattedText(); - 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 = resources.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 - { + // Write the title + WFont * font = resources.GetWFont(Fonts::MAGIC_FONT); + float backup_scale = font->GetScale(); + font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); 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); + 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); + } - if (scale < 0) - { - renderer->RenderQuad(manaIcons[h->color1], 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], 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], 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], 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) + // Write the description { - for (int cost = manacost->getCost(i); cost > 0; --cost) - { - renderer->RenderQuad(manaIcons[i], x + (-12*j + 75)*pos.actZ, pos.actY + (yOffset)*pos.actZ, 0, 0.4f * pos.actZ, 0.4f * pos.actZ); - ++j; - } + 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)); } - // Colorless mana - if (int cost = manacost->getCost(0)) - { - char buffer[10]; - sprintf(buffer, "%d", cost); - renderer->RenderQuad(manaIcons[0], 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 (int cost = manacost->hasX()) - { - char buffer[10]; - sprintf(buffer, "X"); - renderer->RenderQuad(manaIcons[0], 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 + // Write the strength + if (card->data->isCreature()) { - DebugTrace("Typeless card: " << setlist[card->setId].c_str() << card->data->getName() << card->getId()); + 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], 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], 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], 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], 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], 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], 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 (int cost = manacost->hasX()) + { + char buffer[10]; + sprintf(buffer, "X"); + renderer->RenderQuad(manaIcons[0], 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)); - { +//expansion and rarity +font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); +{ char buf[512]; - switch(card->getRarity()){ - case Constants::RARITY_M: + switch(card->getRarity()) + { + case Constants::RARITY_M: sprintf(buf,_("%s Mythic").c_str(),setlist[card->setId].c_str()); break; - case Constants::RARITY_R: + case Constants::RARITY_R: sprintf(buf,_("%s Rare").c_str(),setlist[card->setId].c_str()); break; - case Constants::RARITY_U: + case Constants::RARITY_U: sprintf(buf,_("%s Uncommon").c_str(),setlist[card->setId].c_str()); break; - case Constants::RARITY_C: + case Constants::RARITY_C: sprintf(buf,_("%s Common").c_str(),setlist[card->setId].c_str()); break; - case Constants::RARITY_L: + case Constants::RARITY_L: sprintf(buf,_("%s Land").c_str(),setlist[card->setId].c_str()); break; - case Constants::RARITY_T: + case Constants::RARITY_T: sprintf(buf,_("%s Token").c_str(),setlist[card->setId].c_str()); break; - default: - case Constants::RARITY_S: + 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 + 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); } -void CardGui::AlternateRenderBig(const Pos& pos){ - AlternateRender(card,pos); - RenderCountersBig(pos); +font->SetScale(backup_scale); +} + +void CardGui::AlternateRenderBig(const Pos& pos) +{ + AlternateRender(card, pos); + RenderCountersBig(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(); +void CardGui::RenderBig(MTGCard* card, const Pos& pos) +{ + JRenderer * renderer = JRenderer::GetInstance(); - float x = pos.actX; + float x = pos.actX; - JQuad * quad = resources.RetrieveCard(card); - if (quad){ - if (quad->mHeight < quad->mWidth) { - return TinyCropRender(card, pos, quad); - } - quad->SetColor(ARGB(255,255,255,255)); - float scale = pos.actZ * 257.f / quad->mHeight; - renderer->RenderQuad(quad, x, pos.actY, pos.actT, scale, scale); - return; - } - - //No card found, attempt to render the thumbnail instead (better than nothing, even if it gets super stretched) - JQuad * q; - if ((q = resources.RetrieveCard(card,CACHE_THUMB))) + JQuad * quad = resources.RetrieveCard(card); + if (quad) { - float scale = pos.actZ * 250 / q->mHeight; - q->SetColor(ARGB(255,255,255,255)); - renderer->RenderQuad(q, x, pos.actY, pos.actT, scale, scale); - return; - } - - // If we come here, we do not have the picture. - AlternateRender(card,pos); -} - -void CardGui::RenderCountersBig(const Pos& pos){ - // Write Named Counters - if (card->counters) { - WFont * font = resources.GetWFont(Fonts::MAGIC_FONT); - font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); - font->SetScale(kWidthScaleFactor * pos.actZ); - std::vector txt = card->formattedText(); - unsigned i = txt.size() + 1; - Counter * c = NULL; - for (int t = 0; t < card->counters->mCount; t++, i++) { - if (c) { - c = card->counters->getNext(c); - }else{ - c = card->counters->counters[0]; - } - if (c->nb > 0) { - char buf[512]; - if (c->name != "") { - std::string s = c->name; - s[0] = toupper(s[0]); - sprintf(buf,_("%s counters: %i").c_str(),s.c_str(),c->nb); - }else{ - sprintf(buf,_("%i/%i counters: %i").c_str(),c->power,c->toughness,c->nb); + if (quad->mHeight < quad->mWidth) + { + return TinyCropRender(card, pos, quad); } - font->DrawString(buf, pos.actX + (22 - BigWidth / 2)*pos.actZ, pos.actY + (-BigHeight/2 + 80 + 11 * i)*pos.actZ); - } + quad->SetColor(ARGB(255,255,255,255)); + float scale = pos.actZ * 257.f / quad->mHeight; + renderer->RenderQuad(quad, x, pos.actY, pos.actT, scale, scale); + return; } - } + + //No card found, attempt to render the thumbnail instead (better than nothing, even if it gets super stretched) + JQuad * q; + if ((q = resources.RetrieveCard(card, CACHE_THUMB))) + { + float scale = pos.actZ * 250 / q->mHeight; + q->SetColor(ARGB(255,255,255,255)); + renderer->RenderQuad(q, x, pos.actY, pos.actT, scale, scale); + return; + } + + // If we come here, we do not have the picture. + AlternateRender(card, pos); } -void CardGui::RenderBig(const Pos& pos){ - RenderBig(card,pos); - RenderCountersBig(pos); +void CardGui::RenderCountersBig(const Pos& pos) +{ + // Write Named Counters + if (card->counters) + { + WFont * font = resources.GetWFont(Fonts::MAGIC_FONT); + font->SetColor(ARGB((int)pos.actA, 0, 0, 0)); + font->SetScale(kWidthScaleFactor * pos.actZ); + std::vector txt = card->formattedText(); + unsigned i = txt.size() + 1; + Counter * c = NULL; + for (int t = 0; t < card->counters->mCount; t++, i++) + { + if (c) + { + c = card->counters->getNext(c); + } + else + { + c = card->counters->counters[0]; + } + if (c->nb > 0) + { + char buf[512]; + if (c->name != "") + { + std::string s = c->name; + s[0] = toupper(s[0]); + sprintf(buf, _("%s counters: %i").c_str(), s.c_str(), c->nb); + } + else + { + sprintf(buf, _("%i/%i counters: %i").c_str(), c->power, c->toughness, c->nb); + } + font->DrawString(buf, pos.actX + (22 - BigWidth / 2) * pos.actZ, pos.actY + (-BigHeight / 2 + 80 + 11 * i) + * pos.actZ); + } + } + } } +void CardGui::RenderBig(const Pos& pos) +{ + RenderBig(card, pos); + RenderCountersBig(pos); +} +MTGCardInstance* CardView::getCard() +{ + return card; +} -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) {}; +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); + 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); + return (out << "CardGui ::: x,y " << x << "," << y); } diff --git a/projects/mtg/src/CardPrimitive.cpp b/projects/mtg/src/CardPrimitive.cpp index 310a06c31..737c15844 100644 --- a/projects/mtg/src/CardPrimitive.cpp +++ b/projects/mtg/src/CardPrimitive.cpp @@ -8,304 +8,354 @@ using std::string; -CardPrimitive::CardPrimitive(){ - init(); +CardPrimitive::CardPrimitive() +{ + init(); } +CardPrimitive::CardPrimitive(CardPrimitive * source) +{ + for (map::const_iterator it = source->basicAbilities.begin(); it != source->basicAbilities.end(); ++it) + basicAbilities[it->first] = source->basicAbilities[it->first]; -CardPrimitive::CardPrimitive(CardPrimitive * source){ - for (map::const_iterator it = source->basicAbilities.begin(); it != source->basicAbilities.end(); ++it) - basicAbilities[it->first] = source->basicAbilities[it->first]; + for (size_t i = 0; i < source->types.size(); ++i) + types.push_back(source->types[i]); + for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) + colors[i] = source->colors[i]; + manaCost.copy(source->getManaCost()); - for (size_t i = 0; i< source->types.size(); ++i) - types.push_back(source->types[i]); - for (int i = 0; i< Constants::MTG_NB_COLORS; ++i) - colors[i] = source->colors[i]; - manaCost.copy(source->getManaCost()); + text = source->text; + setName(source->name); - text = source->text; - setName(source->name); + power = source->power; + toughness = source->toughness; - power = source->power; - toughness = source->toughness; - - magicText = source->magicText; - for(map::const_iterator it = source->magicTexts.begin(); it != source->magicTexts.end(); ++it) - magicTexts[it->first] = source->magicTexts[it->first]; - spellTargetType = source->spellTargetType; - alias = source->alias; + magicText = source->magicText; + for (map::const_iterator it = source->magicTexts.begin(); it != source->magicTexts.end(); ++it) + magicTexts[it->first] = source->magicTexts[it->first]; + spellTargetType = source->spellTargetType; + alias = source->alias; } -int CardPrimitive::init(){ - basicAbilities.clear(); +int CardPrimitive::init() +{ + basicAbilities.clear(); - types.clear(); + types.clear(); - for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) - colors[i] = 0; + for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) + colors[i] = 0; - magicText = ""; - magicTexts.clear(); - spellTargetType = ""; - alias = 0; - return 1; + magicText = ""; + magicTexts.clear(); + spellTargetType = ""; + alias = 0; + return 1; } const vector& CardPrimitive::formattedText() { - if (ftdText.empty()) + if (ftdText.empty()) { - std::string s = text; - std::string::size_type found = s.find_first_of("{}"); - while (found!=string::npos) - { - s[found] = '/'; - found = s.find_first_of("{}", found + 1); - } - while (s.length() > 0) - { - std::string::size_type len = neofont ? 24 :33; - std::string::size_type cut = s.find_first_of("., \t)", 0); - if (cut >= len || cut == string::npos) - { - // Fix for single byte character in some complex language like Chinese - u8 * src = (u8 *)s.c_str(); - if (neofont) { - len = 0; - std::string::size_type limit = 24; - while (*src != 0) { - if (*src > 0x80) { // Non-ASCII - if (len + 2 > limit && !(((*src & 0xF0) == 0xA0) && ((*(src+1) & 0xF0) == 0xA0))) break; - src += 2; len += 2; - } - else { // ASCII - if (*src == '/' && (*(src+1) & 0xF0) == 0xA0) limit += 3; - if (len + 1 > limit && (*src == '+' || *src == '-' || *src == '/')) break; - src += 1; len += 1; - } + std::string s = text; + std::string::size_type found = s.find_first_of("{}"); + while (found != string::npos) + { + s[found] = '/'; + found = s.find_first_of("{}", found + 1); + } + while (s.length() > 0) + { + std::string::size_type len = neofont ? 24 : 33; + std::string::size_type cut = s.find_first_of("., \t)", 0); + if (cut >= len || cut == string::npos) + { + // Fix for single byte character in some complex language like Chinese + u8 * src = (u8 *) s.c_str(); + if (neofont) + { + len = 0; + std::string::size_type limit = 24; + while (*src != 0) + { + if (*src > 0x80) + { // Non-ASCII + if (len + 2 > limit && !(((*src & 0xF0) == 0xA0) && ((*(src + 1) & 0xF0) == 0xA0))) + break; + src += 2; + len += 2; + } + else + { // ASCII + if (*src == '/' && (*(src + 1) & 0xF0) == 0xA0) + limit += 3; + if (len + 1 > limit && (*src == '+' || *src == '-' || *src == '/')) + break; + src += 1; + len += 1; + } + } } - } - ftdText.push_back(s.substr(0,len)); - if (s.length() > len) - s = s.substr(len, s.length() - len); - else - s = ""; - } - else - { - std::string::size_type newcut = cut; - while (newcut < len && newcut != string::npos) - { - // neofont use space to separate one line - u8 * src = (u8 *)s.c_str(); - if (neofont && *src > 0x80) break; - cut = newcut; - newcut = s.find_first_of("., \t)", newcut + 1); - } - ftdText.push_back(s.substr(0,cut+1)); - if (s.length() > cut+1) - s = s.substr(cut+1,s.length() - cut - 1); - else - s = ""; - } - } + ftdText.push_back(s.substr(0, len)); + if (s.length() > len) + s = s.substr(len, s.length() - len); + else + s = ""; + } + else + { + std::string::size_type newcut = cut; + while (newcut < len && newcut != string::npos) + { + // neofont use space to separate one line + u8 * src = (u8 *) s.c_str(); + if (neofont && *src > 0x80) + break; + cut = newcut; + newcut = s.find_first_of("., \t)", newcut + 1); + } + ftdText.push_back(s.substr(0, cut + 1)); + if (s.length() > cut + 1) + s = s.substr(cut + 1, s.length() - cut - 1); + else + s = ""; + } + } } - return ftdText; + return ftdText; } - -bool CardPrimitive::isCreature(){ - return hasSubtype(Subtypes::TYPE_CREATURE); +bool CardPrimitive::isCreature() +{ + return hasSubtype(Subtypes::TYPE_CREATURE); } -bool CardPrimitive::isLand(){ - return hasSubtype(Subtypes::TYPE_LAND); +bool CardPrimitive::isLand() +{ + return hasSubtype(Subtypes::TYPE_LAND); } -bool CardPrimitive::isSpell(){ - return (!isCreature() && !isLand()); +bool CardPrimitive::isSpell() +{ + return (!isCreature() && !isLand()); } -void CardPrimitive::setColor(string _color, int removeAllOthers){ - if(_color.compare("blue")==0) return setColor(Constants::MTG_COLOR_BLUE,removeAllOthers); - if(_color.compare("red")==0) return setColor(Constants::MTG_COLOR_RED,removeAllOthers); - if(_color.compare("green")==0) return setColor(Constants::MTG_COLOR_GREEN,removeAllOthers); - if(_color.compare("black")==0) return setColor(Constants::MTG_COLOR_BLACK,removeAllOthers); - if(_color.compare("white")==0) return setColor(Constants::MTG_COLOR_WHITE,removeAllOthers); - if(_color.compare("artifact")==0) return setColor(Constants::MTG_COLOR_ARTIFACT,removeAllOthers); +void CardPrimitive::setColor(string _color, int removeAllOthers) +{ + if (_color.compare("blue") == 0) + return setColor(Constants::MTG_COLOR_BLUE, removeAllOthers); + if (_color.compare("red") == 0) + return setColor(Constants::MTG_COLOR_RED, removeAllOthers); + if (_color.compare("green") == 0) + return setColor(Constants::MTG_COLOR_GREEN, removeAllOthers); + if (_color.compare("black") == 0) + return setColor(Constants::MTG_COLOR_BLACK, removeAllOthers); + if (_color.compare("white") == 0) + return setColor(Constants::MTG_COLOR_WHITE, removeAllOthers); + if (_color.compare("artifact") == 0) + return setColor(Constants::MTG_COLOR_ARTIFACT, removeAllOthers); } -void CardPrimitive::setColor(int _color, int removeAllOthers){ - if (removeAllOthers) - for (int i=0; ifind(value); - addType(id); +void CardPrimitive::setSubtype(const string& value) +{ + int id = Subtypes::subtypesList->find(value); + addType(id); } -void CardPrimitive::addType(int id){ - types.push_back(id); +void CardPrimitive::addType(int id) +{ + types.push_back(id); } - //TODO Definitely move some of these functions to CardInstance. There is no reason to remove a type from an CardPrimitive since they represent the Database //Removes a type from the types of a given card //If removeAll is true, removes all occurences of this type, otherwise only removes the first occurence -int CardPrimitive::removeType(string value, int removeAll){ +int CardPrimitive::removeType(string value, int removeAll) +{ - int id = Subtypes::subtypesList->find(value); - return removeType(id, removeAll); + int id = Subtypes::subtypesList->find(value); + return removeType(id, removeAll); } -int CardPrimitive::removeType(int id, int removeAll){ - int result = 0; - for (int i = types.size() -1 ; i >=0; i--){ - if (types[i] == id){ - types.erase(types.begin()+i); - result++; - if (!removeAll) return result; +int CardPrimitive::removeType(int id, int removeAll) +{ + int result = 0; + for (int i = types.size() - 1; i >= 0; i--) + { + if (types[i] == id) + { + types.erase(types.begin() + i); + result++; + if (!removeAll) + return result; + } } - } - return result; + return result; } - - - -void CardPrimitive::setText(const string& value){ - text = value; +void CardPrimitive::setText(const string& value) +{ + text = value; } -const char * CardPrimitive::getText(){ - return text.c_str(); +const char * CardPrimitive::getText() +{ + return text.c_str(); } -void CardPrimitive::addMagicText(string value){ - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - if (magicText.size()) magicText.append("\n"); - magicText.append(value); +void CardPrimitive::addMagicText(string value) +{ + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + if (magicText.size()) + magicText.append("\n"); + magicText.append(value); } -void CardPrimitive::addMagicText(string value, string key){ - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - if (magicTexts[key].size()) magicTexts[key].append("\n"); - magicTexts[key].append(value); +void CardPrimitive::addMagicText(string value, string key) +{ + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + if (magicTexts[key].size()) + magicTexts[key].append("\n"); + magicTexts[key].append(value); } -void CardPrimitive::setName(const string& value) { - name = value; - lcname = value; - std::transform(lcname.begin(), lcname.end(), lcname.begin(), ::tolower); - //This is a bug fix for plague rats and the "foreach ability" - //Right now we add names as types, so that they get recognized - if (lcname.at(value.length()-1) == 's') Subtypes::subtypesList->find(lcname); +void CardPrimitive::setName(const string& value) +{ + name = value; + lcname = value; + std::transform(lcname.begin(), lcname.end(), lcname.begin(), ::tolower); + //This is a bug fix for plague rats and the "foreach ability" + //Right now we add names as types, so that they get recognized + if (lcname.at(value.length() - 1) == 's') + Subtypes::subtypesList->find(lcname); } -const string CardPrimitive::getName() const{ - return name; +const string CardPrimitive::getName() const +{ + return name; } -const string CardPrimitive::getLCName() const{ - return lcname; +const string CardPrimitive::getLCName() const +{ + return lcname; } - - -ManaCost* CardPrimitive::getManaCost(){ - return &manaCost; +ManaCost* CardPrimitive::getManaCost() +{ + return &manaCost; } - - -bool CardPrimitive::hasType(int _type){ - for (size_t i = 0; ifind(_type); - return hasType(id); +bool CardPrimitive::hasType(const char * _type) +{ + int id = Subtypes::subtypesList->find(_type); + return hasType(id); } - -bool CardPrimitive::hasSubtype(const char * _subtype){ - int id = Subtypes::subtypesList->find(_subtype); - return hasType(id); +bool CardPrimitive::hasSubtype(const char * _subtype) +{ + int id = Subtypes::subtypesList->find(_subtype); + return hasType(id); } -bool CardPrimitive::hasSubtype(string _subtype){ - int id = Subtypes::subtypesList->find(_subtype); - return hasType(id); +bool CardPrimitive::hasSubtype(string _subtype) +{ + int id = Subtypes::subtypesList->find(_subtype); + return hasType(id); } - -int CardPrimitive::has(int basicAbility){ - return basicAbilities[basicAbility]; +int CardPrimitive::has(int basicAbility) +{ + return basicAbilities[basicAbility]; } //--------------------------------------------- // Creature specific //--------------------------------------------- -void CardPrimitive::setPower(int _power){ - power = _power; +void CardPrimitive::setPower(int _power) +{ + power = _power; } -int CardPrimitive::getPower(){ - return power; +int CardPrimitive::getPower() +{ + return power; } -void CardPrimitive::setToughness(int _toughness){ - toughness = _toughness; +void CardPrimitive::setToughness(int _toughness) +{ + toughness = _toughness; } -int CardPrimitive::getToughness(){ - return toughness; +int CardPrimitive::getToughness() +{ + return toughness; } diff --git a/projects/mtg/src/CardSelector.cpp b/projects/mtg/src/CardSelector.cpp index bb34c866b..7691c1d1a 100644 --- a/projects/mtg/src/CardSelector.cpp +++ b/projects/mtg/src/CardSelector.cpp @@ -16,273 +16,436 @@ using std::cout; #undef True #endif -struct Left : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return ref->x - test->x > fabs(ref->y - test->y); } }; -struct Right : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return test->x - ref->x > fabs(ref->y - test->y); } }; -struct Up : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return ref->y - test->y > fabs(ref->x - test->x); } }; -struct Down : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return test->y - ref->y > fabs(ref->x - test->x); } }; -struct Diff : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return ref != test; } }; -struct True : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) - { return true; } }; +struct Left: public Exp +{ + static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) + { + return ref->x - test->x > fabs(ref->y - test->y); + } +}; +struct Right: public Exp +{ + static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) + { + return test->x - ref->x > fabs(ref->y - test->y); + } +}; +struct Up: public Exp +{ + static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) + { + return ref->y - test->y > fabs(ref->x - test->x); + } +}; +struct Down: public Exp +{ + static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) + { + return test->y - ref->y > fabs(ref->x - test->x); + } +}; +struct Diff: public Exp +{ + static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) + { + return ref != test; + } +}; +struct True: public Exp +{ + static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) + { + return true; + } +}; +CardSelector::SelectorMemory::SelectorMemory(PlayGuiObject* object) : + object(object) +{ + if (object) + { + x = object->x; + y = object->y; + } +} +CardSelector::SelectorMemory::SelectorMemory() +{ + object = NULL; + x = y = 0; +} -CardSelector::SelectorMemory::SelectorMemory(PlayGuiObject* object) : object(object) { if (object) { x = object->x; y = object->y; } } -CardSelector::SelectorMemory::SelectorMemory() { object = NULL; x = y = 0; } - - -CardSelector::CardSelector(DuelLayers* duel) : active(NULL), duel(duel), limitor(NULL), bigpos(300, 150, 1.0, 0.0, 220) {} +CardSelector::CardSelector(DuelLayers* duel) : + active(NULL), duel(duel), limitor(NULL), bigpos(300, 150, 1.0, 0.0, 220) +{ +} void CardSelector::Add(CardSelector::Target* target) { - if (NULL == active) - if (NULL == limitor || limitor->select(active)) - active = target; - CardView* c = dynamic_cast(target); - if (c) c->zoom = 1.0f; - c = dynamic_cast(active); - if (c) c->zoom = 1.4f; - cards.push_back(target); + if (NULL == active) + if (NULL == limitor || limitor->select(active)) + active = target; + CardView* c = dynamic_cast (target); + if (c) + c->zoom = 1.0f; + c = dynamic_cast (active); + if (c) + c->zoom = 1.4f; + cards.push_back(target); } void CardSelector::Remove(CardSelector::Target* card) { - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if (card == *it) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if (card == *it) + { + if (active == *it) + { + CardView* c = dynamic_cast (active); + if (c) + c->zoom = 1.0f; + active = closest (cards, limitor, active); + c = dynamic_cast (active); + if (c) + c->zoom = 1.4f; + } + if (active == *it) + active = NULL; + cards.erase(it); + return; + } +} + +CardSelector::Target* CardSelector::fetchMemory(SelectorMemory& memory) +{ + if (NULL == memory.object) + return NULL; + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if (*it == memory.object) + { + if ((NULL == limitor) || (limitor->select(memory.object))) + return memory.object; + else + break; + } + // We come here if the card is not in the selector any more, or if + // it is there but it is now refused by the limitor. + return closest (cards, limitor, memory.x, memory.y); +} + +void CardSelector::Push() +{ + memoryStack.push(SelectorMemory(active)); +} + +void CardSelector::Pop() +{ + Target* oldactive = active; + if (!memoryStack.empty()) { - if (active == *it) - { - CardView* c = dynamic_cast(active); if (c) c->zoom = 1.0f; - active = closest(cards, limitor, active); - c = dynamic_cast(active); if (c) c->zoom = 1.4f; - } - if (active == *it) active = NULL; - cards.erase(it); - return; + active = fetchMemory(memoryStack.top()); + memoryStack.pop(); + CardView::SelectorZone oldowner; + if (CardView *q = dynamic_cast(oldactive)) + oldowner = q->owner; + else + oldowner = CardView::nullZone; + if (CardView::nullZone != oldowner) + lasts[oldowner] = SelectorMemory(oldactive); } -} - -CardSelector::Target* CardSelector::fetchMemory(SelectorMemory& memory) { - if (NULL == memory.object) return NULL; - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if (*it == memory.object) { - if ((NULL == limitor) || (limitor->select(memory.object))) - return memory.object; - else break; + if (active != oldactive) + { + { + CardView* c = dynamic_cast (oldactive); + if (c) + c->zoom = 1.0f; + } //Is this needed, I think it is one in Leaving(0) ? + { + CardView* c = dynamic_cast (active); + if (c) + c->zoom = 1.4f; + } //Is this needed, I think it is one in Entering() ? + if (oldactive) + oldactive->Leaving(JGE_BTN_NONE); + if (active) + active->Entering(); } - // We come here if the card is not in the selector any more, or if - // it is there but it is now refused by the limitor. - return closest(cards, limitor, memory.x, memory.y); -} - -void CardSelector::Push() { - memoryStack.push(SelectorMemory(active)); -} - -void CardSelector::Pop() { - Target* oldactive = active; - if (!memoryStack.empty()) { - active = fetchMemory(memoryStack.top()); - memoryStack.pop(); - CardView::SelectorZone oldowner; - if (CardView *q = dynamic_cast(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone; - if (CardView::nullZone != oldowner) lasts[oldowner] = SelectorMemory(oldactive); - } - if (active != oldactive) { - { CardView* c = dynamic_cast(oldactive); if (c) c->zoom = 1.0f; } //Is this needed, I think it is one in Leaving(0) ? - { CardView* c = dynamic_cast(active); if (c) c->zoom = 1.4f; } //Is this needed, I think it is one in Entering() ? - if (oldactive) oldactive->Leaving(JGE_BTN_NONE); - if (active) active->Entering(); - } } bool CardSelector::CheckUserInput(JButton key) { - if (!active) { - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if ((NULL == limitor) || (limitor->select(*it))) { - active = *it; - active->Entering(); - return true; - } - return true; - } - Target* oldactive = active; - switch (key) { - case JGE_BTN_SEC: - GameObserver::GetInstance()->cancelCurrentAction(); - return true; - case JGE_BTN_OK: - GameObserver::GetInstance()->ButtonPressed(active); - return true; - break; - case JGE_BTN_LEFT: - active = closest(cards, limitor, active); - break; - case JGE_BTN_RIGHT: - active = closest(cards, limitor, active); - break; - case JGE_BTN_UP: - active = closest(cards, limitor, active); - break; - case JGE_BTN_DOWN: - active = closest(cards, limitor, active); - break; - case JGE_BTN_CANCEL: - mDrawMode = (mDrawMode+1) % DrawMode::kNumDrawModes; - if(mDrawMode == DrawMode::kText) - options[Options::DISABLECARDS].number = 1; - else - options[Options::DISABLECARDS].number = 0; - return true; - default: - return false; - } - if (active != oldactive) { - CardView::SelectorZone oldowner, owner; - if (CardView *q = dynamic_cast(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone; - if (CardView *q = dynamic_cast(active)) owner = q->owner; else owner = CardView::nullZone; - if (oldowner != owner) { - if (CardView::nullZone != owner) { - if (PlayGuiObject* old = fetchMemory(lasts[owner])) - switch (key) + if (!active) + { + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if ((NULL == limitor) || (limitor->select(*it))) { - case JGE_BTN_LEFT: if (old->x < oldactive->x) active = old; break; - case JGE_BTN_RIGHT: if (old->x > oldactive->x) active = old; break; - case JGE_BTN_UP: if (old->y < oldactive->y) active = old; break; - case JGE_BTN_DOWN: if (old->y > oldactive->y) active = old; break; - default: if (old) active = old; break; + active = *it; + active->Entering(); + return true; } - } - lasts[oldowner] = SelectorMemory(oldactive); + return true; } - } - else - { - // active card hasn't changed - that means we're probably at an edge of the battlefield. - // check if we're not already a selected avatar - if not, select one depending whether we're going up/down. - GuiAvatar* avatar = dynamic_cast(active); - if (!avatar) - { - if (key == JGE_BTN_DOWN) - { - active = duel->GetAvatars()->GetSelf(); - } - else if (key == JGE_BTN_UP) - { - active = duel->GetAvatars()->GetOpponent(); - } - } - } - if (active != oldactive) { - { CardView* c = dynamic_cast(oldactive); if (c) c->zoom = 1.0f; } - { CardView* c = dynamic_cast(active); if (c) c->zoom = 1.4f; } - if (oldactive) oldactive->Leaving(JGE_BTN_NONE); - if (active) active->Entering(); - } - return true; + Target* oldactive = active; + switch (key) + { + case JGE_BTN_SEC: + GameObserver::GetInstance()->cancelCurrentAction(); + return true; + case JGE_BTN_OK: + GameObserver::GetInstance()->ButtonPressed(active); + return true; + break; + case JGE_BTN_LEFT: + active = closest (cards, limitor, active); + break; + case JGE_BTN_RIGHT: + active = closest (cards, limitor, active); + break; + case JGE_BTN_UP: + active = closest (cards, limitor, active); + break; + case JGE_BTN_DOWN: + active = closest (cards, limitor, active); + break; + case JGE_BTN_CANCEL: + mDrawMode = (mDrawMode + 1) % DrawMode::kNumDrawModes; + if (mDrawMode == DrawMode::kText) + options[Options::DISABLECARDS].number = 1; + else + options[Options::DISABLECARDS].number = 0; + return true; + default: + return false; + } + if (active != oldactive) + { + CardView::SelectorZone oldowner, owner; + if (CardView *q = dynamic_cast(oldactive)) + oldowner = q->owner; + else + oldowner = CardView::nullZone; + if (CardView *q = dynamic_cast(active)) + owner = q->owner; + else + owner = CardView::nullZone; + if (oldowner != owner) + { + if (CardView::nullZone != owner) + { + if (PlayGuiObject* old = fetchMemory(lasts[owner])) + switch (key) + { + case JGE_BTN_LEFT: + if (old->x < oldactive->x) + active = old; + break; + case JGE_BTN_RIGHT: + if (old->x > oldactive->x) + active = old; + break; + case JGE_BTN_UP: + if (old->y < oldactive->y) + active = old; + break; + case JGE_BTN_DOWN: + if (old->y > oldactive->y) + active = old; + break; + default: + if (old) + active = old; + break; + } + } + lasts[oldowner] = SelectorMemory(oldactive); + } + } + else + { + // active card hasn't changed - that means we're probably at an edge of the battlefield. + // check if we're not already a selected avatar - if not, select one depending whether we're going up/down. + GuiAvatar* avatar = dynamic_cast (active); + if (!avatar) + { + if (key == JGE_BTN_DOWN) + { + active = duel->GetAvatars()->GetSelf(); + } + else if (key == JGE_BTN_UP) + { + active = duel->GetAvatars()->GetOpponent(); + } + } + } + if (active != oldactive) + { + { + CardView* c = dynamic_cast (oldactive); + if (c) + c->zoom = 1.0f; + } + { + CardView* c = dynamic_cast (active); + if (c) + c->zoom = 1.4f; + } + if (oldactive) + oldactive->Leaving(JGE_BTN_NONE); + if (active) + active->Entering(); + } + return true; } bool CardSelector::CheckUserInput(int x, int y) { - if (!active) { - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if ((NULL == limitor) || (limitor->select(*it))) { - active = *it; - active->Entering(); - return true; - } - return true; - } - Target* oldactive = active; - active = closest(cards, limitor, static_cast(x), static_cast(y)); - - if (active != oldactive) { - CardView::SelectorZone oldowner, owner; - if (CardView *q = dynamic_cast(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone; - if (CardView *q = dynamic_cast(active)) owner = q->owner; else owner = CardView::nullZone; - if (oldowner != owner) { - if (CardView::nullZone != owner) { - if (PlayGuiObject* old = fetchMemory(lasts[owner])) - if (old) active = old; - } - lasts[oldowner] = SelectorMemory(oldactive); - } - } - if (active != oldactive) { - { CardView* c = dynamic_cast(oldactive); if (c) c->zoom = 1.0f; } - { CardView* c = dynamic_cast(active); if (c) c->zoom = 1.4f; } - if (oldactive) oldactive->Leaving(JGE_BTN_NONE); - if (active) active->Entering(); - } - return true; -} - -void CardSelector::Update(float dt) { - float boundary = duel->RightBoundary(); - float position = boundary - CardGui::BigWidth / 2; - if (CardView* c = dynamic_cast(active)) - if ((c->x + CardGui::Width / 2 > position - CardGui::BigWidth / 2) && - (c->x - CardGui::Width / 2 < position + CardGui::BigWidth / 2)) - position = CardGui::BigWidth / 2 - 10; - if (position < CardGui::BigWidth / 2) position = CardGui::BigWidth / 2; - bigpos.x = position; - bigpos.Update(dt); -} - -void CardSelector::Render() { - if (active) { - active->Render(); - if (CardView* card = dynamic_cast(active)) + if (!active) { - card->DrawCard(bigpos, mDrawMode); + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if ((NULL == limitor) || (limitor->select(*it))) + { + active = *it; + active->Entering(); + return true; + } + return true; } - } -} + Target* oldactive = active; + active = closest (cards, limitor, static_cast (x), static_cast (y)); -void CardSelector::Limit(LimitorFunctor* limitor, CardView::SelectorZone destzone) { - this->limitor = limitor; - if (limitor && !limitor->select(active)) { - PlayGuiObject* oldactive = active; - CardView::SelectorZone oldowner; - if (CardView *q = dynamic_cast(oldactive)) oldowner = q->owner; else oldowner = CardView::nullZone; - if (oldowner != destzone) { - if (CardView::nullZone != destzone) - if (PlayGuiObject* old = fetchMemory(lasts[destzone])) - active = old; - lasts[oldowner] = SelectorMemory(oldactive); - } - - if (limitor && !limitor->select(active)) { - active = NULL; - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if (limitor->select(*it)) { - active = *it; - break; + if (active != oldactive) + { + CardView::SelectorZone oldowner, owner; + if (CardView *q = dynamic_cast(oldactive)) + oldowner = q->owner; + else + oldowner = CardView::nullZone; + if (CardView *q = dynamic_cast(active)) + owner = q->owner; + else + owner = CardView::nullZone; + if (oldowner != owner) + { + if (CardView::nullZone != owner) + { + if (PlayGuiObject* old = fetchMemory(lasts[owner])) + if (old) + active = old; + } + lasts[oldowner] = SelectorMemory(oldactive); } } - - if (active != oldactive) { - { CardView* c = dynamic_cast(oldactive); if (c) c->zoom = 1.0f; } - { CardView* c = dynamic_cast(active); if (c) c->zoom = 1.4f; } - if (oldactive) oldactive->Leaving(JGE_BTN_NONE); - if (active) active->Entering(); + if (active != oldactive) + { + { + CardView* c = dynamic_cast (oldactive); + if (c) + c->zoom = 1.0f; + } + { + CardView* c = dynamic_cast (active); + if (c) + c->zoom = 1.4f; + } + if (oldactive) + oldactive->Leaving(JGE_BTN_NONE); + if (active) + active->Entering(); } - } + return true; } -void CardSelector::PushLimitor() { - if (NULL == limitor) return; - CardView::SelectorZone owner; - if (CardView *q = dynamic_cast(active)) owner = q->owner; else owner = CardView::nullZone; - limitorStack.push(make_pair(limitor, owner)); +void CardSelector::Update(float dt) +{ + float boundary = duel->RightBoundary(); + float position = boundary - CardGui::BigWidth / 2; + if (CardView* c = dynamic_cast(active)) + if ((c->x + CardGui::Width / 2 > position - CardGui::BigWidth / 2) && (c->x - CardGui::Width / 2 < position + + CardGui::BigWidth / 2)) + position = CardGui::BigWidth / 2 - 10; + if (position < CardGui::BigWidth / 2) + position = CardGui::BigWidth / 2; + bigpos.x = position; + bigpos.Update(dt); } -void CardSelector::PopLimitor() { - if (limitorStack.empty()) return; - Limit(limitorStack.top().first, limitorStack.top().second); - limitorStack.pop(); +void CardSelector::Render() +{ + if (active) + { + active->Render(); + if (CardView* card = dynamic_cast(active)) + { + card->DrawCard(bigpos, mDrawMode); + } + } +} + +void CardSelector::Limit(LimitorFunctor* limitor, CardView::SelectorZone destzone) +{ + this->limitor = limitor; + if (limitor && !limitor->select(active)) + { + PlayGuiObject* oldactive = active; + CardView::SelectorZone oldowner; + if (CardView *q = dynamic_cast(oldactive)) + oldowner = q->owner; + else + oldowner = CardView::nullZone; + if (oldowner != destzone) + { + if (CardView::nullZone != destzone) + if (PlayGuiObject* old = fetchMemory(lasts[destzone])) + active = old; + lasts[oldowner] = SelectorMemory(oldactive); + } + + if (limitor && !limitor->select(active)) + { + active = NULL; + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if (limitor->select(*it)) + { + active = *it; + break; + } + } + + if (active != oldactive) + { + { + CardView* c = dynamic_cast (oldactive); + if (c) + c->zoom = 1.0f; + } + { + CardView* c = dynamic_cast (active); + if (c) + c->zoom = 1.4f; + } + if (oldactive) + oldactive->Leaving(JGE_BTN_NONE); + if (active) + active->Entering(); + } + } +} + +void CardSelector::PushLimitor() +{ + if (NULL == limitor) + return; + CardView::SelectorZone owner; + if (CardView *q = dynamic_cast(active)) + owner = q->owner; + else + owner = CardView::nullZone; + limitorStack.push(make_pair(limitor, owner)); +} + +void CardSelector::PopLimitor() +{ + if (limitorStack.empty()) + return; + Limit(limitorStack.top().first, limitorStack.top().second); + limitorStack.pop(); } diff --git a/projects/mtg/src/CardSelectorSingleton.cpp b/projects/mtg/src/CardSelectorSingleton.cpp index 2e31abcec..7d4e817b9 100644 --- a/projects/mtg/src/CardSelectorSingleton.cpp +++ b/projects/mtg/src/CardSelectorSingleton.cpp @@ -6,31 +6,31 @@ #include "Navigator.h" /* -** -*/ + ** + */ namespace CardSelectorSingleton { - static CardSelectorBase* sCardSelectorInstance = NULL; + static CardSelectorBase* sCardSelectorInstance = NULL; - CardSelectorBase* Create(DuelLayers* inDuelLayers) - { - if (sCardSelectorInstance == NULL) - sCardSelectorInstance = NEW CardSelector(inDuelLayers); - //sCardSelectorInstance = NEW Navigator(inDuelLayers); + CardSelectorBase* Create(DuelLayers* inDuelLayers) + { + if (sCardSelectorInstance == NULL) + sCardSelectorInstance = NEW CardSelector(inDuelLayers); + //sCardSelectorInstance = NEW Navigator(inDuelLayers); - return sCardSelectorInstance; - } + return sCardSelectorInstance; + } - CardSelectorBase* Instance() - { - assert(sCardSelectorInstance); - return sCardSelectorInstance; - } + CardSelectorBase* Instance() + { + assert(sCardSelectorInstance); + return sCardSelectorInstance; + } - void Terminate() - { - SAFE_DELETE(sCardSelectorInstance); - sCardSelectorInstance = NULL; - } + void Terminate() + { + SAFE_DELETE(sCardSelectorInstance); + sCardSelectorInstance = NULL; + } } diff --git a/projects/mtg/src/Closest.cpp b/projects/mtg/src/Closest.cpp index 36cd5b961..22f1e34e1 100644 --- a/projects/mtg/src/Closest.cpp +++ b/projects/mtg/src/Closest.cpp @@ -1,48 +1,53 @@ #ifndef _CLOSEST_H_ #define _CLOSEST_H_ -template +template static inline Target* closest(vector& cards, Limitor* limitor, Target* ref) { - Target* card = ref; - float curdist = 1000000.0f; // This is bigger than any possible distance - for (typename vector::iterator it = cards.begin(); it != cards.end(); ++it) + Target* card = ref; + float curdist = 1000000.0f; // This is bigger than any possible distance + for (typename vector::iterator it = cards.begin(); it != cards.end(); ++it) { - if (!T::test(ref, (*it))) continue; - if ((*it)->actA < 32) continue; - if ((NULL != limitor) && (!limitor->select(*it))) continue; - if (ref) + if (!T::test(ref, (*it))) + continue; + if ((*it)->actA < 32) + continue; + if ((NULL != limitor) && (!limitor->select(*it))) + continue; + if (ref) { - float dist = ((*it)->x - ref->x) * ((*it)->x - ref->x) + ((*it)->y - ref->y) * ((*it)->y - ref->y); - if (dist < curdist) + float dist = ((*it)->x - ref->x) * ((*it)->x - ref->x) + ((*it)->y - ref->y) * ((*it)->y - ref->y); + if (dist < curdist) { - curdist = dist; - card = *it; + curdist = dist; + card = *it; } } - else - card = *it; + else + card = *it; } - return card; + return card; } -template +template static inline Target* closest(vector& cards, Limitor* limitor, float x, float y) { - Target* card = NULL; - float curdist = 1000000.0f; // This is bigger than any possible distance - for (typename vector::iterator it = cards.begin(); it != cards.end(); ++it) + Target* card = NULL; + float curdist = 1000000.0f; // This is bigger than any possible distance + for (typename vector::iterator it = cards.begin(); it != cards.end(); ++it) { - if ((*it)->actA < 32) continue; - if ((NULL != limitor) && (!limitor->select(*it))) continue; - float dist = ((*it)->x - x) * ((*it)->x - x) + ((*it)->y - y) * ((*it)->y - y); - if (dist < curdist) + if ((*it)->actA < 32) + continue; + if ((NULL != limitor) && (!limitor->select(*it))) + continue; + float dist = ((*it)->x - x) * ((*it)->x - x) + ((*it)->y - y) * ((*it)->y - y); + if (dist < curdist) { - curdist = dist; - card = *it; + curdist = dist; + card = *it; } } - return card; + return card; } #endif diff --git a/projects/mtg/src/Counters.cpp b/projects/mtg/src/Counters.cpp index 2fe4c15a9..f98372251 100644 --- a/projects/mtg/src/Counters.cpp +++ b/projects/mtg/src/Counters.cpp @@ -3,129 +3,167 @@ #include "Counters.h" #include "MTGCardInstance.h" -Counter::Counter(MTGCardInstance * _target, int _power, int _toughness){ - init(_target,"",_power, _toughness); -} -Counter::Counter(MTGCardInstance * _target, const char * _name,int _power, int _toughness ){ - init(_target,_name,_power, _toughness); +Counter::Counter(MTGCardInstance * _target, int _power, int _toughness) +{ + init(_target, "", _power, _toughness); } -int Counter::init(MTGCardInstance * _target,const char * _name, int _power, int _toughness){ - target = _target; - name = _name; - power = _power; - toughness = _toughness; - nb = 1; - return 1; +Counter::Counter(MTGCardInstance * _target, const char * _name, int _power, int _toughness) +{ + init(_target, _name, _power, _toughness); } -bool Counter::sameAs(const char * _name, int _power, int _toughness){ - if (power == 0 && toughness == 0) return (name.compare(_name) == 0); - return (power == _power && toughness == _toughness); +int Counter::init(MTGCardInstance * _target, const char * _name, int _power, int _toughness) +{ + target = _target; + name = _name; + power = _power; + toughness = _toughness; + nb = 1; + return 1; } -bool Counter::cancels(int _power, int _toughness){ - if (power == 0 && toughness == 0) return false; - return (power == -_power && toughness == -_toughness); +bool Counter::sameAs(const char * _name, int _power, int _toughness) +{ + if (power == 0 && toughness == 0) + return (name.compare(_name) == 0); + return (power == _power && toughness == _toughness); } -int Counter::added(){ - if (power != 0 || toughness != 0){ - target->power+= power; - target->addToToughness(toughness); - } - return 1; +bool Counter::cancels(int _power, int _toughness) +{ + if (power == 0 && toughness == 0) + return false; + return (power == -_power && toughness == -_toughness); } -int Counter::removed(){ - if (power != 0 || toughness != 0){ - target->power-= power; - target->addToToughness(-toughness); - } - return 1; -} - - -Counters::Counters(MTGCardInstance * _target):target(_target){ - mCount = 0; -} -Counters::~Counters(){ - for (int i = 0; i < mCount; i++){ - SAFE_DELETE(counters[i]); - } -} - -int Counters::addCounter(const char * _name,int _power, int _toughness){ - for (int i = 0; i < mCount; i++){ - if (counters[i]->cancels( _power,_toughness) && counters[i]->nb > 0){ - counters[i]->removed(); - counters[i]->nb--; - return mCount; +int Counter::added() +{ + if (power != 0 || toughness != 0) + { + target->power += power; + target->addToToughness(toughness); } - } + return 1; +} - for (int i = 0; i < mCount; i++){ - if (counters[i]->sameAs(_name, _power,_toughness)){ - counters[i]->added(); - counters[i]->nb++; - return mCount; +int Counter::removed() +{ + if (power != 0 || toughness != 0) + { + target->power -= power; + target->addToToughness(-toughness); } - } - Counter * counter = NEW Counter(target,_name, _power, _toughness); - counters[mCount] = counter; - counter->added(); - mCount++; - return mCount; + return 1; } -int Counters::addCounter(int _power, int _toughness){ - return addCounter("",_power, _toughness); +Counters::Counters(MTGCardInstance * _target) : + target(_target) +{ + mCount = 0; } - -int Counters::init(){ - for (int i = mCount-1; i >= 0; i--){ - while (counters[i]->nb >= 1) { - counters[i]->removed(); - counters[i]->nb--; +Counters::~Counters() +{ + for (int i = 0; i < mCount; i++) + { + SAFE_DELETE(counters[i]); } - } - return 1; } -int Counters::removeCounter(const char * _name,int _power, int _toughness){ - for (int i = 0; i < mCount; i++){ - if (counters[i]->sameAs(_name, _power,_toughness)){ - if (counters[i]->nb < 1) return 0; - counters[i]->removed(); - counters[i]->nb--; - return mCount; +int Counters::addCounter(const char * _name, int _power, int _toughness) +{ + for (int i = 0; i < mCount; i++) + { + if (counters[i]->cancels(_power, _toughness) && counters[i]->nb > 0) + { + counters[i]->removed(); + counters[i]->nb--; + return mCount; + } } - } - return 0; -} -int Counters::removeCounter(int _power, int _toughness){ - return removeCounter("",_power, _toughness); -} - -Counter * Counters::hasCounter(const char * _name,int _power, int _toughness){ - for (int i = 0; i < mCount; i++){ - if (counters[i]->sameAs(_name, _power,_toughness)){ - if (counters[i]->nb > 0) return counters[i]; + for (int i = 0; i < mCount; i++) + { + if (counters[i]->sameAs(_name, _power, _toughness)) + { + counters[i]->added(); + counters[i]->nb++; + return mCount; + } } - } - return NULL; + Counter * counter = NEW Counter(target, _name, _power, _toughness); + counters[mCount] = counter; + counter->added(); + mCount++; + return mCount; } -Counter * Counters::hasCounter(int _power , int _toughness ){ - return hasCounter("",_power, _toughness); +int Counters::addCounter(int _power, int _toughness) +{ + return addCounter("", _power, _toughness); } -Counter * Counters::getNext(Counter * previous){ - int found = 0; - for (int i = 0; i < mCount ; i++){ - if (found && counters[i]->nb > 0) return counters[i]; - if (counters[i] == previous) found = 1; - } - return NULL; +int Counters::init() +{ + for (int i = mCount - 1; i >= 0; i--) + { + while (counters[i]->nb >= 1) + { + counters[i]->removed(); + counters[i]->nb--; + } + } + return 1; +} + +int Counters::removeCounter(const char * _name, int _power, int _toughness) +{ + for (int i = 0; i < mCount; i++) + { + if (counters[i]->sameAs(_name, _power, _toughness)) + { + if (counters[i]->nb < 1) + return 0; + counters[i]->removed(); + counters[i]->nb--; + return mCount; + } + } + return 0; +} + +int Counters::removeCounter(int _power, int _toughness) +{ + return removeCounter("", _power, _toughness); +} + +Counter * Counters::hasCounter(const char * _name, int _power, int _toughness) +{ + for (int i = 0; i < mCount; i++) + { + if (counters[i]->sameAs(_name, _power, _toughness)) + { + if (counters[i]->nb > 0) + return counters[i]; + } + } + return NULL; +} + +Counter * Counters::hasCounter(int _power, int _toughness) +{ + return hasCounter("", _power, _toughness); +} + +Counter * Counters::getNext(Counter * previous) +{ + int found = 0; + for (int i = 0; i < mCount; i++) + { + if (found && counters[i]->nb > 0) + return counters[i]; + if (counters[i] == previous) + found = 1; + } + return NULL; } diff --git a/projects/mtg/src/Credits.cpp b/projects/mtg/src/Credits.cpp index 8ed1a2035..8fe9baf0c 100644 --- a/projects/mtg/src/Credits.cpp +++ b/projects/mtg/src/Credits.cpp @@ -11,343 +11,416 @@ #include "GameStateShop.h" #include "PlayerData.h" - CreditBonus::CreditBonus(int _value, string _text){ +CreditBonus::CreditBonus(int _value, string _text) +{ value = _value; text = _text; - } +} - - void CreditBonus::Render(float x, float y, WFont * font){ +void CreditBonus::Render(float x, float y, WFont * font) +{ char buffer[512]; sprintf(buffer, "%s: %i", text.c_str(), value); - font->DrawString(buffer,x,y); - } + font->DrawString(buffer, x, y); +} - Credits::Credits(){ +Credits::Credits() +{ unlockedTex = NULL; unlockedQuad = NULL; unlocked = -1; p1 = NULL; p2 = NULL; - } +} - Credits::~Credits(){ +Credits::~Credits() +{ resources.Release(unlockedTex); - for (unsigned int i = 0; iturn) return; - PlayerData * playerdata = NEW PlayerData(app->collection); - if (!p1->isAI() && p2->isAI() && p1!= g->gameOver){ - gameLength = time(0) - g->startedAt; - value = 400; - if (app->gameType != GAME_TYPE_CLASSIC) value = 200; - int difficulty = options[Options::DIFFICULTY].number; - if (options[Options::DIFFICULTY_MODE_UNLOCKED].number && difficulty) { - CreditBonus * b = NEW CreditBonus(100*difficulty, _("Difficulty Bonus")); - bonus.push_back(b); - } - - if (p1->life == 1) { - CreditBonus * b = NEW CreditBonus(111, _("'Live dangerously and you live right' Bonus")); - bonus.push_back(b); - } - - int diff = p1->life - p2->life; - if (diff < 0) diff = 0; - if (diff > 500) diff = 500; - if (diff){ - CreditBonus * b = NEW CreditBonus(diff, _("Life Delta Bonus")); - bonus.push_back(b); - } - - if (p1->game->library->nb_cards == 0) { - CreditBonus * b = NEW CreditBonus(391, _("'Decree of Theophilus' Bonus")); - bonus.push_back(b); - } - - if ((p2->game->library->nb_cards == 0) && p1->game->library->nb_cards) { - CreditBonus * b = NEW CreditBonus(p1->game->library->nb_cards * 3, _("Miller Bonus")); - bonus.push_back(b); - } - - if (g->turn < 15) { - CreditBonus * b = NEW CreditBonus((20 - g->turn)*17, _("'Fast and Furious' Bonus")); - bonus.push_back(b); - } - - GameOptionAward * goa = NULL; - // - vector finishedTasks; - playerdata->taskList->getDoneTasks(_p1, _p2, _app, &finishedTasks); - - char buffer[512]; - - for (vector::iterator it = finishedTasks.begin(); it!=finishedTasks.end(); it++) { - sprintf(buffer, _("Task: %s").c_str(), (*it)->getShortDesc().c_str()); - CreditBonus * b = NEW CreditBonus((*it)->getReward(), buffer); - bonus.push_back(b); - playerdata->taskList->removeTask(*it); - } - // - - if (unlocked == -1){ - unlocked = isDifficultyUnlocked(); - if (unlocked){ - unlockedTex = resources.RetrieveTexture("unlocked.png"); - unlockedQuad = resources.RetrieveQuad("unlocked.png", 2, 2, 396, 96); - goa = (GameOptionAward*) &options[Options::DIFFICULTY_MODE_UNLOCKED]; - goa->giveAward(); - options.save(); - } else if ((unlocked = isMomirUnlocked())) { - unlockedTex = resources.RetrieveTexture("momir_unlocked.png"); - unlockedQuad = resources.RetrieveQuad("momir_unlocked.png", 2, 2, 396, 96); - goa = (GameOptionAward*) &options[Options::MOMIR_MODE_UNLOCKED]; - goa->giveAward(); - options.save(); - } else if ((unlocked = isEvilTwinUnlocked())) { - unlockedTex = resources.RetrieveTexture("eviltwin_unlocked.png"); - unlockedQuad = resources.RetrieveQuad("eviltwin_unlocked.png", 2, 2, 396, 96); - goa = (GameOptionAward*) &options[Options::EVILTWIN_MODE_UNLOCKED]; - goa->giveAward(); - options.save(); - }else if((unlocked = isRandomDeckUnlocked())) { - unlockedTex = resources.RetrieveTexture("randomdeck_unlocked.png"); - unlockedQuad = resources.RetrieveQuad("randomdeck_unlocked.png", 2, 2, 396, 96); - goa = (GameOptionAward*) &options[Options::RANDOMDECK_MODE_UNLOCKED]; - goa->giveAward(); - options.save(); - }else if((unlocked = unlockRandomSet())) { - unlockedTex = resources.RetrieveTexture("set_unlocked.png"); - unlockedQuad = resources.RetrieveQuad("set_unlocked.png", 2, 2, 396, 96); - MTGSetInfo * si = setlist.getInfo(unlocked - 1); - if(si) unlockedString = si->getName(); //Show the set's pretty name for unlocks. - } - - if (unlocked && options[Options::SFXVOLUME].number > 0){ - JSample * sample = resources.RetrieveSample("bonus.wav"); - if (sample){ - JSoundSystem::GetInstance()->PlaySample(sample); +void Credits::compute(Player * _p1, Player * _p2, GameApp * _app) +{ + p1 = _p1; + p2 = _p2; + app = _app; + showMsg = (WRand() % 3); + GameObserver * g = GameObserver::GetInstance(); + if (!g->turn) + return; + PlayerData * playerdata = NEW PlayerData(app->collection); + if (!p1->isAI() && p2->isAI() && p1 != g->gameOver) + { + gameLength = time(0) - g->startedAt; + value = 400; + if (app->gameType != GAME_TYPE_CLASSIC) + value = 200; + int difficulty = options[Options::DIFFICULTY].number; + if (options[Options::DIFFICULTY_MODE_UNLOCKED].number && difficulty) + { + CreditBonus * b = NEW CreditBonus(100 * difficulty, _("Difficulty Bonus")); + bonus.push_back(b); + } + + if (p1->life == 1) + { + CreditBonus * b = NEW CreditBonus(111, _("'Live dangerously and you live right' Bonus")); + bonus.push_back(b); + } + + int diff = p1->life - p2->life; + if (diff < 0) + diff = 0; + if (diff > 500) + diff = 500; + if (diff) + { + CreditBonus * b = NEW CreditBonus(diff, _("Life Delta Bonus")); + bonus.push_back(b); + } + + if (p1->game->library->nb_cards == 0) + { + CreditBonus * b = NEW CreditBonus(391, _("'Decree of Theophilus' Bonus")); + bonus.push_back(b); + } + + if ((p2->game->library->nb_cards == 0) && p1->game->library->nb_cards) + { + CreditBonus * b = NEW CreditBonus(p1->game->library->nb_cards * 3, _("Miller Bonus")); + bonus.push_back(b); + } + + if (g->turn < 15) + { + CreditBonus * b = NEW CreditBonus((20 - g->turn) * 17, _("'Fast and Furious' Bonus")); + bonus.push_back(b); + } + + GameOptionAward * goa = NULL; + // + vector finishedTasks; + playerdata->taskList->getDoneTasks(_p1, _p2, _app, &finishedTasks); + + char buffer[512]; + + for (vector::iterator it = finishedTasks.begin(); it != finishedTasks.end(); it++) + { + sprintf(buffer, _("Task: %s").c_str(), (*it)->getShortDesc().c_str()); + CreditBonus * b = NEW CreditBonus((*it)->getReward(), buffer); + bonus.push_back(b); + playerdata->taskList->removeTask(*it); + } + // + + if (unlocked == -1) + { + unlocked = isDifficultyUnlocked(); + if (unlocked) + { + unlockedTex = resources.RetrieveTexture("unlocked.png"); + unlockedQuad = resources.RetrieveQuad("unlocked.png", 2, 2, 396, 96); + goa = (GameOptionAward*) &options[Options::DIFFICULTY_MODE_UNLOCKED]; + goa->giveAward(); + options.save(); + } + else if ((unlocked = isMomirUnlocked())) + { + unlockedTex = resources.RetrieveTexture("momir_unlocked.png"); + unlockedQuad = resources.RetrieveQuad("momir_unlocked.png", 2, 2, 396, 96); + goa = (GameOptionAward*) &options[Options::MOMIR_MODE_UNLOCKED]; + goa->giveAward(); + options.save(); + } + else if ((unlocked = isEvilTwinUnlocked())) + { + unlockedTex = resources.RetrieveTexture("eviltwin_unlocked.png"); + unlockedQuad = resources.RetrieveQuad("eviltwin_unlocked.png", 2, 2, 396, 96); + goa = (GameOptionAward*) &options[Options::EVILTWIN_MODE_UNLOCKED]; + goa->giveAward(); + options.save(); + } + else if ((unlocked = isRandomDeckUnlocked())) + { + unlockedTex = resources.RetrieveTexture("randomdeck_unlocked.png"); + unlockedQuad = resources.RetrieveQuad("randomdeck_unlocked.png", 2, 2, 396, 96); + goa = (GameOptionAward*) &options[Options::RANDOMDECK_MODE_UNLOCKED]; + goa->giveAward(); + options.save(); + } + else if ((unlocked = unlockRandomSet())) + { + unlockedTex = resources.RetrieveTexture("set_unlocked.png"); + unlockedQuad = resources.RetrieveQuad("set_unlocked.png", 2, 2, 396, 96); + MTGSetInfo * si = setlist.getInfo(unlocked - 1); + if (si) + unlockedString = si->getName(); //Show the set's pretty name for unlocks. + } + + if (unlocked && options[Options::SFXVOLUME].number > 0) + { + JSample * sample = resources.RetrieveSample("bonus.wav"); + if (sample) + { + JSoundSystem::GetInstance()->PlaySample(sample); + } + } + + } + + vector::iterator it; + if (bonus.size()) + { + CreditBonus * b = NEW CreditBonus(value, _("Victory")); + bonus.insert(bonus.begin(), b); + for (it = bonus.begin() + 1; it < bonus.end(); ++it) + value += (*it)->value; + } + + playerdata->credits += value; + PriceList::updateKey(); + playerdata->taskList->passOneDay(); + if (playerdata->taskList->getTaskCount() < 6) + { + playerdata->taskList->addRandomTask(); + playerdata->taskList->addRandomTask(); } - } } + else + { + unlocked = 0; + playerdata->taskList->passOneDay(); + } + playerdata->save(); + SAFE_DELETE(playerdata); +} + +void Credits::Render() +{ + if (!p1) + return; + GameObserver * g = GameObserver::GetInstance(); + JRenderer * r = JRenderer::GetInstance(); + WFont * f = resources.GetWFont(Fonts::MAIN_FONT); + WFont * f2 = resources.GetWFont(Fonts::MENU_FONT); + WFont * f3 = resources.GetWFont(Fonts::MAGIC_FONT); + f->SetScale(1); + f->SetColor(ARGB(255,255,255,255)); + f2->SetScale(1); + f2->SetColor(ARGB(255,255,255,255)); + f3->SetScale(1); + f3->SetColor(ARGB(255,255,255,255)); + char buffer[512]; + if (!g->turn) + { + sprintf(buffer, "%s", _("Please check your deck (not enough cards?)").c_str()); + } + else + { + if (!p1->isAI() && p2->isAI()) + { + if (g->gameOver != p1) + { + sprintf(buffer, _("Congratulations! You earn %i credits").c_str(), value); + if (unlockedQuad) + { + showMsg = 0; + r->RenderQuad(unlockedQuad, 20, 20); + } + if (unlockedString.size()) + { + f2->DrawString(unlockedString.c_str(), SCREEN_WIDTH / 2, 80, JGETEXT_CENTER); + } + } + else + { + sprintf(buffer, "%s", _("You have been defeated").c_str()); + } + } + else + { + int winner = 2; + if (g->gameOver != p1) + { + winner = 1; + } + int p0life = p1->life; + sprintf(buffer, _("Player %i wins (%i)").c_str(), winner, p0life); + } + } + + float y = 130; + + if (showMsg == 1) + y = 50; vector::iterator it; - if (bonus.size()){ - CreditBonus * b = NEW CreditBonus(value, _("Victory")); - bonus.insert(bonus.begin(),b); - for (it = bonus.begin() + 1; it < bonus.end(); ++it) - value += (*it)->value; + for (it = bonus.begin(); it < bonus.end(); ++it) + { + (*it)->Render(10, y, f3); + y += 12; + } + f2->DrawString(buffer, 10, y); + y += 15; + + //!! + if (g->gameOver != p1) + { + sprintf(buffer, _("Game length: %i turns (%i seconds)").c_str(), g->turn, this->gameLength); + f->DrawString(buffer, 10, y); + y += 10; + sprintf(buffer, _("Credits per minute: %i").c_str(), (int) (60 * value / this->gameLength)); + f->DrawString(buffer, 10, y); + y += 10; + showMsg = 0; } + if (showMsg == 1) + { + f2->DrawString(_("Please support this project!").c_str(), 10, y + 15); + f->DrawString(_("Wagic is free, open source, and developed on the little free time I have").c_str(), 10, y + 30); + f->DrawString(_("If you enjoy this game, please consider donating a few bucks").c_str(), 10, y + 42); + f->DrawString(_("(Seriously, donate or I'll kill this cute little bunny)").c_str(), 10, y + 54); + f->DrawString(_("Thanks in advance for your support.").c_str(), 10, y + 66); + f2->DrawString("-> http://wololo.net/wagic", 10, y + 78); + } +} +int Credits::isDifficultyUnlocked() +{ + if (options[Options::DIFFICULTY_MODE_UNLOCKED].number) + return 0; + int nbAIDecks = 0; + int found = 1; + int wins = 0; + DeckStats * stats = DeckStats::GetInstance(); + stats->load(p1); + while (found) + { + found = 0; + char buffer[512]; + char aiSmallDeckName[512]; + sprintf(buffer, JGE_GET_RES("ai/baka/deck%i.txt").c_str(), nbAIDecks + 1); + if (fileExists(buffer)) + { + found = 1; + nbAIDecks++; + sprintf(aiSmallDeckName, "ai_baka_deck%i", nbAIDecks); + int percentVictories = stats->percentVictories(string(aiSmallDeckName)); + if (percentVictories >= 67) + wins++; + if (wins >= 10) + return 1; + } + } + return 0; +} + +int Credits::isMomirUnlocked() +{ + if (options[Options::MOMIR_MODE_UNLOCKED].number) + return 0; + if (p1->game->inPlay->countByType("land") == 8) + return 1; + return 0; +} + +int Credits::isEvilTwinUnlocked() +{ + if (options[Options::EVILTWIN_MODE_UNLOCKED].number) + return 0; + if (p1->game->inPlay->nb_cards && (p1->game->inPlay->nb_cards == p2->game->inPlay->nb_cards)) + return 1; + return 0; +} + +int Credits::isRandomDeckUnlocked() +{ + if (0 == options[Options::DIFFICULTY].number) + return 0; + if (options[Options::RANDOMDECK_MODE_UNLOCKED].number) + return 0; + if (p1->life >= 20) + return 1; + return 0; +} + +int Credits::addCreditBonus(int value) +{ + PlayerData * playerdata = NEW PlayerData(); playerdata->credits += value; - PriceList::updateKey(); - playerdata->taskList->passOneDay(); - if (playerdata->taskList->getTaskCount() < 6) { - playerdata->taskList->addRandomTask(); - playerdata->taskList->addRandomTask(); - } - - }else{ - unlocked = 0; - playerdata->taskList->passOneDay(); - } - - playerdata->save(); - SAFE_DELETE(playerdata); -} - -void Credits::Render(){ - if (!p1) return; - GameObserver * g = GameObserver::GetInstance(); - JRenderer * r = JRenderer::GetInstance(); - WFont * f = resources.GetWFont(Fonts::MAIN_FONT); - WFont * f2 = resources.GetWFont(Fonts::MENU_FONT); - WFont * f3 = resources.GetWFont(Fonts::MAGIC_FONT); - f->SetScale(1); - f->SetColor(ARGB(255,255,255,255)); - f2->SetScale(1); - f2->SetColor(ARGB(255,255,255,255)); - f3->SetScale(1); - f3->SetColor(ARGB(255,255,255,255)); - char buffer[512]; - if (!g->turn){ - sprintf(buffer, "%s", _("Please check your deck (not enough cards?)").c_str() ); - }else{ - if (!p1->isAI() && p2->isAI() ){ - if (g->gameOver != p1){ - sprintf (buffer, _("Congratulations! You earn %i credits").c_str(), value); - if (unlockedQuad){ - showMsg = 0; - r->RenderQuad(unlockedQuad, 20, 20); - } - if(unlockedString.size()){ - f2->DrawString(unlockedString.c_str(),SCREEN_WIDTH/2, 80,JGETEXT_CENTER); - } - }else{ - sprintf (buffer, "%s", _("You have been defeated").c_str()); - } - }else{ - int winner = 2; - if (g->gameOver !=p1){ - winner = 1; - } - int p0life = p1->life; - sprintf(buffer, _("Player %i wins (%i)").c_str(), winner, p0life ); - } - } - - float y = 130; - - if (showMsg == 1) y = 50; - vector:: iterator it; - for ( it=bonus.begin() ; it < bonus.end(); ++it){ - (*it)->Render(10,y,f3); - y+=12; - } - f2->DrawString(buffer, 10, y); - y+=15; - - //!! - if (g->gameOver != p1) { - sprintf(buffer, _("Game length: %i turns (%i seconds)").c_str(), g->turn, this->gameLength); - f->DrawString(buffer, 10, y); - y += 10; - sprintf(buffer, _("Credits per minute: %i").c_str(), (int)(60*value/this->gameLength)); - f->DrawString(buffer, 10, y); - y += 10; - showMsg = 0; - } - - if (showMsg == 1){ - f2->DrawString(_("Please support this project!").c_str() ,10,y+15); - f->DrawString(_("Wagic is free, open source, and developed on the little free time I have").c_str() ,10,y+30); - f->DrawString(_("If you enjoy this game, please consider donating a few bucks").c_str() ,10,y+42); - f->DrawString(_("(Seriously, donate or I'll kill this cute little bunny)").c_str() ,10,y+54); - f->DrawString(_("Thanks in advance for your support.").c_str() ,10,y+66); - f2->DrawString("-> http://wololo.net/wagic" ,10,y+78); - } - -} - - -int Credits::isDifficultyUnlocked(){ - if (options[Options::DIFFICULTY_MODE_UNLOCKED].number) return 0; - int nbAIDecks = 0; - int found = 1; - int wins = 0; - DeckStats * stats = DeckStats::GetInstance(); - stats->load(p1); - while (found){ - found = 0; - char buffer[512]; - char aiSmallDeckName[512]; - sprintf(buffer, JGE_GET_RES("ai/baka/deck%i.txt").c_str(),nbAIDecks+1); - if(fileExists(buffer)){ - found = 1; - nbAIDecks++; - sprintf(aiSmallDeckName, "ai_baka_deck%i",nbAIDecks); - int percentVictories = stats->percentVictories(string(aiSmallDeckName)); - if (percentVictories >=67) wins++; - if (wins >= 10) return 1; - } - } - return 0; -} - -int Credits::isMomirUnlocked(){ - if (options[Options::MOMIR_MODE_UNLOCKED].number) return 0; - if (p1->game->inPlay->countByType("land") == 8) return 1; - return 0; -} - -int Credits::isEvilTwinUnlocked(){ - if (options[Options::EVILTWIN_MODE_UNLOCKED].number) return 0; - if (p1->game->inPlay->nb_cards && (p1->game->inPlay->nb_cards == p2->game->inPlay->nb_cards)) return 1; - return 0; -} - -int Credits::isRandomDeckUnlocked(){ - if (0 == options[Options::DIFFICULTY].number) return 0; - if (options[Options::RANDOMDECK_MODE_UNLOCKED].number) return 0; - if (p1->life >= 20 ) return 1; - return 0; -} - -int Credits::addCreditBonus(int value){ - PlayerData * playerdata = NEW PlayerData(); - playerdata->credits += value; - playerdata->save(); - SAFE_DELETE(playerdata); - return value; + playerdata->save(); + SAFE_DELETE(playerdata); + return value; } /* * adds a Card to a deck * @param cardId id of the card * @param collection deck representing player's collection -*/ -int Credits::addCardToCollection(int cardId, MTGDeck * collection) { - return collection->add(cardId); + */ +int Credits::addCardToCollection(int cardId, MTGDeck * collection) +{ + return collection->add(cardId); } /* * adds a Card to player's collection * prefer to call the above function if you want to add several cards, since saving is expensive */ -int Credits::addCardToCollection(int cardId) { - MTGAllCards * ac = GameApp::collection; - PlayerData * playerdata = NEW PlayerData(ac); - int result = addCardToCollection(cardId, playerdata->collection); - playerdata->collection->save(); - return result; +int Credits::addCardToCollection(int cardId) +{ + MTGAllCards * ac = GameApp::collection; + PlayerData * playerdata = NEW PlayerData(ac); + int result = addCardToCollection(cardId, playerdata->collection); + playerdata->collection->save(); + return result; } -int Credits::unlockSetByName(string name){ - int setId = setlist.findSet(name); - if (setId < 0) return 0; +int Credits::unlockSetByName(string name) +{ + int setId = setlist.findSet(name); + if (setId < 0) + return 0; + + GameOptionAward* goa = (GameOptionAward*) &options[Options::optionSet(setId)]; + goa->giveAward(); + options.save(); + return setId + 1; //We add 1 here to show success/failure. Be sure to subtract later. - GameOptionAward* goa = (GameOptionAward*) &options[Options::optionSet(setId)]; - goa->giveAward(); - options.save(); - return setId + 1; //We add 1 here to show success/failure. Be sure to subtract later. - } -int Credits::unlockRandomSet(bool force){ - int setId = WRand() % setlist.size(); +int Credits::unlockRandomSet(bool force) +{ + int setId = WRand() % setlist.size(); - if (force) { - int init = setId; - bool found = false; - do { - if (1 != options[Options::optionSet(setId)].number) - found = true; - else { - setId++; - if (setId == setlist.size()) - setId = 0; - } - } while (setId != init && !found); - } + if (force) + { + int init = setId; + bool found = false; + do + { + if (1 != options[Options::optionSet(setId)].number) + found = true; + else + { + setId++; + if (setId == setlist.size()) + setId = 0; + } + } while (setId != init && !found); + } - if (1 == options[Options::optionSet(setId)].number) - return 0; + if (1 == options[Options::optionSet(setId)].number) + return 0; - GameOptionAward* goa = (GameOptionAward*) &options[Options::optionSet(setId)]; - goa->giveAward(); - options.save(); - return setId + 1; //We add 1 here to show success/failure. Be sure to subtract later. + GameOptionAward* goa = (GameOptionAward*) &options[Options::optionSet(setId)]; + goa->giveAward(); + options.save(); + return setId + 1; //We add 1 here to show success/failure. Be sure to subtract later. } diff --git a/projects/mtg/src/Damage.cpp b/projects/mtg/src/Damage.cpp index 55cf74f5e..893d22e59 100644 --- a/projects/mtg/src/Damage.cpp +++ b/projects/mtg/src/Damage.cpp @@ -8,215 +8,266 @@ #include "WResourceManager.h" #include "GameObserver.h" -Damage::Damage(MTGCardInstance * source, Damageable * target) { - init(source, target, source->getPower(), DAMAGE_OTHER); +Damage::Damage(MTGCardInstance * source, Damageable * target) +{ + init(source, target, source->getPower(), DAMAGE_OTHER); } -Damage::Damage(MTGCardInstance * source, Damageable * target, int damage,int _typeOfDamage) { - init(source, target, damage, _typeOfDamage); +Damage::Damage(MTGCardInstance * source, Damageable * target, int damage, int _typeOfDamage) +{ + init(source, target, damage, _typeOfDamage); } -void Damage::init(MTGCardInstance * _source, Damageable * _target, int _damage, int _typeOfDamage){ - typeOfDamage = _typeOfDamage; - target = _target; - source = _source; +void Damage::init(MTGCardInstance * _source, Damageable * _target, int _damage, int _typeOfDamage) +{ + typeOfDamage = _typeOfDamage; + target = _target; + source = _source; - - if (_damage < 0) _damage = 0; //Negative damages cannot happen - damage = _damage; - mHeight = 40; - type = ACTION_DAMAGE; + if (_damage < 0) + _damage = 0; //Negative damages cannot happen + damage = _damage; + mHeight = 40; + type = ACTION_DAMAGE; } -int Damage::resolve(){ - if (damage <0) damage = 0; //Negative damages cannot happen - state = RESOLVED_OK; - GameObserver * g = GameObserver::GetInstance(); - WEvent * e = NEW WEventDamage(this); - //Replacement Effects - e = g->replacementEffects->replace(e); - if (!e) return 0; - WEventDamage * ev = dynamic_cast(e); - if (!ev) { - g->receiveEvent(e); - return 0; - } - damage = ev->damage->damage; - target = ev->damage->target; - if (!damage) return 0; - -//asorbing effects for cards controller----------- - -//reserved for culmulitive absorb ability coding - - //prevent next damage----------------------------- - if((target)->preventable >= 1) { - int preventing =(target)->preventable; - for(int k = preventing; k > 0;k--){ - //the following keeps preventable from ADDING toughness/life if damage was less then preventable amount. - for (int i = damage; i >= 1; i--){ - (target)->preventable -= 1; - damage -= 1; - break;//does the redux of damage 1 time, breaks the loop to deincrement preventing and start the loop over. - } - } - } - - //set prevent next damage back to 0 if it is equal to less then 0 - if((target)->preventable < 0){ - (target)->preventable = 0; - } - - //------------------------------------------------- - if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){ - MTGCardInstance * _target = (MTGCardInstance *)target; - if ((_target)->protectedAgainst(source)) damage = 0; - //rulings = 10/4/2004 The damage prevention ability works even if it has no counters, as long as some effect keeps its toughness above zero. - //these creature are essentially immune to damage. however 0/-1 effects applied through lords or counters can kill them. - if ((_target)->has(Constants::PHANTOM)) { - damage = 0; - (_target)->counters->removeCounter(1,1); +int Damage::resolve() +{ + if (damage < 0) + damage = 0; //Negative damages cannot happen + state = RESOLVED_OK; + GameObserver * g = GameObserver::GetInstance(); + WEvent * e = NEW WEventDamage(this); + //Replacement Effects + e = g->replacementEffects->replace(e); + if (!e) + return 0; + WEventDamage * ev = dynamic_cast (e); + if (!ev) + { + g->receiveEvent(e); + return 0; } - if ((_target)->has(Constants::ABSORB)) { - damage -= 1; - } - if ((_target)->has(Constants::WILTING)) { - for (int j = damage; j > 0; j--){ - (_target)->counters->addCounter(-1,-1); - } - damage = 0; - } - if ((_target)->has(Constants::VIGOR)){ - for (int j = damage; j > 0; j--){ - (_target)->counters->addCounter(1,1); - } - damage = 0; - } - if (!damage){ - state = RESOLVED_NOK; - delete (e); - return 0; - } - _target->doDamageTest = 1; - } - - int a = damage; + damage = ev->damage->damage; + target = ev->damage->target; + if (!damage) + return 0; - if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE && - (source->has(Constants::WITHER) || source->has(Constants::INFECT))){ - // Damage for WITHER or poison on creatures. This should probably go in replacement effects - MTGCardInstance * _target = (MTGCardInstance *)target; - for (int i = 0; i < damage; i++){ - _target->counters->addCounter(-1, -1); + //asorbing effects for cards controller----------- + + //reserved for culmulitive absorb ability coding + + //prevent next damage----------------------------- + if ((target)->preventable >= 1) + { + int preventing = (target)->preventable; + for (int k = preventing; k > 0; k--) + { + //the following keeps preventable from ADDING toughness/life if damage was less then preventable amount. + for (int i = damage; i >= 1; i--) + { + (target)->preventable -= 1; + damage -= 1; + break;//does the redux of damage 1 time, breaks the loop to deincrement preventing and start the loop over. + } + } } - } else if (target->type_as_damageable == DAMAGEABLE_PLAYER && source->has(Constants::INFECT)) { - // Poison on player - Player * _target = (Player *)target; - _target->poisonCount += damage;//this will be changed to poison counters. - } else if (target->type_as_damageable == DAMAGEABLE_PLAYER && - ( source->has(Constants::POISONTOXIC) || source->has(Constants::POISONTWOTOXIC) || source->has(Constants::POISONTHREETOXIC) )) { - //Damage + 1, 2, or 3 poison counters on player - Player * _target = (Player *)target; - a = target->dealDamage(damage); - target->damageCount += damage; - if (source->has(Constants::POISONTOXIC)) { - _target->poisonCount += 1; - }else if (source->has(Constants::POISONTWOTOXIC)) { - _target->poisonCount += 2; - } else { - _target->poisonCount += 3; + //set prevent next damage back to 0 if it is equal to less then 0 + if ((target)->preventable < 0) + { + (target)->preventable = 0; } - } else { - // "Normal" case, - //return the left over amount after effects have been applied to them. - a = target->dealDamage(damage); - target->damageCount += 1; - } - - //Send (Damage/Replaced effect) event to listeners - g->receiveEvent(e); - return a; -} -void Damage::Render(){ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetBase(0); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - char buffer[200]; - sprintf(buffer, _("Deals %i damage to").c_str(), damage); - mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT); - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * quad = resources.RetrieveCard(source,CACHE_THUMB); - if (quad){ - float scale = 30 / quad->mHeight; - renderer->RenderQuad(quad, x , y , 0,scale,scale); - }else{ - mFont->DrawString(_(source->getName()).c_str(),x,y-15); - } - quad = target->getIcon(); - if (quad){ - float scale = 30 / quad->mHeight; - renderer->RenderQuad(quad, x + 150 , y , 0,scale,scale); - }else{ + //------------------------------------------------- if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) - mFont->DrawString(_(((MTGCardInstance *)target)->getName()).c_str(),x+120,y); - } + { + MTGCardInstance * _target = (MTGCardInstance *) target; + if ((_target)->protectedAgainst(source)) + damage = 0; + //rulings = 10/4/2004 The damage prevention ability works even if it has no counters, as long as some effect keeps its toughness above zero. + //these creature are essentially immune to damage. however 0/-1 effects applied through lords or counters can kill them. + if ((_target)->has(Constants::PHANTOM)) + { + damage = 0; + (_target)->counters->removeCounter(1, 1); + } + if ((_target)->has(Constants::ABSORB)) + { + damage -= 1; + } + if ((_target)->has(Constants::WILTING)) + { + for (int j = damage; j > 0; j--) + { + (_target)->counters->addCounter(-1, -1); + } + damage = 0; + } + if ((_target)->has(Constants::VIGOR)) + { + for (int j = damage; j > 0; j--) + { + (_target)->counters->addCounter(1, 1); + } + damage = 0; + } + if (!damage) + { + state = RESOLVED_NOK; + delete (e); + return 0; + } + _target->doDamageTest = 1; + } + + int a = damage; + + if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE && (source->has(Constants::WITHER) || source->has( + Constants::INFECT))) + { + // Damage for WITHER or poison on creatures. This should probably go in replacement effects + MTGCardInstance * _target = (MTGCardInstance *) target; + for (int i = 0; i < damage; i++) + { + _target->counters->addCounter(-1, -1); + } + + } + else if (target->type_as_damageable == DAMAGEABLE_PLAYER && source->has(Constants::INFECT)) + { + // Poison on player + Player * _target = (Player *) target; + _target->poisonCount += damage;//this will be changed to poison counters. + } + else if (target->type_as_damageable == DAMAGEABLE_PLAYER && (source->has(Constants::POISONTOXIC) || + source->has(Constants::POISONTWOTOXIC) || source->has(Constants::POISONTHREETOXIC))) + { + //Damage + 1, 2, or 3 poison counters on player + Player * _target = (Player *) target; + a = target->dealDamage(damage); + target->damageCount += damage; + if (source->has(Constants::POISONTOXIC)) + { + _target->poisonCount += 1; + } + else if (source->has(Constants::POISONTWOTOXIC)) + { + _target->poisonCount += 2; + } + else + { + _target->poisonCount += 3; + } + + } + else + { + // "Normal" case, + //return the left over amount after effects have been applied to them. + a = target->dealDamage(damage); + target->damageCount += 1; + } + + //Send (Damage/Replaced effect) event to listeners + g->receiveEvent(e); + return a; +} +void Damage::Render() +{ + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetBase(0); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + char buffer[200]; + sprintf(buffer, _("Deals %i damage to").c_str(), damage); + mFont->DrawString(buffer, x + 20, y, JGETEXT_LEFT); + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * quad = resources.RetrieveCard(source, CACHE_THUMB); + if (quad) + { + float scale = 30 / quad->mHeight; + renderer->RenderQuad(quad, x, y, 0, scale, scale); + } + else + { + mFont->DrawString(_(source->getName()).c_str(), x, y - 15); + } + quad = target->getIcon(); + if (quad) + { + float scale = 30 / quad->mHeight; + renderer->RenderQuad(quad, x + 150, y, 0, scale, scale); + } + else + { + if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE) + mFont->DrawString(_(((MTGCardInstance *) target)->getName()).c_str(), x + 120, y); + } } ostream& Damage::toString(ostream& out) const { - out << "Damage ::: target : " << target << " ; damage " << damage; - return out; + out << "Damage ::: target : " << target << " ; damage " << damage; + return out; } -DamageStack::DamageStack() { - currentState = -1; - type = ACTION_DAMAGES; +DamageStack::DamageStack() +{ + currentState = -1; + type = ACTION_DAMAGES; } - /* Damage Stack resolve process: -1 - apply damages to targets. For each of them, send an event to the GameObserver (for Damage triggers) -2 - Once this is done, send a "Damage Stakc Resolved" event to the GameObserver -3 - Once that message is received on the DamageStack's side, do the "afterDamage" effects (send to graveyard, etc...) -Using events in 2 and 3 guarantees that the "send to graveyard" effect will only apply AFTER Damaged triggers are applied -*/ -int DamageStack::resolve(){ - for (int i = mCount-1; i>= 0; i--){ - Damage * damage = (Damage*)mObjects[i]; - if (damage->state == NOT_RESOLVED) damage->resolve(); - } - GameObserver::GetInstance()->receiveEvent(NEW WEventDamageStackResolved()); - return 1; - } - -int DamageStack::receiveEvent(WEvent * e) { - WEventDamageStackResolved *event = dynamic_cast(e); - if (!event) return 0; - - for (int i = mCount-1; i>= 0; i--){ - Damage * damage = (Damage*)mObjects[i]; - if (damage->state == RESOLVED_OK) damage->target->afterDamage(); - } - return 1; + 1 - apply damages to targets. For each of them, send an event to the GameObserver (for Damage triggers) + 2 - Once this is done, send a "Damage Stakc Resolved" event to the GameObserver + 3 - Once that message is received on the DamageStack's side, do the "afterDamage" effects (send to graveyard, etc...) + Using events in 2 and 3 guarantees that the "send to graveyard" effect will only apply AFTER Damaged triggers are applied + */ +int DamageStack::resolve() +{ + for (int i = mCount - 1; i >= 0; i--) + { + Damage * damage = (Damage*) mObjects[i]; + if (damage->state == NOT_RESOLVED) + damage->resolve(); + } + GameObserver::GetInstance()->receiveEvent(NEW WEventDamageStackResolved()); + return 1; } -void DamageStack::Render(){ - float currenty = y; - for (int i= 0; i < mCount; i++){ - Damage * damage = (Damage*)mObjects[i]; - if (damage->state == NOT_RESOLVED){ - damage->x = x; - damage->y = currenty; - currenty += damage->mHeight; - damage->Render(); +int DamageStack::receiveEvent(WEvent * e) +{ + WEventDamageStackResolved *event = dynamic_cast (e); + if (!event) + return 0; + + for (int i = mCount - 1; i >= 0; i--) + { + Damage * damage = (Damage*) mObjects[i]; + if (damage->state == RESOLVED_OK) + damage->target->afterDamage(); + } + return 1; +} + +void DamageStack::Render() +{ + float currenty = y; + for (int i = 0; i < mCount; i++) + { + Damage * damage = (Damage*) mObjects[i]; + if (damage->state == NOT_RESOLVED) + { + damage->x = x; + damage->y = currenty; + currenty += damage->mHeight; + damage->Render(); + } } - } } ostream& DamageStack::toString(ostream& out) const { - return (out << "DamageStack ::: currentState : " << currentState); + return (out << "DamageStack ::: currentState : " << currentState); } diff --git a/projects/mtg/src/DamagerDamaged.cpp b/projects/mtg/src/DamagerDamaged.cpp index 494b6128e..0e57113cd 100644 --- a/projects/mtg/src/DamagerDamaged.cpp +++ b/projects/mtg/src/DamagerDamaged.cpp @@ -3,84 +3,105 @@ #include "DamagerDamaged.h" /* -Temporary objects that store the damages dealt to/from creatures during the combat phase -*/ + Temporary objects that store the damages dealt to/from creatures during the combat phase + */ -DamagerDamaged::DamagerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : TransientCardView(card, x, y), show(show), damageSelecter(damageSelecter) {} -DamagerDamaged::DamagerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : TransientCardView(card, ref), show(show), damageSelecter(damageSelecter) {} - -DamagerDamaged::~DamagerDamaged(){} - -int DamagerDamaged::sumDamages(){ - int total = 0; - for (vector::iterator i = damages.begin(); i != damages.end(); ++i) - total += i->damage; - return total; +DamagerDamaged::DamagerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : + TransientCardView(card, x, y), show(show), damageSelecter(damageSelecter) +{ +} +DamagerDamaged::DamagerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : + TransientCardView(card, ref), show(show), damageSelecter(damageSelecter) +{ } -bool DamagerDamaged::hasLethalDamage(){ - return (sumDamages() >= card->life); +DamagerDamaged::~DamagerDamaged() +{ } -void DamagerDamaged::addDamage(int damage, DamagerDamaged* source){ - for (vector::iterator i = damages.begin(); i != damages.end(); ++i) - if (i->source == source->card){ - i->damage += damage; - if (0 >= i->damage) damages.erase(i); - return; - } - if (0 < damage) damages.push_back(Damage(source->card, card, damage,DAMAGE_COMBAT)); - return; +int DamagerDamaged::sumDamages() +{ + int total = 0; + for (vector::iterator i = damages.begin(); i != damages.end(); ++i) + total += i->damage; + return total; } +bool DamagerDamaged::hasLethalDamage() +{ + return (sumDamages() >= card->life); +} -int DamagerDamaged::removeDamagesFrom(DamagerDamaged* source){ - for (vector::iterator i = damages.begin(); i != damages.end(); ++i) - if (i->source == source->card){ - int damage = i->damage; - damages.erase(i); - return damage; - } - return 0; +void DamagerDamaged::addDamage(int damage, DamagerDamaged* source) +{ + for (vector::iterator i = damages.begin(); i != damages.end(); ++i) + if (i->source == source->card) + { + i->damage += damage; + if (0 >= i->damage) + damages.erase(i); + return; + } + if (0 < damage) + damages.push_back(Damage(source->card, card, damage, DAMAGE_COMBAT)); + return; +} + +int DamagerDamaged::removeDamagesFrom(DamagerDamaged* source) +{ + for (vector::iterator i = damages.begin(); i != damages.end(); ++i) + if (i->source == source->card) + { + int damage = i->damage; + damages.erase(i); + return damage; + } + return 0; } void DamagerDamaged::clearDamage() { - damages.clear(); + damages.clear(); } void DamagerDamaged::Render(CombatStep mode) { - TransientCardView::Render(); - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetBase(0); + TransientCardView::Render(); + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetBase(0); - switch (mode) + switch (mode) { - case BLOCKERS : - case TRIGGERS : - case ORDER : - mFont->SetColor(ARGB(92,255,255,255)); - break; - case FIRST_STRIKE : - case END_FIRST_STRIKE : - case DAMAGE : - case END_DAMAGE : - mFont->SetColor(ARGB(255, 255, 64, 0)); - break; + case BLOCKERS: + case TRIGGERS: + case ORDER: + mFont->SetColor(ARGB(92,255,255,255)); + break; + case FIRST_STRIKE: + case END_FIRST_STRIKE: + case DAMAGE: + case END_DAMAGE: + mFont->SetColor(ARGB(255, 255, 64, 0)); + break; } - char buf[6]; + char buf[6]; sprintf(buf, "%i", sumDamages()); mFont->DrawString(buf, actX - 14 * actZ + 5, actY - 14 * actZ); } - -AttackerDamaged::AttackerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : DamagerDamaged(card, x, y, show, damageSelecter) {} -AttackerDamaged::AttackerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : DamagerDamaged(card, ref, show, damageSelecter) {} - -AttackerDamaged::~AttackerDamaged(){ -for (vector::iterator q = blockers.begin(); q != blockers.end(); ++q) - delete(*q); +AttackerDamaged::AttackerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : + DamagerDamaged(card, x, y, show, damageSelecter) +{ +} +AttackerDamaged::AttackerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : + DamagerDamaged(card, ref, show, damageSelecter) +{ +} + +AttackerDamaged::~AttackerDamaged() +{ + for (vector::iterator q = blockers.begin(); q != blockers.end(); ++q) + delete (*q); } diff --git a/projects/mtg/src/DeckDataWrapper.cpp b/projects/mtg/src/DeckDataWrapper.cpp index 5571f1c38..31139cca0 100644 --- a/projects/mtg/src/DeckDataWrapper.cpp +++ b/projects/mtg/src/DeckDataWrapper.cpp @@ -5,21 +5,26 @@ #include "PriceList.h" #include "WDataSrc.h" -DeckDataWrapper::DeckDataWrapper(MTGDeck * deck){ - parent = deck; - loadMatches(deck); +DeckDataWrapper::DeckDataWrapper(MTGDeck * deck) +{ + parent = deck; + loadMatches(deck); } -void DeckDataWrapper::save(){ - if(parent){ - Rebuild(parent); - parent->save(); - } +void DeckDataWrapper::save() +{ + if (parent) + { + Rebuild(parent); + parent->save(); + } } -void DeckDataWrapper::save(string filepath, bool useExpandedCardNames, string &deckTitle, string &deckDesc){ - if(parent){ - Rebuild(parent); - parent->save(filepath, useExpandedCardNames, deckTitle, deckDesc); - } +void DeckDataWrapper::save(string filepath, bool useExpandedCardNames, string &deckTitle, string &deckDesc) +{ + if (parent) + { + Rebuild(parent); + parent->save(filepath, useExpandedCardNames, deckTitle, deckDesc); + } } diff --git a/projects/mtg/src/DeckEditorMenu.cpp b/projects/mtg/src/DeckEditorMenu.cpp index 3f2854ed6..aa87021f0 100644 --- a/projects/mtg/src/DeckEditorMenu.cpp +++ b/projects/mtg/src/DeckEditorMenu.cpp @@ -6,92 +6,92 @@ #include "GameApp.h" #include -DeckEditorMenu::DeckEditorMenu(int id, JGuiListener* listener, int fontId, const char * _title, DeckDataWrapper *_selectedDeck, StatsWrapper *stats) -: DeckMenu( id, listener, fontId, _title ), selectedDeck(_selectedDeck), stw( stats ) +DeckEditorMenu::DeckEditorMenu(int id, JGuiListener* listener, int fontId, const char * _title, DeckDataWrapper *_selectedDeck, + StatsWrapper *stats) : + DeckMenu(id, listener, fontId, _title), selectedDeck(_selectedDeck), stw(stats) { - backgroundName = "DeckEditorMenuBackdrop"; - - - deckTitle = selectedDeck ? selectedDeck->parent->meta_name : ""; + backgroundName = "DeckEditorMenuBackdrop"; - mX = 123; - mY = 70; - starsOffsetX = 50; + deckTitle = selectedDeck ? selectedDeck->parent->meta_name : ""; - titleX = 110; // center point in title box - titleY = 25; - titleWidth = 180; // width of inner box of title + mX = 123; + mY = 70; + starsOffsetX = 50; - descX = 275; - descY = 80; - descHeight = 154; - descWidth = 175; - - statsHeight = 50; - statsWidth = 185; - statsX = 280; - statsY = 12; - - avatarX = 222; - avatarY = 8; + titleX = 110; // center point in title box + titleY = 25; + titleWidth = 180; // width of inner box of title - float scrollerWidth = 80; - SAFE_DELETE(scroller); // need to delete the scroller init in the base class - scroller = NEW TextScroller(Fonts::MAIN_FONT, 40 , 230, scrollerWidth, 100, 1, 1); + descX = 275; + descY = 80; + descHeight = 154; + descWidth = 175; + + statsHeight = 50; + statsWidth = 185; + statsX = 280; + statsY = 12; + + avatarX = 222; + avatarY = 8; + + float scrollerWidth = 80; + SAFE_DELETE(scroller); // need to delete the scroller init in the base class + scroller = NEW TextScroller(Fonts::MAIN_FONT, 40, 230, scrollerWidth, 100, 1, 1); } void DeckEditorMenu::Render() { - JRenderer *r = JRenderer::GetInstance(); - r->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(200,0,0,0)); + JRenderer *r = JRenderer::GetInstance(); + r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); - DeckMenu::Render(); - if ( deckTitle.size() > 0 ) - { - WFont *mainFont = resources.GetWFont( Fonts::OPTION_FONT ); - DWORD currentColor = mainFont->GetColor(); - mainFont->SetColor( ARGB(255,255,255,255) ); - mainFont->DrawString( deckTitle.c_str(), statsX + (statsWidth / 2), statsHeight / 2 , JGETEXT_CENTER); - mainFont->SetColor( currentColor ); - } + DeckMenu::Render(); + if (deckTitle.size() > 0) + { + WFont *mainFont = resources.GetWFont(Fonts::OPTION_FONT); + DWORD currentColor = mainFont->GetColor(); + mainFont->SetColor(ARGB(255,255,255,255)); + mainFont->DrawString(deckTitle.c_str(), statsX + (statsWidth / 2), statsHeight / 2, JGETEXT_CENTER); + mainFont->SetColor(currentColor); + } - if ( stw && selectedDeck ) - drawDeckStatistics(); + if (stw && selectedDeck) + drawDeckStatistics(); } void DeckEditorMenu::drawDeckStatistics() { - ostringstream deckStatsString; + ostringstream deckStatsString; - deckStatsString - << "------- Deck Summary -----" << endl - << "Cards: "<< selectedDeck->getCount() << endl - << "Creatures: "<< setw(2) << stw->countCreatures - << " Enchantments: " << stw->countEnchantments << endl - << "Instants: " << setw(4) << stw->countInstants - << " Sorceries: " << setw(2) << stw->countSorceries << endl - << "Lands: " - << "A: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_ARTIFACT ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_ARTIFACT ] << " " - << "G: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_GREEN ] + stw->countLandsPerColor[ Constants::MTG_COLOR_GREEN ] << " " - << "R: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_RED ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_RED ] << " " - << "U: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_BLUE ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_BLUE ] << " " - << "B: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_BLACK ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_BLACK ] << " " - << "W: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_WHITE ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_WHITE ] << endl + deckStatsString + << "------- Deck Summary -----" << endl + << "Cards: "<< selectedDeck->getCount() << endl + << "Creatures: "<< setw(2) << stw->countCreatures + << " Enchantments: " << stw->countEnchantments << endl + << "Instants: " << setw(4) << stw->countInstants + << " Sorceries: " << setw(2) << stw->countSorceries << endl + << "Lands: " + << "A: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_ARTIFACT ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_ARTIFACT ] << " " + << "G: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_GREEN ] + stw->countLandsPerColor[ Constants::MTG_COLOR_GREEN ] << " " + << "R: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_RED ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_RED ] << " " + << "U: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_BLUE ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_BLUE ] << " " + << "B: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_BLACK ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_BLACK ] << " " + << "W: " << setw(2) << left << stw->countLandsPerColor[ Constants::MTG_COLOR_WHITE ] + stw->countBasicLandsPerColor[ Constants::MTG_COLOR_WHITE ] << endl - << " --- Card color count --- " << endl - << "A: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_ARTIFACT) << " " - << "G: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_GREEN) << " " - << "U: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_BLUE) << " " - << "R: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_RED) << " " - << "B: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_BLACK) << " " - << "W: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_WHITE) << endl + << " --- Card color count --- " << endl + << "A: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_ARTIFACT) << " " + << "G: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_GREEN) << " " + << "U: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_BLUE) << " " + << "R: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_RED) << " " + << "B: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_BLACK) << " " + << "W: " << setw(2) << left << selectedDeck->getCount(Constants::MTG_COLOR_WHITE) << endl - << " --- Average Cost --- " << endl - << "Creature: "<< setprecision(2) << stw->avgCreatureCost << endl - << "Mana: " << setprecision(2) << stw->avgManaCost << " " - << "Spell: " << setprecision(2) << stw->avgSpellCost << endl; + << " --- Average Cost --- " << endl + << "Creature: "<< setprecision(2) << stw->avgCreatureCost << endl + << "Mana: " << setprecision(2) << stw->avgManaCost << " " + << "Spell: " << setprecision(2) << stw->avgSpellCost << endl; WFont *mainFont = resources.GetWFont( Fonts::MAIN_FONT ); mainFont->DrawString( deckStatsString.str().c_str(), descX, descY + 25 ); @@ -99,5 +99,5 @@ void DeckEditorMenu::drawDeckStatistics() DeckEditorMenu::~DeckEditorMenu() { - SAFE_DELETE( scroller ); + SAFE_DELETE( scroller ); } diff --git a/projects/mtg/src/DeckManager.cpp b/projects/mtg/src/DeckManager.cpp index 8b69b6980..e723bcba9 100644 --- a/projects/mtg/src/DeckManager.cpp +++ b/projects/mtg/src/DeckManager.cpp @@ -4,61 +4,57 @@ #include "Player.h" #include -void DeckManager::updateMetaDataList( vector * refList, bool isAI ) +void DeckManager::updateMetaDataList(vector * refList, bool isAI) { - if (refList) - { - vector * inputList = isAI? &aiDeckOrderList : &playerDeckOrderList; - inputList->clear(); - inputList->assign( refList->begin(), refList -> end() ); - } + if (refList) + { + vector * inputList = isAI ? &aiDeckOrderList : &playerDeckOrderList; + inputList->clear(); + inputList->assign(refList->begin(), refList -> end()); + } } - vector * DeckManager::getPlayerDeckOrderList() { return &playerDeckOrderList; } - + vector * DeckManager::getAIDeckOrderList() { return &aiDeckOrderList; } - DeckManager * DeckManager::mInstance = NULL; bool DeckManager::instanceFlag = false; void DeckManager::EndInstance() { - if (mInstance) - { - mInstance->aiDeckOrderList.clear(); - mInstance->playerDeckOrderList.clear(); - SAFE_DELETE( mInstance ); - } + if (mInstance) + { + mInstance->aiDeckOrderList.clear(); + mInstance->playerDeckOrderList.clear(); + SAFE_DELETE( mInstance ); + } } - DeckManager* DeckManager::GetInstance() { - if ( !instanceFlag ) - { - mInstance = NEW DeckManager(); - instanceFlag = true; - } + if (!instanceFlag) + { + mInstance = NEW DeckManager(); + instanceFlag = true; + } - return mInstance; + return mInstance; } - // p1 is assumed to be the player you want stats for // p2 is the opponent -int DeckManager::getDifficultyRating( Player *statsPlayer, Player *player ) +int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player) { - DeckMetaDataList * metas = DeckMetaDataList::decksMetaData; + DeckMetaDataList * metas = DeckMetaDataList::decksMetaData; - DeckMetaData *meta = metas->get( player->deckFile, statsPlayer ); + DeckMetaData *meta = metas->get(player->deckFile, statsPlayer); - return meta->getDifficulty(); + return meta->getDifficulty(); } diff --git a/projects/mtg/src/DeckMenu.cpp b/projects/mtg/src/DeckMenu.cpp index 44315f51f..63b7fd436 100644 --- a/projects/mtg/src/DeckMenu.cpp +++ b/projects/mtg/src/DeckMenu.cpp @@ -12,14 +12,14 @@ namespace { - const float kVerticalMargin = 16; - const float kHorizontalMargin = 20; - const float kLineHeight = 20; - const float kDescriptionVerticalBoxPadding = 5; - const float kDescriptionHorizontalBoxPadding = 5; + const float kVerticalMargin = 16; + const float kHorizontalMargin = 20; + const float kLineHeight = 20; + const float kDescriptionVerticalBoxPadding = 5; + const float kDescriptionHorizontalBoxPadding = 5; } -hgeParticleSystem* DeckMenu::stars = NULL; +hgeParticleSystem* DeckMenu::stars = NULL; // // For the additional info window, maximum characters per line is roughly 30 characters across. @@ -30,241 +30,252 @@ hgeParticleSystem* DeckMenu::stars = NULL; // * descriptive information 125 // *** Need to make this configurable in a file somewhere to allow for class reuse -DeckMenu::DeckMenu(int id, JGuiListener* listener, int fontId, const string _title, const float& mFontScale): JGuiController(id, listener), fontId(fontId), menuFontScale( mFontScale ) { +DeckMenu::DeckMenu(int id, JGuiListener* listener, int fontId, const string _title, const float& mFontScale) : + JGuiController(id, listener), fontId(fontId), menuFontScale(mFontScale) +{ - backgroundName = "DeckMenuBackdrop"; + backgroundName = "DeckMenuBackdrop"; - mY = 55; - mWidth = 176; - mX = 125; + mY = 55; + mWidth = 176; + mX = 125; - titleX = 130; // center point in title box - titleY = 28; - titleWidth = 180; // width of inner box of title + titleX = 130; // center point in title box + titleY = 28; + titleWidth = 180; // width of inner box of title - descX = 230 + kDescriptionVerticalBoxPadding; - descY = 65 + kDescriptionHorizontalBoxPadding; - descHeight = 145; - descWidth = 220; + descX = 230 + kDescriptionVerticalBoxPadding; + descY = 65 + kDescriptionHorizontalBoxPadding; + descHeight = 145; + descWidth = 220; - starsOffsetX = 50; + starsOffsetX = 50; - statsX = 280; - statsY = 8; - statsHeight = 50; - statsWidth = 227; - - avatarX = 230; - avatarY = 8; + statsX = 280; + statsY = 8; + statsHeight = 50; + statsWidth = 227; - menuInitialized = false; + avatarX = 230; + avatarY = 8; - float scrollerWidth = 80; - scroller = NEW TextScroller(Fonts::MAIN_FONT, 40 , 230, scrollerWidth, 100, 1, 1); + menuInitialized = false; - autoTranslate = true; - maxItems = 7; - mHeight = 2 * kVerticalMargin + ( maxItems * kLineHeight ); + float scrollerWidth = 80; + scroller = NEW TextScroller(Fonts::MAIN_FONT, 40, 230, scrollerWidth, 100, 1, 1); - // we want to cap the deck titles to 15 characters to avoid overflowing deck names - title = _(_title); - displayTitle = title; - mFont = resources.GetWFont(fontId); - - startId = 0; - selectionT = 0; - timeOpen = 0; - closed = false; + autoTranslate = true; + maxItems = 7; + mHeight = 2 * kVerticalMargin + (maxItems * kLineHeight); - if ( mFont->GetStringWidth( title.c_str() ) > titleWidth ) - titleFontScale = 0.75f; - else - titleFontScale = 1.0f; + // we want to cap the deck titles to 15 characters to avoid overflowing deck names + title = _(_title); + displayTitle = title; + mFont = resources.GetWFont(fontId); - selectionTargetY = selectionY = kVerticalMargin; - - if (NULL == stars) - stars = NEW hgeParticleSystem(resources.RetrievePSI("stars.psi", resources.GetQuad("stars"))); - stars->FireAt(mX, mY); + startId = 0; + selectionT = 0; + timeOpen = 0; + closed = false; - updateScroller(); + if (mFont->GetStringWidth(title.c_str()) > titleWidth) + titleFontScale = 0.75f; + else + titleFontScale = 1.0f; + + selectionTargetY = selectionY = kVerticalMargin; + + if (NULL == stars) + stars = NEW hgeParticleSystem(resources.RetrievePSI("stars.psi", resources.GetQuad("stars"))); + stars->FireAt(mX, mY); + + updateScroller(); } - void DeckMenu::RenderBackground() { - ostringstream bgFilename; - bgFilename << backgroundName << ".png"; + ostringstream bgFilename; + bgFilename << backgroundName << ".png"; - static bool loadBackground = true; - if (loadBackground) - { - JQuad *background = resources.RetrieveTempQuad(bgFilename.str(), TEXTURE_SUB_5551); - if ( background ) - JRenderer::GetInstance()->RenderQuad( background, 0, 0 ); - else - loadBackground = false; - } + static bool loadBackground = true; + if (loadBackground) + { + JQuad *background = resources.RetrieveTempQuad(bgFilename.str(), TEXTURE_SUB_5551); + if (background) + JRenderer::GetInstance()->RenderQuad(background, 0, 0); + else + loadBackground = false; + } } void DeckMenu::initMenuItems() { - float sY = mY + kVerticalMargin; - for (int i = startId; i < startId + mCount; ++i) { - float y = mY + kVerticalMargin + i * kLineHeight; - DeckMenuItem * currentMenuItem = static_cast(mObjects[i]); - currentMenuItem->Relocate( mX, y ); - if (currentMenuItem->hasFocus()) - sY = y; - } - selectionTargetY = selectionY = sY; + float sY = mY + kVerticalMargin; + for (int i = startId; i < startId + mCount; ++i) + { + float y = mY + kVerticalMargin + i * kLineHeight; + DeckMenuItem * currentMenuItem = static_cast (mObjects[i]); + currentMenuItem->Relocate(mX, y); + if (currentMenuItem->hasFocus()) + sY = y; + } + selectionTargetY = selectionY = sY; } -void DeckMenu::Render() +void DeckMenu::Render() { - JRenderer * renderer = JRenderer::GetInstance(); - float height = mHeight; - - if (!menuInitialized) - { - initMenuItems(); - stars->Fire(); - timeOpen = 0; - menuInitialized = true; - } - if (timeOpen < 1) height *= timeOpen > 0 ? timeOpen : -timeOpen; + JRenderer * renderer = JRenderer::GetInstance(); + float height = mHeight; - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); - stars->Render(); - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + if (!menuInitialized) + { + initMenuItems(); + stars->Fire(); + timeOpen = 0; + menuInitialized = true; + } + if (timeOpen < 1) + height *= timeOpen > 0 ? timeOpen : -timeOpen; - for (int i = startId; i < startId + maxItems ; i++){ - if (i > mCount-1) break; - DeckMenuItem *currentMenuItem = static_cast(mObjects[i]); - if ( currentMenuItem->mY - kLineHeight * startId < mY + height - kLineHeight + 7) { - if ( currentMenuItem->hasFocus()){ - // display the avatar image - if ( currentMenuItem->imageFilename.size() > 0 ) + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); + stars->Render(); + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + + for (int i = startId; i < startId + maxItems; i++) + { + if (i > mCount - 1) + break; + DeckMenuItem *currentMenuItem = static_cast (mObjects[i]); + if (currentMenuItem->mY - kLineHeight * startId < mY + height - kLineHeight + 7) { - JQuad * quad = resources.RetrieveTempQuad( currentMenuItem->imageFilename, TEXTURE_SUB_AVATAR ); - if (quad) - renderer->RenderQuad(quad, avatarX, avatarY); + if (currentMenuItem->hasFocus()) + { + // display the avatar image + if (currentMenuItem->imageFilename.size() > 0) + { + JQuad * quad = resources.RetrieveTempQuad(currentMenuItem->imageFilename, TEXTURE_SUB_AVATAR); + if (quad) + renderer->RenderQuad(quad, avatarX, avatarY); + } + // fill in the description part of the screen + string text = currentMenuItem->desc; + WFont *mainFont = resources.GetWFont(Fonts::MAIN_FONT); + mainFont->DrawString(text.c_str(), descX, descY); + mFont->SetColor(ARGB(255,255,255,255)); + + // fill in the statistical portion + if (currentMenuItem->meta) + { + ostringstream oss; + oss << "Deck: " << currentMenuItem->meta->getName() << endl; + oss << currentMenuItem->meta->getStatsSummary(); + + mainFont->DrawString(oss.str(), statsX, statsY); + } + } + else + { + mFont->SetColor(ARGB(150,255,255,255)); + } + mFont->SetScale(menuFontScale); + currentMenuItem->RenderWithOffset(-kLineHeight * startId); } - // fill in the description part of the screen - string text = currentMenuItem->desc; - WFont *mainFont = resources.GetWFont(Fonts::MAIN_FONT); - mainFont->DrawString(text.c_str(), descX, descY); + } + + RenderBackground(); + + if (!title.empty()) + { mFont->SetColor(ARGB(255,255,255,255)); + mFont->SetScale(titleFontScale); + mFont->DrawString(title.c_str(), titleX, titleY, JGETEXT_CENTER); + } + mFont->SetScale(1.0f); + scroller->Render(); - // fill in the statistical portion - if ( currentMenuItem->meta ) +} + +void DeckMenu::Update(float dt) +{ + JGuiController::Update(dt); + if (mCurr > startId + maxItems - 1) + startId = mCurr - maxItems + 1; + else if (mCurr < startId) + startId = mCurr; + stars->Update(dt); + selectionT += 3 * dt; + selectionY += (selectionTargetY - selectionY) * 8 * dt; + + float starsX = starsOffsetX + ((mWidth - 2 * kHorizontalMargin) * (1 + cos(selectionT)) / 2); + float starsY = selectionY + 5 * cos(selectionT * 2.35f) + kLineHeight / 2 - kLineHeight * startId; + stars->MoveTo(starsX, starsY); + if (timeOpen < 0) + { + timeOpen += dt * 10; + if (timeOpen >= 0) { - ostringstream oss; - oss << "Deck: " << currentMenuItem->meta->getName() << endl; - oss << currentMenuItem->meta->getStatsSummary(); - - mainFont->DrawString( oss.str(), statsX, statsY ); + timeOpen = 0; + closed = true; + stars->FireAt(mX, mY); } - } - else { - mFont->SetColor(ARGB(150,255,255,255)); - } - mFont->SetScale( menuFontScale ); - currentMenuItem->RenderWithOffset(-kLineHeight*startId); } - } + else + { + closed = false; + timeOpen += dt * 10; + } - RenderBackground(); - - - if (!title.empty()) - { - mFont->SetColor(ARGB(255,255,255,255)); - mFont->SetScale( titleFontScale ); - mFont->DrawString(title.c_str(), titleX, titleY, JGETEXT_CENTER); - } - mFont->SetScale( 1.0f ); - scroller->Render(); - + scroller->Update(dt); } -void DeckMenu::Update(float dt){ - JGuiController::Update(dt); - if (mCurr > startId + maxItems-1) - startId = mCurr - maxItems +1; - else if (mCurr < startId) - startId = mCurr; - stars->Update(dt); - selectionT += 3*dt; - selectionY += (selectionTargetY - selectionY) * 8 * dt; +void DeckMenu::Add(int id, const char * text, string desc, bool forceFocus, DeckMetaData * deckMetaData) +{ + DeckMenuItem * menuItem = NEW DeckMenuItem(this, id, fontId, text, 0, mY + kVerticalMargin + mCount * kLineHeight, + (mCount == 0), autoTranslate, deckMetaData); + Translator * t = Translator::GetInstance(); + map::iterator it = t->deckValues.find(text); + if (it != t->deckValues.end()) //translate decks desc + menuItem->desc = it->second; + else + menuItem->desc = deckMetaData ? deckMetaData->getDescription() : desc; - float starsX = starsOffsetX + ((mWidth - 2 * kHorizontalMargin)*(1+cos(selectionT))/2); - float starsY = selectionY + 5 * cos(selectionT*2.35f) + kLineHeight / 2 - kLineHeight * startId; - stars->MoveTo( starsX, starsY); - if (timeOpen < 0) - { - timeOpen += dt * 10; - if (timeOpen >= 0) - { - timeOpen = 0; - closed = true; - stars->FireAt(mX, mY); + JGuiController::Add(menuItem); + if (mCount <= maxItems) + mHeight += kLineHeight; + if (forceFocus) + { + mObjects[mCurr]->Leaving(JGE_BTN_DOWN); + mCurr = mCount - 1; + menuItem->Entering(); } - } - else - { - closed = false; - timeOpen += dt * 10; - } - - scroller->Update(dt); -} - -void DeckMenu::Add(int id, const char * text,string desc, bool forceFocus, DeckMetaData * deckMetaData) { - DeckMenuItem * menuItem = NEW DeckMenuItem(this, id, fontId, text, 0, mY + kVerticalMargin + mCount*kLineHeight, (mCount == 0), autoTranslate, deckMetaData); - Translator * t = Translator::GetInstance(); - map::iterator it = t->deckValues.find(text); - if (it != t->deckValues.end()) //translate decks desc - menuItem->desc = it->second; - else - menuItem->desc = deckMetaData ? deckMetaData->getDescription() : desc; - - JGuiController::Add(menuItem); - if (mCount <= maxItems) - mHeight += kLineHeight; - if (forceFocus){ - mObjects[mCurr]->Leaving(JGE_BTN_DOWN); - mCurr = mCount-1; - menuItem->Entering(); - } } void DeckMenu::updateScroller() { - // add all the items from the Tasks db. - TaskList taskList; - scroller->Reset(); - for (vector::iterator it = taskList.tasks.begin(); it!=taskList.tasks.end(); it++) - { - ostringstream taskDescription; - taskDescription << "[ " << setw(4) << (*it)->getReward() << " / " << (*it)->getExpiration() << " ] " << (*it)->getDesc() << endl; - scroller->Add( taskDescription.str() ); - } + // add all the items from the Tasks db. + TaskList taskList; + scroller->Reset(); + for (vector::iterator it = taskList.tasks.begin(); it != taskList.tasks.end(); it++) + { + ostringstream taskDescription; + taskDescription << "[ " << setw(4) << (*it)->getReward() << " / " << (*it)->getExpiration() << " ] " + << (*it)->getDesc() << endl; + scroller->Add(taskDescription.str()); + } } - void DeckMenu::Close() { - timeOpen = -1.0; - stars->Stop(true); + timeOpen = -1.0; + stars->Stop(true); } - -void DeckMenu::destroy(){ - SAFE_DELETE(DeckMenu::stars); - } +void DeckMenu::destroy() +{ + SAFE_DELETE(DeckMenu::stars); +} DeckMenu::~DeckMenu() { - SAFE_DELETE(scroller); + SAFE_DELETE(scroller); } diff --git a/projects/mtg/src/DeckMenuItem.cpp b/projects/mtg/src/DeckMenuItem.cpp index 24b2b5b69..dc27f9a05 100644 --- a/projects/mtg/src/DeckMenuItem.cpp +++ b/projects/mtg/src/DeckMenuItem.cpp @@ -7,89 +7,85 @@ #define ITEM_PX_WIDTH 190.f DeckMenuItem::DeckMenuItem(DeckMenu* _parent, int id, int fontId, string text, float x, float y, bool hasFocus, bool autoTranslate, DeckMetaData *deckMetaData) -: JGuiObject(id), parent(_parent), fontId(fontId), mX(x), mY(y) + : JGuiObject(id), parent(_parent), fontId(fontId), mX(x), mY(y) { - if (autoTranslate) - mText = _(text); - else - mText = text; - - //trim the string so that its width fits in the background. - //in the future we might want to replace this with a horizontal scrolling of long strings - WFont * mFont = resources.GetWFont(fontId); - while (mFont->GetStringWidth(mText.c_str()) > ITEM_PX_WIDTH) - mText.erase(mText.size()-1); + if (autoTranslate) + mText = _(text); + else + mText = text; - mHasFocus = hasFocus; - if (hasFocus) - Entering(); + //trim the string so that its width fits in the background. + //in the future we might want to replace this with a horizontal scrolling of long strings + WFont * mFont = resources.GetWFont(fontId); + while (mFont->GetStringWidth(mText.c_str()) > ITEM_PX_WIDTH) + mText.erase(mText.size() - 1); + + mHasFocus = hasFocus; + if (hasFocus) + Entering(); + + meta = deckMetaData; + if (meta && meta->getAvatarFilename().size() > 0) + this->imageFilename = meta->getAvatarFilename(); + else + this->imageFilename = "avatar.jpg"; - meta = deckMetaData; - if ( meta && meta->getAvatarFilename().size() > 0 ) - this->imageFilename = meta->getAvatarFilename(); - else - this->imageFilename = "avatar.jpg"; - } - void DeckMenuItem::RenderWithOffset(float yOffset) { - WFont * mFont = resources.GetWFont(fontId); - mFont->DrawString(mText.c_str(), mX, mY + yOffset, JGETEXT_CENTER); + WFont * mFont = resources.GetWFont(fontId); + mFont->DrawString(mText.c_str(), mX, mY + yOffset, JGETEXT_CENTER); } void DeckMenuItem::Render() { - RenderWithOffset(0); + RenderWithOffset(0); } void DeckMenuItem::Entering() { - mHasFocus = true; - parent->selectionTargetY = mY; + mHasFocus = true; + parent->selectionTargetY = mY; } - bool DeckMenuItem::Leaving(JButton key) { - mHasFocus = false; - return true; + mHasFocus = false; + return true; } - bool DeckMenuItem::ButtonPressed() { - return true; + return true; } void DeckMenuItem::Relocate(float x, float y) { - mX = x; - mY = y; + mX = x; + mY = y; } float DeckMenuItem::GetWidth() { - WFont * mFont = resources.GetWFont(fontId); - return mFont->GetStringWidth(mText.c_str()); + WFont * mFont = resources.GetWFont(fontId); + return mFont->GetStringWidth(mText.c_str()); } bool DeckMenuItem::hasFocus() { - return mHasFocus; + return mHasFocus; } ostream& DeckMenuItem::toString(ostream& out) const { - return out << "DeckMenuItem ::: mHasFocus : " << mHasFocus - << " ; parent : " << parent - << " ; mText : " << mText - << " ; mX,mY : " << mX << "," << mY; + return out << "DeckMenuItem ::: mHasFocus : " << mHasFocus + << " ; parent : " << parent + << " ; mText : " << mText + << " ; mX,mY : " << mX << "," << mY; } - DeckMenuItem::~DeckMenuItem() { - meta = NULL; -} \ No newline at end of file + meta = NULL; +} diff --git a/projects/mtg/src/DeckMetaData.cpp b/projects/mtg/src/DeckMetaData.cpp index cb59ffb3b..1dcb384a3 100644 --- a/projects/mtg/src/DeckMetaData.cpp +++ b/projects/mtg/src/DeckMetaData.cpp @@ -9,169 +9,177 @@ //Merge this with DeckStats //Have this class handle all the Meta Data rather than relying on MTGDeck. Then MTGDeck would have a MetaData object... - DeckMetaDataList * DeckMetaDataList::decksMetaData = NEW DeckMetaDataList(); -DeckMetaData::DeckMetaData(){ - -} - -DeckMetaData::DeckMetaData(string filename, Player * statsPlayer){ - load(filename); -} - - -void DeckMetaData::loadStatsForPlayer( Player * statsPlayer, string deckStatsFileName ) +DeckMetaData::DeckMetaData() { - DeckStats * stats = DeckStats::GetInstance(); - if ( statsPlayer ) - { - stats->load(statsPlayer); - DeckStat * opponentDeckStats = stats->getDeckStat(deckStatsFileName); - if ( opponentDeckStats ) + +} + +DeckMetaData::DeckMetaData(string filename, Player * statsPlayer) +{ + load(filename); +} + +void DeckMetaData::loadStatsForPlayer(Player * statsPlayer, string deckStatsFileName) +{ + DeckStats * stats = DeckStats::GetInstance(); + if (statsPlayer) { - _percentVictories = stats->percentVictories(deckStatsFileName); - _victories = opponentDeckStats->victories; - _nbGamesPlayed = opponentDeckStats->nbgames; - ostringstream oss; - int oppDeckId = atoi ( deckStatsFileName.substr( deckStatsFileName.find("deck") + 4, deckStatsFileName.find_last_of(".") ).c_str() ); - int avatarId = getAvatarId( oppDeckId ); - oss << "avatar" << avatarId << ".jpg"; - _avatarFilename = oss.str(); - if (_percentVictories < 34) - { - _difficulty = HARD; - } - else if (_percentVictories < 55) - { - _difficulty = NORMAL; - } - else - { - _difficulty = EASY; - } + stats->load(statsPlayer); + DeckStat * opponentDeckStats = stats->getDeckStat(deckStatsFileName); + if (opponentDeckStats) + { + _percentVictories = stats->percentVictories(deckStatsFileName); + _victories = opponentDeckStats->victories; + _nbGamesPlayed = opponentDeckStats->nbgames; + ostringstream oss; + int deckFilenameOffset = deckStatsFileName.find("deck") + 4; + int oppDeckId = atoi(deckStatsFileName.substr(deckFilenameOffset, deckStatsFileName.find_last_of(".")).c_str()); + int avatarId = getAvatarId(oppDeckId); + oss << "avatar" << avatarId << ".jpg"; + _avatarFilename = oss.str(); + if (_percentVictories < 34) + { + _difficulty = HARD; + } + else if (_percentVictories < 55) + { + _difficulty = NORMAL; + } + else + { + _difficulty = EASY; + } + } + else + { + ostringstream oss; + oss << "avatar" << getAvatarId(_deckid) << ".jpg"; + _avatarFilename = oss.str(); + } } else { - ostringstream oss; - oss << "avatar" << getAvatarId( _deckid ) << ".jpg"; - _avatarFilename = oss.str(); + if (fileExists(deckStatsFileName.c_str())) + { + stats->load(deckStatsFileName.c_str()); + _nbGamesPlayed = stats->nbGames(); + _percentVictories = stats->percentVictories(); + } } - } - else - { - if(fileExists(deckStatsFileName.c_str())){ - stats->load(deckStatsFileName.c_str()); - _nbGamesPlayed = stats->nbGames(); - _percentVictories = stats->percentVictories(); - } - } - stats = NULL; + stats = NULL; } // since we only have 100 stock avatar images, we need to recylce the images for deck numbers > 99 -int DeckMetaData::getAvatarId( int deckId ) +int DeckMetaData::getAvatarId(int deckId) { - int avatarId = deckId % 100; - if ( deckId >= 100 && avatarId == 0) - return 100; + int avatarId = deckId % 100; + if (deckId >= 100 && avatarId == 0) + return 100; - return avatarId; -} - -void DeckMetaData::load(string filename){ - MTGDeck * mtgd = NEW MTGDeck(filename.c_str(),NULL,1); - _name = trim( mtgd->meta_name ); - _desc = trim( mtgd->meta_desc ); - _deckid = atoi( (filename.substr( filename.find("deck") + 4, filename.find(".txt") )).c_str() ); - _percentVictories = 0; - _nbGamesPlayed = 0; - _filename = filename; - _victories = 0; - delete(mtgd); + return avatarId; } - -DeckMetaDataList::~DeckMetaDataList(){ - for(map::iterator it = values.begin(); it != values.end(); ++it){ - SAFE_DELETE(it->second); - } - values.clear(); +void DeckMetaData::load(string filename) +{ + MTGDeck * mtgd = NEW MTGDeck(filename.c_str(), NULL, 1); + _name = trim(mtgd->meta_name); + _desc = trim(mtgd->meta_desc); + _deckid = atoi((filename.substr(filename.find("deck") + 4, filename.find(".txt"))).c_str()); + _percentVictories = 0; + _nbGamesPlayed = 0; + _filename = filename; + _victories = 0; + delete (mtgd); } -void DeckMetaDataList::invalidate(string filename){ - map::iterator it = values.find(filename); - if (it !=values.end()){ - SAFE_DELETE(it->second); - values.erase(it); - } -} - -DeckMetaData * DeckMetaDataList::get(string filename, Player * statsPlayer){ - map::iterator it = values.find(filename); - if (it ==values.end()){ - if (fileExists(filename.c_str())) { - values[filename] = NEW DeckMetaData(filename, statsPlayer); +DeckMetaDataList::~DeckMetaDataList() +{ + for (map::iterator it = values.begin(); it != values.end(); ++it) + { + SAFE_DELETE(it->second); } - } + values.clear(); +} - return values[filename]; //this creates a NULL entry if the file does not exist +void DeckMetaDataList::invalidate(string filename) +{ + map::iterator it = values.find(filename); + if (it != values.end()) + { + SAFE_DELETE(it->second); + values.erase(it); + } +} + +DeckMetaData * DeckMetaDataList::get(string filename, Player * statsPlayer) +{ + map::iterator it = values.find(filename); + if (it == values.end()) + { + if (fileExists(filename.c_str())) + { + values[filename] = NEW DeckMetaData(filename, statsPlayer); + } + } + + return values[filename]; //this creates a NULL entry if the file does not exist } //Accessors string DeckMetaData::getFilename() { - return _filename; + return _filename; } string DeckMetaData::getName() { - return _name; + return _name; } int DeckMetaData::getDeckId() { - return _deckid; + return _deckid; } string DeckMetaData::getAvatarFilename() { - return _avatarFilename; + return _avatarFilename; } int DeckMetaData::getGamesPlayed() { - return _nbGamesPlayed; + return _nbGamesPlayed; } - int DeckMetaData::getVictories() { - return _victories; + return _victories; } int DeckMetaData::getVictoryPercentage() { - return _percentVictories; + return _percentVictories; } int DeckMetaData::getDifficulty() { - return _difficulty; + return _difficulty; } string DeckMetaData::getDifficultyString() { string difficultyString = "Normal"; - switch( _difficulty ) + switch (_difficulty) { - case HARD: - difficultyString = "Hard"; - break; - case EASY: - difficultyString = "Easy"; - break; + case HARD: + difficultyString = "Hard"; + break; + case EASY: + difficultyString = "Easy"; + break; } return difficultyString; @@ -184,11 +192,11 @@ string DeckMetaData::getDescription() string DeckMetaData::getStatsSummary() { - ostringstream statsSummary; - statsSummary << "Difficulty: " << getDifficultyString() << endl - << "Victory %: " << getVictoryPercentage() << endl - << "Games Played: " << getGamesPlayed() << endl; + ostringstream statsSummary; + statsSummary << "Difficulty: " << getDifficultyString() << endl + << "Victory %: " << getVictoryPercentage() << endl + << "Games Played: " << getGamesPlayed() << endl; + + return statsSummary.str(); - return statsSummary.str(); - } diff --git a/projects/mtg/src/DeckStats.cpp b/projects/mtg/src/DeckStats.cpp index 6d7c3fd2c..ccea6a606 100644 --- a/projects/mtg/src/DeckStats.cpp +++ b/projects/mtg/src/DeckStats.cpp @@ -6,196 +6,237 @@ DeckStats * DeckStats::mInstance = NULL; -int DeckStat::percentVictories(){ - if (nbgames == 0) return 50; - return (100 * victories / nbgames); -} - -DeckStats * DeckStats::GetInstance(){ - if (!mInstance){ - mInstance = NEW DeckStats(); - - } - return mInstance; -} - -void DeckStats::cleanStats(){ - map::iterator it; - for (it = stats.begin(); it != stats.end(); it++){ - SAFE_DELETE(it->second); - } - - stats.clear(); -} - -DeckStats::~DeckStats(){ - cleanStats(); -} - -int DeckStats::percentVictories(string opponentsFile){ - map::iterator it = stats.find(opponentsFile); - if (it == stats.end()){ - return 50; - }else{ - return (it->second->percentVictories()); - } -} - -DeckStat* DeckStats::getDeckStat(string opponentsFile){ - map::iterator it = stats.find(opponentsFile); - if (it == stats.end()){ - return NULL; - }else{ - return it->second; - } -} - -int DeckStats::nbGames(){ - int nbgames = 0; - map::iterator it; - for (it = stats.begin(); it != stats.end(); it++){ - DeckStat * d = it->second; - nbgames+=d->nbgames; - } - return nbgames; -} - - -int DeckStats::percentVictories(){ - int victories = 0; - int nbgames = 0; - map::iterator it; - for (it = stats.begin(); it != stats.end(); it++){ - DeckStat * d = it->second; - nbgames+=d->nbgames; - victories+=d->victories; - } - if (nbgames){ - return (victories * 100)/nbgames; - } - return 50; -} - -void DeckStats::load(Player * player){ - char filename[512]; - sprintf(filename,"stats/%s.txt",player->deckFileSmall.c_str()); - load(options.profileFile(filename).c_str()); -} - -void DeckStats::load(const char * filename){ - cleanStats(); - std::ifstream file(filename); - std::string s; - - if(file){ - while(std::getline(file,s)){ - string deckfile = s; - std::getline(file,s); - int games = atoi(s.c_str()); - std::getline(file,s); - int victories = atoi(s.c_str()); - map::iterator it = stats.find(deckfile); - if (it == stats.end()){ - stats[deckfile] = NEW DeckStat(games,victories); - } - } - file.close(); - } -} - -void DeckStats::save(Player * player){ - char filename[512]; - sprintf(filename,"stats/%s.txt",player->deckFileSmall.c_str()); - save(options.profileFile(filename).c_str()); -} - -void DeckStats::save(const char * filename){ - std::ofstream file(filename); - char writer[512]; - if (file){ - map::iterator it; - for (it = stats.begin(); it != stats.end(); it++){ - sprintf(writer,"%s\n", it->first.c_str()); - file<second->nbgames); - file<second->victories); - file<gameOver){ - if (player->life == opponent->life) return; - if (player->life < opponent->life) victory = 0; - }else if (game->gameOver == player) { - victory = 0; - } - load(player); - map::iterator it = stats.find(opponent->deckFileSmall); - if (it == stats.end()){ - stats[opponent->deckFileSmall] = NEW DeckStat(1,victory); - }else{ - it->second->victories+=victory; - it->second->nbgames+=1; - } - save(player); -} - - -StatsWrapper::StatsWrapper( int deckId ) +int DeckStat::percentVictories() { - // Load deck statistics - char buffer[512]; - DeckStats * stats = DeckStats::GetInstance(); - aiDeckNames.clear(); - aiDeckStats.clear(); - - sprintf(buffer, "stats/player_deck%i.txt", deckId); - string deckstats = options.profileFile(buffer); - - if(fileExists(deckstats.c_str())){ - stats->load(deckstats.c_str()); - percentVictories = stats->percentVictories(); - gamesPlayed = stats->nbGames(); - - // Detailed deck statistics against AI - int found = 1; - int nbDecks = 0; - while (found){ - found = 0; - char buffer[512]; - char smallDeckName[512]; - sprintf(buffer, "%s/deck%i.txt",RESPATH"/ai/baka",nbDecks+1); - if(fileExists(buffer)){ - MTGDeck * mtgd = NEW MTGDeck(buffer,NULL,1); - found = 1; - nbDecks++; - - sprintf(smallDeckName, "%s_deck%i","ai_baka",nbDecks); - DeckStat* deckStat = stats->getDeckStat(string(smallDeckName)); - - if ((deckStat != NULL) && (deckStat->nbgames>0)) { - int percentVictories = stats->percentVictories(string(smallDeckName)); - aiDeckNames.push_back(string(mtgd->meta_name)); - aiDeckStats.push_back(deckStat); - } - - delete mtgd; - } - } - } - else { - gamesPlayed = 0; - percentVictories = 0; - } + if (nbgames == 0) + return 50; + return (100 * victories / nbgames); +} + +DeckStats * DeckStats::GetInstance() +{ + if (!mInstance) + { + mInstance = NEW DeckStats(); + + } + return mInstance; +} + +void DeckStats::cleanStats() +{ + map::iterator it; + for (it = stats.begin(); it != stats.end(); it++) + { + SAFE_DELETE(it->second); + } + + stats.clear(); +} + +DeckStats::~DeckStats() +{ + cleanStats(); +} + +int DeckStats::percentVictories(string opponentsFile) +{ + map::iterator it = stats.find(opponentsFile); + if (it == stats.end()) + { + return 50; + } + else + { + return (it->second->percentVictories()); + } +} + +DeckStat* DeckStats::getDeckStat(string opponentsFile) +{ + map::iterator it = stats.find(opponentsFile); + if (it == stats.end()) + { + return NULL; + } + else + { + return it->second; + } +} + +int DeckStats::nbGames() +{ + int nbgames = 0; + map::iterator it; + for (it = stats.begin(); it != stats.end(); it++) + { + DeckStat * d = it->second; + nbgames += d->nbgames; + } + return nbgames; +} + +int DeckStats::percentVictories() +{ + int victories = 0; + int nbgames = 0; + map::iterator it; + for (it = stats.begin(); it != stats.end(); it++) + { + DeckStat * d = it->second; + nbgames += d->nbgames; + victories += d->victories; + } + if (nbgames) + { + return (victories * 100) / nbgames; + } + return 50; +} + +void DeckStats::load(Player * player) +{ + char filename[512]; + sprintf(filename, "stats/%s.txt", player->deckFileSmall.c_str()); + load(options.profileFile(filename).c_str()); +} + +void DeckStats::load(const char * filename) +{ + cleanStats(); + std::ifstream file(filename); + std::string s; + + if (file) + { + while (std::getline(file, s)) + { + string deckfile = s; + std::getline(file, s); + int games = atoi(s.c_str()); + std::getline(file, s); + int victories = atoi(s.c_str()); + map::iterator it = stats.find(deckfile); + if (it == stats.end()) + { + stats[deckfile] = NEW DeckStat(games, victories); + } + } + file.close(); + } +} + +void DeckStats::save(Player * player) +{ + char filename[512]; + sprintf(filename, "stats/%s.txt", player->deckFileSmall.c_str()); + save(options.profileFile(filename).c_str()); +} + +void DeckStats::save(const char * filename) +{ + std::ofstream file(filename); + char writer[512]; + if (file) + { + map::iterator it; + for (it = stats.begin(); it != stats.end(); it++) + { + sprintf(writer, "%s\n", it->first.c_str()); + file << writer; + sprintf(writer, "%i\n", it->second->nbgames); + file << writer; + sprintf(writer, "%i\n", it->second->victories); + file << writer; + } + file.close(); + } +} + +void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game) +{ + int victory = 1; + if (!game->gameOver) + { + if (player->life == opponent->life) + return; + if (player->life < opponent->life) + victory = 0; + } + else if (game->gameOver == player) + { + victory = 0; + } + load(player); + map::iterator it = stats.find(opponent->deckFileSmall); + if (it == stats.end()) + { + stats[opponent->deckFileSmall] = NEW DeckStat(1, victory); + } + else + { + it->second->victories += victory; + it->second->nbgames += 1; + } + save(player); +} + +StatsWrapper::StatsWrapper(int deckId) +{ + // Load deck statistics + char buffer[512]; + DeckStats * stats = DeckStats::GetInstance(); + aiDeckNames.clear(); + aiDeckStats.clear(); + + sprintf(buffer, "stats/player_deck%i.txt", deckId); + string deckstats = options.profileFile(buffer); + + if (fileExists(deckstats.c_str())) + { + stats->load(deckstats.c_str()); + percentVictories = stats->percentVictories(); + gamesPlayed = stats->nbGames(); + + // Detailed deck statistics against AI + int found = 1; + int nbDecks = 0; + while (found) + { + found = 0; + char buffer[512]; + char smallDeckName[512]; + sprintf(buffer, "%s/deck%i.txt", RESPATH"/ai/baka", nbDecks + 1); + if (fileExists(buffer)) + { + MTGDeck * mtgd = NEW MTGDeck(buffer, NULL, 1); + found = 1; + nbDecks++; + + sprintf(smallDeckName, "%s_deck%i", "ai_baka", nbDecks); + DeckStat* deckStat = stats->getDeckStat(string(smallDeckName)); + + if ((deckStat != NULL) && (deckStat->nbgames > 0)) + { + int percentVictories = stats->percentVictories(string(smallDeckName)); + aiDeckNames.push_back(string(mtgd->meta_name)); + aiDeckStats.push_back(deckStat); + } + + delete mtgd; + } + } + } + else + { + gamesPlayed = 0; + percentVictories = 0; + } } StatsWrapper::~StatsWrapper() { - aiDeckNames.clear(); - aiDeckStats.clear(); -} \ No newline at end of file + aiDeckNames.clear(); + aiDeckStats.clear(); +} diff --git a/projects/mtg/src/DuelLayers.cpp b/projects/mtg/src/DuelLayers.cpp index 81929eedc..ed6d56be6 100644 --- a/projects/mtg/src/DuelLayers.cpp +++ b/projects/mtg/src/DuelLayers.cpp @@ -13,198 +13,221 @@ #include "Trash.h" #include "DuelLayers.h" -void DuelLayers::init(){ +void DuelLayers::init() +{ - GameObserver* go = GameObserver::GetInstance(); + GameObserver* go = GameObserver::GetInstance(); - mCardSelector = CardSelectorSingleton::Create(this); - //1 Action Layer - action = NEW ActionLayer(); - action->Add(NEW MTGGamePhase(action->getMaxId())); - //Add Magic Specific Rules - action->Add(NEW MTGPutInPlayRule(-1)); - action->Add(NEW MTGAlternativeCostRule(-1)); - action->Add(NEW MTGBuyBackRule(-1)); - action->Add(NEW MTGFlashBackRule(-1)); - action->Add(NEW MTGRetraceRule(-1)); - action->Add(NEW MTGAttackRule(-1)); - action->Add(NEW MTGBlockRule(-1)); - action->Add(NEW MTGCombatTriggersRule(-1)); - action->Add(NEW MTGLegendRule(-1)); - action->Add(NEW MTGTokensCleanup(-1)); // needs to be before persist - action->Add(NEW MTGPersistRule(-1)); - action->Add(NEW MTGAffinityRule(-1)); - action->Add(NEW MTGUnearthRule(-1)); - action->Add(NEW MTGCantCasterstart(-1)); - action->Add(NEW MTGSneakAttackRule(-1)); - action->Add(NEW MTGLifelinkRule(-1)); - action->Add(NEW MTGDeathtouchRule(-1)); - action->Add(NEW OtherAbilitiesEventReceiver(-1)); + mCardSelector = CardSelectorSingleton::Create(this); + //1 Action Layer + action = NEW ActionLayer(); + action->Add(NEW MTGGamePhase(action->getMaxId())); + //Add Magic Specific Rules + action->Add(NEW MTGPutInPlayRule(-1)); + action->Add(NEW MTGAlternativeCostRule(-1)); + action->Add(NEW MTGBuyBackRule(-1)); + action->Add(NEW MTGFlashBackRule(-1)); + action->Add(NEW MTGRetraceRule(-1)); + action->Add(NEW MTGAttackRule(-1)); + action->Add(NEW MTGBlockRule(-1)); + action->Add(NEW MTGCombatTriggersRule(-1)); + action->Add(NEW MTGLegendRule(-1)); + action->Add(NEW MTGTokensCleanup(-1)); // needs to be before persist + action->Add(NEW MTGPersistRule(-1)); + action->Add(NEW MTGAffinityRule(-1)); + action->Add(NEW MTGUnearthRule(-1)); + action->Add(NEW MTGCantCasterstart(-1)); + action->Add(NEW MTGSneakAttackRule(-1)); + action->Add(NEW MTGLifelinkRule(-1)); + action->Add(NEW MTGDeathtouchRule(-1)); + action->Add(NEW OtherAbilitiesEventReceiver(-1)); - //Other display elements - action->Add(NEW HUDDisplay(-1)); + //Other display elements + action->Add(NEW HUDDisplay(-1)); - Add(NEW GuiMana(20,20,go->players[1])); - Add(NEW GuiMana(440,20,go->players[0])); - Add(stack = NEW ActionStack(go)); - Add(combat = NEW GuiCombat(go)); - Add(action); - Add(mCardSelector); - Add(hand = NEW GuiHandSelf(go->players[0]->game->hand)); - Add(avatars = NEW GuiAvatars()); - Add(NEW GuiHandOpponent(go->players[1]->game->hand)); - Add(NEW GuiPlay(go)); - Add(NEW GuiPhaseBar()); - Add(NEW GuiFrame()); - Add(NEW GuiBackground()); + Add(NEW GuiMana(20, 20, go->players[1])); + Add(NEW GuiMana(440, 20, go->players[0])); + Add(stack = NEW ActionStack(go)); + Add(combat = NEW GuiCombat(go)); + Add(action); + Add(mCardSelector); + Add(hand = NEW GuiHandSelf(go->players[0]->game->hand)); + Add(avatars = NEW GuiAvatars()); + Add(NEW GuiHandOpponent(go->players[1]->game->hand)); + Add(NEW GuiPlay(go)); + Add(NEW GuiPhaseBar()); + Add(NEW GuiFrame()); + Add(NEW GuiBackground()); } -void DuelLayers::CheckUserInput(int isAI){ - JButton key; - int x, y; - while ((key = JGE::GetInstance()->ReadButton())) - { - if ((!isAI) && (0 != key)) +void DuelLayers::CheckUserInput(int isAI) +{ + JButton key; + int x, y; + while ((key = JGE::GetInstance()->ReadButton())) { - if (stack->CheckUserInput(key)) break; - if (combat->CheckUserInput(key)) break; - if (avatars->CheckUserInput(key)) break; //avatars need to check their input before action (CTRL_CROSS) - if (action->CheckUserInput(key)) break; - if (hand->CheckUserInput(key)) break; - if (CardSelectorSingleton::Instance()->CheckUserInput(key)) break; + if ((!isAI) && (0 != key)) + { + if (stack->CheckUserInput(key)) + break; + if (combat->CheckUserInput(key)) + break; + if (avatars->CheckUserInput(key)) + break; //avatars need to check their input before action (CTRL_CROSS) + if (action->CheckUserInput(key)) + break; + if (hand->CheckUserInput(key)) + break; + if (CardSelectorSingleton::Instance()->CheckUserInput(key)) + break; + } } - } - if(JGE::GetInstance()->GetLeftClickCoordinates(x, y)) - { - if (avatars->CheckUserInput(x, y)) + if (JGE::GetInstance()->GetLeftClickCoordinates(x, y)) { - JGE::GetInstance()->LeftClickedProcessed(); + if (avatars->CheckUserInput(x, y)) + { + JGE::GetInstance()->LeftClickedProcessed(); + } + else if (CardSelectorSingleton::Instance()->CheckUserInput(x, y)) + { + JGE::GetInstance()->LeftClickedProcessed(); + } } - else if (CardSelectorSingleton::Instance()->CheckUserInput(x, y)) - { - JGE::GetInstance()->LeftClickedProcessed(); - } - } } void DuelLayers::Update(float dt, Player * currentPlayer) { - for (int i = 0; i < nbitems; ++i) objects[i]->Update(dt); - int isAI = currentPlayer->isAI(); - if (isAI) currentPlayer->Act(dt); - CheckUserInput(isAI); + for (int i = 0; i < nbitems; ++i) + objects[i]->Update(dt); + int isAI = currentPlayer->isAI(); + if (isAI) + currentPlayer->Act(dt); + CheckUserInput(isAI); } -ActionStack * DuelLayers::stackLayer(){ - return stack; +ActionStack * DuelLayers::stackLayer() +{ + return stack; } -GuiCombat * DuelLayers::combatLayer(){ - return combat; +GuiCombat * DuelLayers::combatLayer() +{ + return combat; } -ActionLayer * DuelLayers::actionLayer(){ - return action; +ActionLayer * DuelLayers::actionLayer() +{ + return action; } GuiAvatars * DuelLayers::GetAvatars() { - return avatars; + return avatars; } -DuelLayers::DuelLayers() : nbitems(0) {} +DuelLayers::DuelLayers() : + nbitems(0) +{ +} -DuelLayers::~DuelLayers(){ - int _nbitems = nbitems; - nbitems = 0; - for (int i = 0; i < _nbitems; ++i) - { - if (objects[i] != mCardSelector) +DuelLayers::~DuelLayers() +{ + int _nbitems = nbitems; + nbitems = 0; + for (int i = 0; i < _nbitems; ++i) { - delete objects[i]; - objects[i] = NULL; + if (objects[i] != mCardSelector) + { + delete objects[i]; + objects[i] = NULL; + } } - } - for (size_t i = 0; i < waiters.size(); ++i) - delete(waiters[i]); - Trash::cleanup(); + for (size_t i = 0; i < waiters.size(); ++i) + delete (waiters[i]); + Trash::cleanup(); - CardSelectorSingleton::Terminate(); - mCardSelector = NULL; + CardSelectorSingleton::Terminate(); + mCardSelector = NULL; } -void DuelLayers::Add(GuiLayer * layer){ - objects.push_back(layer); - nbitems++; +void DuelLayers::Add(GuiLayer * layer) +{ + objects.push_back(layer); + nbitems++; } -void DuelLayers::Remove(){ - --nbitems; +void DuelLayers::Remove() +{ + --nbitems; } -void DuelLayers::Render(){ - bool focusMakesItThrough = true; - for (int i = 0; i < nbitems; ++i) +void DuelLayers::Render() +{ + bool focusMakesItThrough = true; + for (int i = 0; i < nbitems; ++i) { - objects[i]->hasFocus = focusMakesItThrough; - if (objects[i]->modal) focusMakesItThrough = false; + objects[i]->hasFocus = focusMakesItThrough; + if (objects[i]->modal) + focusMakesItThrough = false; } - for (int i = nbitems - 1; i >= 0; --i) - objects[i]->Render(); + for (int i = nbitems - 1; i >= 0; --i) + objects[i]->Render(); } -int DuelLayers::receiveEvent(WEvent * e){ +int DuelLayers::receiveEvent(WEvent * e) +{ #if 0 #define PRINT_IF(type) { type *foo = dynamic_cast(e); if (foo) cout << "Is a " #type " " << *foo << endl; } - cout << "Received event " << e << " "; - PRINT_IF(WEventZoneChange); - PRINT_IF(WEventDamage); - PRINT_IF(WEventPhaseChange); - PRINT_IF(WEventCardUpdate); - PRINT_IF(WEventCardTap); - PRINT_IF(WEventCreatureAttacker); - PRINT_IF(WEventCreatureBlocker); - PRINT_IF(WEventCreatureBlockerRank); - PRINT_IF(WEventCombatStepChange); - PRINT_IF(WEventEngageMana); - PRINT_IF(WEventConsumeMana); - PRINT_IF(WEventEmptyManaPool); + cout << "Received event " << e << " "; + PRINT_IF(WEventZoneChange); + PRINT_IF(WEventDamage); + PRINT_IF(WEventPhaseChange); + PRINT_IF(WEventCardUpdate); + PRINT_IF(WEventCardTap); + PRINT_IF(WEventCreatureAttacker); + PRINT_IF(WEventCreatureBlocker); + PRINT_IF(WEventCreatureBlockerRank); + PRINT_IF(WEventCombatStepChange); + PRINT_IF(WEventEngageMana); + PRINT_IF(WEventConsumeMana); + PRINT_IF(WEventEmptyManaPool); #endif - int used = 0; - for (int i = 0; i < nbitems; ++i) - used |= objects[i]->receiveEventPlus(e); - if (!used) + int used = 0; + for (int i = 0; i < nbitems; ++i) + used |= objects[i]->receiveEventPlus(e); + if (!used) { - Pos* p; - if (WEventZoneChange *event = dynamic_cast(e)) - { - MTGCardInstance* card = event->card; - if (card->view) - waiters.push_back(p = NEW Pos(*(card->view))); - else - waiters.push_back(p = NEW Pos(0, 0, 0, 0, 255)); - const Pos* ref = card->view; - while (card) + Pos* p; + if (WEventZoneChange *event = dynamic_cast(e)) + { + MTGCardInstance* card = event->card; + if (card->view) + waiters.push_back(p = NEW Pos(*(card->view))); + else + waiters.push_back(p = NEW Pos(0, 0, 0, 0, 255)); + const Pos* ref = card->view; + while (card) { - if (ref == card->view) card->view = p; - card = card->next; + if (ref == card->view) + card->view = p; + card = card->next; } - } + } } - for (int i = 0; i < nbitems; ++i) - objects[i]->receiveEventMinus(e); + for (int i = 0; i < nbitems; ++i) + objects[i]->receiveEventMinus(e); - if (WEventPhaseChange *event = dynamic_cast(e)) - if (Constants::MTG_PHASE_BEFORE_BEGIN == event->to->id) - Trash::cleanup(); + if (WEventPhaseChange *event = dynamic_cast(e)) + if (Constants::MTG_PHASE_BEFORE_BEGIN == event->to->id) + Trash::cleanup(); - return 1; + return 1; } float DuelLayers::RightBoundary() { - return MIN (hand->LeftBoundary(), avatars->LeftBoundarySelf()); + return MIN (hand->LeftBoundary(), avatars->LeftBoundarySelf()); } diff --git a/projects/mtg/src/ExtraCost.cpp b/projects/mtg/src/ExtraCost.cpp index eaaf42ab0..523aa8e84 100644 --- a/projects/mtg/src/ExtraCost.cpp +++ b/projects/mtg/src/ExtraCost.cpp @@ -7,475 +7,608 @@ #include "Player.h" #include "Counters.h" -ExtraCost::ExtraCost(const std::string& inCostRenderString, TargetChooser *_tc) - : tc(_tc), source(NULL), target(NULL), mCostRenderString(inCostRenderString) +ExtraCost::ExtraCost(const std::string& inCostRenderString, TargetChooser *_tc) : + tc(_tc), source(NULL), target(NULL), mCostRenderString(inCostRenderString) { - if (tc) tc->targetter = NULL; + if (tc) + tc->targetter = NULL; } -ExtraCost::~ExtraCost(){ - SAFE_DELETE(tc); +ExtraCost::~ExtraCost() +{ + SAFE_DELETE(tc); } -int ExtraCost::setSource(MTGCardInstance * _source){ - source=_source; - if (tc) - { - tc->source = _source; - // "extra cost is not targetting, protections do not apply" this is not cryptic at all :) make an ability you will understand it then. this keeps the target chooser from being unable to select a creature with shroud/protections. - tc->targetter = NULL; - } - else - { - target = _source; - } - return 1; -} - -void ExtraCost::Render(){ - if (!mCostRenderString.empty()) - { - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(mCostRenderString, 20 ,20, JGETEXT_LEFT); - } -} - -int ExtraCost::setPayment(MTGCardInstance * card){ - int result = 0; - if (tc) { - result = tc->addTarget(card); - if (result) { - target = card; +int ExtraCost::setSource(MTGCardInstance * _source) +{ + source = _source; + if (tc) + { + tc->source = _source; + // "extra cost is not targetting, protections do not apply" this is not cryptic at all :) make an ability you will understand it then. this keeps the target chooser from being unable to select a creature with shroud/protections. + tc->targetter = NULL; } - } - return result; + else + { + target = _source; + } + return 1; +} + +void ExtraCost::Render() +{ + if (!mCostRenderString.empty()) + { + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(mCostRenderString, 20, 20, JGETEXT_LEFT); + } +} + +int ExtraCost::setPayment(MTGCardInstance * card) +{ + int result = 0; + if (tc) + { + result = tc->addTarget(card); + if (result) + { + target = card; + } + } + return result; } //life cost -LifeCost * LifeCost::clone() const{ - LifeCost * ec = NEW LifeCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +LifeCost * LifeCost::clone() const +{ + LifeCost * ec = NEW LifeCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -LifeCost::LifeCost(TargetChooser *_tc) - : ExtraCost("Life", _tc){ +LifeCost::LifeCost(TargetChooser *_tc) : + ExtraCost("Life", _tc) +{ } -int LifeCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - _target->controller()->life -= 1; - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int LifeCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + _target->controller()->life -= 1; + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //discard a card at random as a cost //DiscardRandom cost -DiscardRandomCost * DiscardRandomCost::clone() const{ - DiscardRandomCost * ec = NEW DiscardRandomCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +DiscardRandomCost * DiscardRandomCost::clone() const +{ + DiscardRandomCost * ec = NEW DiscardRandomCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -DiscardRandomCost::DiscardRandomCost(TargetChooser *_tc) - : ExtraCost("Discard Random", _tc){ +DiscardRandomCost::DiscardRandomCost(TargetChooser *_tc) : + ExtraCost("Discard Random", _tc) +{ } -int DiscardRandomCost::canPay(){ - MTGGameZone * z = target->controller()->game->hand; - int nbcards = z->nb_cards; - if(nbcards < 1) return 0; - if(nbcards == 1 && z->hasCard(source)) return 0; - return 1; -} - -int DiscardRandomCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - _target->controller()->game->discardRandom(_target->controller()->game->hand,source); - target = NULL; - if (tc) tc->initTargets(); +int DiscardRandomCost::canPay() +{ + MTGGameZone * z = target->controller()->game->hand; + int nbcards = z->nb_cards; + if (nbcards < 1) + return 0; + if (nbcards == 1 && z->hasCard(source)) + return 0; return 1; - } - return 0; +} + +int DiscardRandomCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + _target->controller()->game->discardRandom(_target->controller()->game->hand, source); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //a choosen discard -DiscardCost * DiscardCost::clone() const{ - DiscardCost * ec = NEW DiscardCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +DiscardCost * DiscardCost::clone() const +{ + DiscardCost * ec = NEW DiscardCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -DiscardCost::DiscardCost(TargetChooser *_tc) - : ExtraCost("Choose card to Discard", _tc){ +DiscardCost::DiscardCost(TargetChooser *_tc) : + ExtraCost("Choose card to Discard", _tc) +{ } -int DiscardCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - WEvent * e = NEW WEventCardDiscard(target); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); - _target->controller()->game->putInGraveyard(_target); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int DiscardCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + WEvent * e = NEW WEventCardDiscard(target); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); + _target->controller()->game->putInGraveyard(_target); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //to library cost -ToLibraryCost * ToLibraryCost::clone() const{ - ToLibraryCost * ec = NEW ToLibraryCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +ToLibraryCost * ToLibraryCost::clone() const +{ + ToLibraryCost * ec = NEW ToLibraryCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -ToLibraryCost::ToLibraryCost(TargetChooser *_tc) - : ExtraCost("Put a card on top of Library", _tc){ +ToLibraryCost::ToLibraryCost(TargetChooser *_tc) : + ExtraCost("Put a card on top of Library", _tc) +{ } -int ToLibraryCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - _target->controller()->game->putInLibrary(target); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int ToLibraryCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + _target->controller()->game->putInLibrary(target); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //Mill yourself as a cost -MillCost * MillCost::clone() const{ - MillCost * ec = NEW MillCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +MillCost * MillCost::clone() const +{ + MillCost * ec = NEW MillCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -MillCost::MillCost(TargetChooser *_tc) - : ExtraCost("Deplete", _tc){ +MillCost::MillCost(TargetChooser *_tc) : + ExtraCost("Deplete", _tc) +{ } -int MillCost::canPay(){ - MTGGameZone * z = target->controller()->game->library; - int nbcards = z->nb_cards; - if(nbcards < 1) return 0; - return 1; -} - -int MillCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - _target->controller()->game->putInZone(_target->controller()->game->library->cards[_target->controller()->game->library->nb_cards-1],_target->controller()->game->library, _target->controller()->game->graveyard); - target = NULL; - if (tc) tc->initTargets(); +int MillCost::canPay() +{ + MTGGameZone * z = target->controller()->game->library; + int nbcards = z->nb_cards; + if (nbcards < 1) + return 0; return 1; - } - return 0; } -MillExileCost::MillExileCost(TargetChooser *_tc) - : MillCost( _tc){ +int MillCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + _target->controller()->game->putInZone( + _target->controller()->game->library->cards[_target->controller()->game->library->nb_cards - 1], + _target->controller()->game->library, _target->controller()->game->graveyard); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; +} + +MillExileCost::MillExileCost(TargetChooser *_tc) : + MillCost(_tc) +{ // override the base string here mCostRenderString = "Deplete To Exile"; } -int MillExileCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - _target->controller()->game->putInZone(_target->controller()->game->library->cards[_target->controller()->game->library->nb_cards-1], - _target->controller()->game->library, - _target->controller()->game->exile); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int MillExileCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + _target->controller()->game->putInZone( + _target->controller()->game->library->cards[_target->controller()->game->library->nb_cards - 1], + _target->controller()->game->library, _target->controller()->game->exile); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //Tap target cost -TapTargetCost * TapTargetCost::clone() const{ - TapTargetCost * ec = NEW TapTargetCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +TapTargetCost * TapTargetCost::clone() const +{ + TapTargetCost * ec = NEW TapTargetCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -TapTargetCost::TapTargetCost(TargetChooser *_tc) - : ExtraCost("Tap Target", _tc){ +TapTargetCost::TapTargetCost(TargetChooser *_tc) : + ExtraCost("Tap Target", _tc) +{ } -int TapTargetCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - _target->tap(); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int TapTargetCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + _target->tap(); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //exile as cost -ExileTargetCost * ExileTargetCost::clone() const{ - ExileTargetCost * ec = NEW ExileTargetCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +ExileTargetCost * ExileTargetCost::clone() const +{ + ExileTargetCost * ec = NEW ExileTargetCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -ExileTargetCost::ExileTargetCost(TargetChooser *_tc) - : ExtraCost("Exile Target", _tc){ +ExileTargetCost::ExileTargetCost(TargetChooser *_tc) : + ExtraCost("Exile Target", _tc) +{ } -int ExileTargetCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - target->controller()->game->putInExile(target); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int ExileTargetCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + target->controller()->game->putInExile(target); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //Bounce as cost -BounceTargetCost * BounceTargetCost::clone() const{ - BounceTargetCost * ec = NEW BounceTargetCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +BounceTargetCost * BounceTargetCost::clone() const +{ + BounceTargetCost * ec = NEW BounceTargetCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -BounceTargetCost::BounceTargetCost(TargetChooser *_tc) - : ExtraCost("Return Target to Hand", _tc){ +BounceTargetCost::BounceTargetCost(TargetChooser *_tc) : + ExtraCost("Return Target to Hand", _tc) +{ } -int BounceTargetCost::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - target->controller()->game->putInHand(target); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int BounceTargetCost::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + target->controller()->game->putInHand(target); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //Bounce as cost for ninja -Ninja * Ninja::clone() const{ - Ninja * ec = NEW Ninja(*this); - if (tc) ec->tc = tc->clone(); - return ec; +Ninja * Ninja::clone() const +{ + Ninja * ec = NEW Ninja(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -Ninja::Ninja(TargetChooser *_tc) - : ExtraCost("Select unblocked attacker", _tc){ +Ninja::Ninja(TargetChooser *_tc) : + ExtraCost("Select unblocked attacker", _tc) +{ } -int Ninja::isPaymentSet(){ - GameObserver * g = GameObserver::GetInstance(); - int currentPhase = g->getCurrentGamePhase(); - if (target && ((target->isAttacker() && target->blocked == true) || target->isAttacker() < 1 || currentPhase != Constants::MTG_PHASE_COMBATBLOCKERS)){ tc->removeTarget(target);target = NULL; return 0;} - if(target) return 1; - return 0; +int Ninja::isPaymentSet() +{ + GameObserver * g = GameObserver::GetInstance(); + int currentPhase = g->getCurrentGamePhase(); + if (target && ((target->isAttacker() && target->blocked == true) || target->isAttacker() < 1 || currentPhase + != Constants::MTG_PHASE_COMBATBLOCKERS)) + { + tc->removeTarget(target); + target = NULL; + return 0; + } + if (target) + return 1; + return 0; } -int Ninja::doPay(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(target){ - target->controller()->game->putInHand(target); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int Ninja::doPay() +{ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (target) + { + target->controller()->game->putInHand(target); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //endbouncetargetcostforninja //------------------------------------------------------------ -SacrificeCost * SacrificeCost::clone() const{ - SacrificeCost * ec = NEW SacrificeCost(*this); - if (tc) ec->tc = tc->clone(); - return ec; +SacrificeCost * SacrificeCost::clone() const +{ + SacrificeCost * ec = NEW SacrificeCost(*this); + if (tc) + ec->tc = tc->clone(); + return ec; } -SacrificeCost::SacrificeCost(TargetChooser *_tc) - : ExtraCost("Sacrifice", _tc){ +SacrificeCost::SacrificeCost(TargetChooser *_tc) : + ExtraCost("Sacrifice", _tc) +{ } -int SacrificeCost::doPay(){ - if(target){ - WEvent * e = NEW WEventCardSacrifice(target); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); - target->controller()->game->putInGraveyard(target); - target = NULL; - if (tc) tc->initTargets(); - return 1; - } - return 0; +int SacrificeCost::doPay() +{ + if (target) + { + WEvent * e = NEW WEventCardSacrifice(target); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); + target->controller()->game->putInGraveyard(target); + target = NULL; + if (tc) + tc->initTargets(); + return 1; + } + return 0; } //Counter costs -CounterCost * CounterCost::clone() const{ - CounterCost * ec = NEW CounterCost(*this); - if (tc) ec->tc = tc->clone(); - if (counter) ec->counter = NEW Counter(counter->target, counter->name.c_str(),counter->power, counter->toughness); - return ec; +CounterCost * CounterCost::clone() const +{ + CounterCost * ec = NEW CounterCost(*this); + if (tc) + ec->tc = tc->clone(); + if (counter) + ec->counter = NEW Counter(counter->target, counter->name.c_str(), counter->power, counter->toughness); + return ec; } -CounterCost::CounterCost(Counter * _counter,TargetChooser *_tc) - : ExtraCost("Counters", _tc) { - counter = _counter; - hasCounters = 0; -} - -int CounterCost::setPayment(MTGCardInstance *card){ - if (tc) { - int result = tc->addTarget(card); - if (result) { - if (counter->nb >= 0) return 1; //add counters always possible - target = card; - Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness); - if (targetCounter && targetCounter->nb >= - counter->nb) { - hasCounters = 1; - return result; - } - } - } - return 0; -} - -int CounterCost::isPaymentSet(){ - if (!target) return 0; - if (counter->nb >=0) return 1; //add counters always possible - Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness); - if (targetCounter && targetCounter->nb >= - counter->nb) { - hasCounters = 1; - } - if (target && hasCounters) return 1; - return 0; -} - -int CounterCost::canPay(){ - // if target needs to be chosen, then move on. - if (tc) return 1; - if (counter->nb >=0) return 1; //add counters always possible - // otherwise, move on only if target has enough counters - Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness); - if (targetCounter && targetCounter->nb >= - counter->nb) return 1; - return 0; -} - -int CounterCost::doPay(){ - if (!target) return 0; - - if (counter->nb >=0) { //Add counters as a cost - for (int i = 0; i < counter->nb; i++) { - target->counters->addCounter(counter->name.c_str(),counter->power,counter->toughness); - } - return 1; - } - - //remove counters as a cost - if (hasCounters) { - for (int i = 0; i < - counter->nb; i++) { - target->counters->removeCounter(counter->name.c_str(),counter->power,counter->toughness); - } +CounterCost::CounterCost(Counter * _counter, TargetChooser *_tc) : + ExtraCost("Counters", _tc) +{ + counter = _counter; hasCounters = 0; - return 1; - } - return 0; } -CounterCost::~CounterCost(){ - SAFE_DELETE(counter); +int CounterCost::setPayment(MTGCardInstance *card) +{ + if (tc) + { + int result = tc->addTarget(card); + if (result) + { + if (counter->nb >= 0) + return 1; //add counters always possible + target = card; + Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness); + if (targetCounter && targetCounter->nb >= -counter->nb) + { + hasCounters = 1; + return result; + } + } + } + return 0; +} + +int CounterCost::isPaymentSet() +{ + if (!target) + return 0; + if (counter->nb >= 0) + return 1; //add counters always possible + Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness); + if (targetCounter && targetCounter->nb >= -counter->nb) + { + hasCounters = 1; + } + if (target && hasCounters) + return 1; + return 0; +} + +int CounterCost::canPay() +{ + // if target needs to be chosen, then move on. + if (tc) + return 1; + if (counter->nb >= 0) + return 1; //add counters always possible + // otherwise, move on only if target has enough counters + Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness); + if (targetCounter && targetCounter->nb >= -counter->nb) + return 1; + return 0; +} + +int CounterCost::doPay() +{ + if (!target) + return 0; + + if (counter->nb >= 0) + { //Add counters as a cost + for (int i = 0; i < counter->nb; i++) + { + target->counters->addCounter(counter->name.c_str(), counter->power, counter->toughness); + } + return 1; + } + + //remove counters as a cost + if (hasCounters) + { + for (int i = 0; i < -counter->nb; i++) + { + target->counters->removeCounter(counter->name.c_str(), counter->power, counter->toughness); + } + hasCounters = 0; + return 1; + } + return 0; +} + +CounterCost::~CounterCost() +{ + SAFE_DELETE(counter); } // //Container // -ExtraCosts::ExtraCosts(){ - action = NULL; - source = NULL; +ExtraCosts::ExtraCosts() +{ + action = NULL; + source = NULL; } -ExtraCosts * ExtraCosts::clone() const{ - ExtraCosts * ec = NEW ExtraCosts(*this); - ec->costs.clear(); - for (size_t i = 0; i < costs.size(); i++){ - ec->costs.push_back(costs[i]->clone()); - } - return ec; +ExtraCosts * ExtraCosts::clone() const +{ + ExtraCosts * ec = NEW ExtraCosts(*this); + ec->costs.clear(); + for (size_t i = 0; i < costs.size(); i++) + { + ec->costs.push_back(costs[i]->clone()); + } + return ec; } -void ExtraCosts::Render(){ - //TODO cool window and stuff... - for (size_t i = 0; i < costs.size(); i++){ - costs[i]->Render(); - } +void ExtraCosts::Render() +{ + //TODO cool window and stuff... + for (size_t i = 0; i < costs.size(); i++) + { + costs[i]->Render(); + } } -int ExtraCosts::setAction(MTGAbility * _action, MTGCardInstance * _card){ - action = _action; - source = _card; - for (size_t i = 0; i < costs.size(); i++){ - costs[i]->setSource(_card); - } - return 1; +int ExtraCosts::setAction(MTGAbility * _action, MTGCardInstance * _card) +{ + action = _action; + source = _card; + for (size_t i = 0; i < costs.size(); i++) + { + costs[i]->setSource(_card); + } + return 1; } -int ExtraCosts::reset(){ - action = NULL; - source = NULL; - //TODO set all payments to "unset" - return 1; +int ExtraCosts::reset() +{ + action = NULL; + source = NULL; + //TODO set all payments to "unset" + return 1; } -int ExtraCosts::tryToSetPayment(MTGCardInstance * card){ - for (size_t i = 0; i < costs.size(); i++){ - if (int result = costs[i]->setPayment(card)) return result; - } - return 0; +int ExtraCosts::tryToSetPayment(MTGCardInstance * card) +{ + for (size_t i = 0; i < costs.size(); i++) + { + if (int result = costs[i]->setPayment(card)) + return result; + } + return 0; } -int ExtraCosts::isPaymentSet(){ - for (size_t i = 0; i < costs.size(); i++){ - if (!costs[i]->isPaymentSet()) return 0; - } - return 1; +int ExtraCosts::isPaymentSet() +{ + for (size_t i = 0; i < costs.size(); i++) + { + if (!costs[i]->isPaymentSet()) + return 0; + } + return 1; } -int ExtraCosts::canPay(){ - for (size_t i = 0; i < costs.size(); i++){ - if (!costs[i]->canPay()) return 0; - } - return 1; +int ExtraCosts::canPay() +{ + for (size_t i = 0; i < costs.size(); i++) + { + if (!costs[i]->canPay()) + return 0; + } + return 1; } -int ExtraCosts::doPay(){ - int result = 0; - for (size_t i = 0; i < costs.size(); i++){ - result+=costs[i]->doPay(); - } - return result; +int ExtraCosts::doPay() +{ + int result = 0; + for (size_t i = 0; i < costs.size(); i++) + { + result += costs[i]->doPay(); + } + return result; } -ExtraCosts::~ExtraCosts(){ - for (size_t i = 0; i < costs.size(); i++){ - SAFE_DELETE(costs[i]); - } +ExtraCosts::~ExtraCosts() +{ + for (size_t i = 0; i < costs.size(); i++) + { + SAFE_DELETE(costs[i]); + } } -void ExtraCosts::Dump(){ - DebugTrace("=====\nDumping ExtraCosts=====\n"); - DebugTrace("NbElements: " << costs.size()); +void ExtraCosts::Dump() +{ + DebugTrace("=====\nDumping ExtraCosts=====\n"); + DebugTrace("NbElements: " << costs.size()); } diff --git a/projects/mtg/src/GameApp.cpp b/projects/mtg/src/GameApp.cpp index 7869a6075..47babcf7b 100644 --- a/projects/mtg/src/GameApp.cpp +++ b/projects/mtg/src/GameApp.cpp @@ -27,415 +27,445 @@ #define DEFAULT_DURATION .25 MTGAllCards * GameApp::collection = NULL; -int GameApp::players[] = {0,0}; +int GameApp::players[] = { 0, 0 }; int GameApp::HasMusic = 1; JMusic * GameApp::music = NULL; string GameApp::currentMusicFile = ""; string GameApp::systemError = ""; -JQuad* manaIcons[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; +JQuad* manaIcons[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -GameState::GameState(GameApp* parent): mParent(parent) +GameState::GameState(GameApp* parent) : + mParent(parent) { - mEngine = JGE::GetInstance(); + mEngine = JGE::GetInstance(); } - -GameApp::GameApp(): JApp() +GameApp::GameApp() : + JApp() { #ifdef DEBUG - nbUpdates = 0; - totalFPS = 0; + nbUpdates = 0; + totalFPS = 0; #endif #ifdef DOLOG - remove(LOG_FILE); + remove(LOG_FILE); #endif - mScreenShotCount = 0; + mScreenShotCount = 0; - for (int i=0; i < GAME_STATE_MAX ; i++) - mGameStates[i] = NULL; + for (int i = 0; i < GAME_STATE_MAX; i++) + mGameStates[i] = NULL; - mShowDebugInfo = false; - players[0] = 0; - players[1] = 0; - gameType = GAME_TYPE_CLASSIC; + mShowDebugInfo = false; + players[0] = 0; + players[1] = 0; + gameType = GAME_TYPE_CLASSIC; - - mCurrentState = NULL; - mNextState = NULL; - collection = NULL; - - music = NULL; + mCurrentState = NULL; + mNextState = NULL; + collection = NULL; + + music = NULL; } - GameApp::~GameApp() { } - void GameApp::Create() { - srand((unsigned int)time(0)); // initialize random + srand((unsigned int) time(0)); // initialize random #ifndef QT_CONFIG #if defined (WIN32) - _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); + _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #elif not defined (LINUX) - pspFpuSetEnable(0); //disable FPU Exceptions until we find where the FPU errors come from + pspFpuSetEnable(0); //disable FPU Exceptions until we find where the FPU errors come from #endif #endif //QT_CONFIG + //_CrtSetBreakAlloc(368); + LOG("starting Game"); - //_CrtSetBreakAlloc(368); - LOG("starting Game"); - - //Find the Res folder - std::ifstream mfile("Res.txt"); - string resPath; - if(mfile){ - if (std::getline(mfile, resPath)) { - if (resPath[resPath.size()-1] == '\r') resPath.erase(resPath.size()-1); //Handle DOS files - //TODO ERROR Handling if file does not exist - JFileSystem::GetInstance()->SetResourceRoot(trim(resPath)); + //Find the Res folder + std::ifstream mfile("Res.txt"); + string resPath; + if (mfile) + { + if (std::getline(mfile, resPath)) + { + if (resPath[resPath.size() - 1] == '\r') + resPath.erase(resPath.size() - 1); //Handle DOS files + //TODO ERROR Handling if file does not exist + JFileSystem::GetInstance()->SetResourceRoot(trim(resPath)); + } + mfile.close(); } - mfile.close(); - } LOG("Res Root:"); LOG(JFileSystem::GetInstance()->GetResourceRoot().c_str()); + //Link this to our settings manager. + options.theGame = this; - //Link this to our settings manager. - options.theGame = this; + //Ensure that options are partially loaded before loading files. + LOG("options.reloadProfile()"); + options.reloadProfile(); - //Ensure that options are partially loaded before loading files. - LOG("options.reloadProfile()"); - options.reloadProfile(); + LOG("Checking for music files"); + //Test for Music files presence + string filepath = JGE_GET_RES(resources.musicFile("Track0.mp3")); + std::ifstream file(filepath.c_str()); + if (file) + file.close(); + else + HasMusic = 0; - LOG("Checking for music files"); - //Test for Music files presence - string filepath = JGE_GET_RES(resources.musicFile("Track0.mp3")); - std::ifstream file(filepath.c_str()); - if (file) - file.close(); - else - HasMusic = 0; + filepath = JGE_GET_RES(resources.musicFile("Track1.mp3")); + std::ifstream file2(filepath.c_str()); + if (file2) + file2.close(); + else + HasMusic = 0; - filepath = JGE_GET_RES(resources.musicFile("Track1.mp3")); - std::ifstream file2(filepath.c_str()); - if (file2) - file2.close(); - else - HasMusic = 0; + LOG("Loading Textures"); + LOG("--Loading menuicons.png"); + resources.RetrieveTexture("menuicons.png", RETRIEVE_MANAGE); + LOG("---Gettings menuicons.png quads"); + //Creating thes quad in this specific order allows us to have them in the correct order to call them by integer id + manaIcons[Constants::MTG_COLOR_GREEN] = resources.RetrieveQuad("menuicons.png", 2 + 0 * 36, 38, 32, 32, "c_green", + RETRIEVE_MANAGE); + manaIcons[Constants::MTG_COLOR_BLUE] = resources.RetrieveQuad("menuicons.png", 2 + 1 * 36, 38, 32, 32, "c_blue", + RETRIEVE_MANAGE); + manaIcons[Constants::MTG_COLOR_RED] = resources.RetrieveQuad("menuicons.png", 2 + 3 * 36, 38, 32, 32, "c_red", RETRIEVE_MANAGE); + manaIcons[Constants::MTG_COLOR_BLACK] = resources.RetrieveQuad("menuicons.png", 2 + 2 * 36, 38, 32, 32, "c_black", + RETRIEVE_MANAGE); + manaIcons[Constants::MTG_COLOR_WHITE] = resources.RetrieveQuad("menuicons.png", 2 + 4 * 36, 38, 32, 32, "c_white", + RETRIEVE_MANAGE); + manaIcons[Constants::MTG_COLOR_LAND] = resources.RetrieveQuad("menuicons.png", 2 + 5 * 36, 38, 32, 32, "c_land", + RETRIEVE_MANAGE); + manaIcons[Constants::MTG_COLOR_ARTIFACT] = resources.RetrieveQuad("menuicons.png", 2 + 6 * 36, 38, 32, 32, "c_artifact", + RETRIEVE_MANAGE); - LOG("Loading Textures"); - LOG("--Loading menuicons.png"); - resources.RetrieveTexture("menuicons.png",RETRIEVE_MANAGE); - LOG("---Gettings menuicons.png quads"); - //Creating thes quad in this specific order allows us to have them in the correct order to call them by integer id - manaIcons[Constants::MTG_COLOR_GREEN] = resources.RetrieveQuad("menuicons.png", 2 + 0*36, 38, 32, 32, "c_green",RETRIEVE_MANAGE); - manaIcons[Constants::MTG_COLOR_BLUE] = resources.RetrieveQuad("menuicons.png", 2 + 1*36, 38, 32, 32, "c_blue",RETRIEVE_MANAGE); - manaIcons[Constants::MTG_COLOR_RED] = resources.RetrieveQuad("menuicons.png", 2 + 3*36, 38, 32, 32, "c_red",RETRIEVE_MANAGE); - manaIcons[Constants::MTG_COLOR_BLACK] = resources.RetrieveQuad("menuicons.png", 2 + 2*36, 38, 32, 32, "c_black",RETRIEVE_MANAGE); - manaIcons[Constants::MTG_COLOR_WHITE] = resources.RetrieveQuad("menuicons.png", 2 + 4*36, 38, 32, 32, "c_white",RETRIEVE_MANAGE); - manaIcons[Constants::MTG_COLOR_LAND] = resources.RetrieveQuad("menuicons.png", 2 + 5*36, 38, 32, 32, "c_land",RETRIEVE_MANAGE); - manaIcons[Constants::MTG_COLOR_ARTIFACT] = resources.RetrieveQuad("menuicons.png", 2 + 6*36, 38, 32, 32, "c_artifact",RETRIEVE_MANAGE); + for (int i = sizeof(manaIcons) / sizeof(manaIcons[0]) - 1; i >= 0; --i) + if (manaIcons[i]) + manaIcons[i]->SetHotSpot(16, 16); + LOG("--Loading back.jpg"); + resources.RetrieveTexture("back.jpg", RETRIEVE_MANAGE); + JQuad * jq = resources.RetrieveQuad("back.jpg", 0, 0, 0, 0, "back", RETRIEVE_MANAGE); + if (jq) + jq->SetHotSpot(jq->mWidth / 2, jq->mHeight / 2); - for (int i = sizeof(manaIcons)/sizeof(manaIcons[0]) - 1; i >= 0; --i) - if (manaIcons[i]) manaIcons[i]->SetHotSpot(16,16); + resources.RetrieveTexture("back_thumb.jpg", RETRIEVE_MANAGE); + resources.RetrieveQuad("back_thumb.jpg", 0, 0, MTG_MINIIMAGE_WIDTH, MTG_MINIIMAGE_HEIGHT, "back_thumb", RETRIEVE_MANAGE); - LOG("--Loading back.jpg"); - resources.RetrieveTexture("back.jpg",RETRIEVE_MANAGE); - JQuad * jq = resources.RetrieveQuad("back.jpg", 0, 0, 0, 0, "back",RETRIEVE_MANAGE); - if (jq) jq->SetHotSpot(jq->mWidth/2, jq->mHeight/2); + LOG("--Loading particles.png"); + resources.RetrieveTexture("particles.png", RETRIEVE_MANAGE); + jq = resources.RetrieveQuad("particles.png", 0, 0, 32, 32, "particles", RETRIEVE_MANAGE); + if (jq) + jq->SetHotSpot(16, 16); + jq = resources.RetrieveQuad("particles.png", 64, 0, 32, 32, "stars", RETRIEVE_MANAGE); + if (jq) + jq->SetHotSpot(16, 16); - resources.RetrieveTexture("back_thumb.jpg",RETRIEVE_MANAGE); - resources.RetrieveQuad("back_thumb.jpg", 0, 0, MTG_MINIIMAGE_WIDTH, MTG_MINIIMAGE_HEIGHT, "back_thumb",RETRIEVE_MANAGE); + LOG("--Loading fonts"); + string lang = options[Options::LANG].str; + std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower); + resources.InitFonts(lang); - LOG("--Loading particles.png"); - resources.RetrieveTexture("particles.png",RETRIEVE_MANAGE); - jq = resources.RetrieveQuad("particles.png", 0, 0, 32, 32, "particles",RETRIEVE_MANAGE); - if (jq) jq->SetHotSpot(16,16); - jq = resources.RetrieveQuad("particles.png", 64, 0, 32, 32, "stars",RETRIEVE_MANAGE); - if (jq) jq->SetHotSpot(16,16); + LOG("--Loading various textures"); + resources.RetrieveTexture("phasebar.png", RETRIEVE_MANAGE); + resources.RetrieveTexture("wood.png", RETRIEVE_MANAGE); + resources.RetrieveTexture("gold.png", RETRIEVE_MANAGE); + resources.RetrieveTexture("goldglow.png", RETRIEVE_MANAGE); + resources.RetrieveTexture("backdrop.jpg", RETRIEVE_MANAGE); + resources.RetrieveTexture("handback.png", RETRIEVE_MANAGE); + resources.RetrieveTexture("BattleIcon.png", RETRIEVE_MANAGE); + resources.RetrieveTexture("DefenderIcon.png", RETRIEVE_MANAGE); + resources.RetrieveTexture("shadow.png", RETRIEVE_MANAGE); - LOG("--Loading fonts"); - string lang = options[Options::LANG].str; - std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower); - resources.InitFonts(lang); + jq = resources.RetrieveQuad("BattleIcon.png", 0, 0, 25, 25, "BattleIcon", RETRIEVE_MANAGE); + if (jq) + jq->SetHotSpot(12, 12); + jq = resources.RetrieveQuad("DefenderIcon.png", 0, 0, 24, 23, "DefenderIcon", RETRIEVE_MANAGE); + if (jq) + jq->SetHotSpot(12, 12); + jq = resources.RetrieveQuad("shadow.png", 0, 0, 16, 16, "shadow", RETRIEVE_MANAGE); + if (jq) + jq->SetHotSpot(8, 8); + jq = resources.RetrieveQuad("phasebar.png", 0, 0, 0, 0, "phasebar", RETRIEVE_MANAGE); - LOG("--Loading various textures"); - resources.RetrieveTexture("phasebar.png",RETRIEVE_MANAGE); - resources.RetrieveTexture("wood.png",RETRIEVE_MANAGE); - resources.RetrieveTexture("gold.png",RETRIEVE_MANAGE); - resources.RetrieveTexture("goldglow.png",RETRIEVE_MANAGE); - resources.RetrieveTexture("backdrop.jpg",RETRIEVE_MANAGE); - resources.RetrieveTexture("handback.png",RETRIEVE_MANAGE); - resources.RetrieveTexture("BattleIcon.png",RETRIEVE_MANAGE); - resources.RetrieveTexture("DefenderIcon.png",RETRIEVE_MANAGE); - resources.RetrieveTexture("shadow.png",RETRIEVE_MANAGE); + LOG("Init Collection"); + collection = NEW MTGAllCards(); - jq = resources.RetrieveQuad("BattleIcon.png", 0, 0, 25, 25,"BattleIcon",RETRIEVE_MANAGE); - if (jq) jq->SetHotSpot(12, 12); - jq = resources.RetrieveQuad("DefenderIcon.png", 0, 0, 24, 23,"DefenderIcon",RETRIEVE_MANAGE); - if (jq) jq->SetHotSpot(12, 12); - jq = resources.RetrieveQuad("shadow.png", 0, 0, 16, 16,"shadow",RETRIEVE_MANAGE); - if (jq) jq->SetHotSpot(8, 8); - jq = resources.RetrieveQuad("phasebar.png",0,0,0,0,"phasebar",RETRIEVE_MANAGE); + LOG("Creating Game States"); + mGameStates[GAME_STATE_DECK_VIEWER] = NEW GameStateDeckViewer(this); + mGameStates[GAME_STATE_DECK_VIEWER]->Create(); - LOG("Init Collection"); - collection = NEW MTGAllCards(); + mGameStates[GAME_STATE_MENU] = NEW GameStateMenu(this); + mGameStates[GAME_STATE_MENU]->Create(); - LOG("Creating Game States"); - mGameStates[GAME_STATE_DECK_VIEWER] = NEW GameStateDeckViewer(this); - mGameStates[GAME_STATE_DECK_VIEWER]->Create(); + mGameStates[GAME_STATE_DUEL] = NEW GameStateDuel(this); + mGameStates[GAME_STATE_DUEL]->Create(); - mGameStates[GAME_STATE_MENU] = NEW GameStateMenu(this); - mGameStates[GAME_STATE_MENU]->Create(); + mGameStates[GAME_STATE_SHOP] = NEW GameStateShop(this); + mGameStates[GAME_STATE_SHOP]->Create(); - mGameStates[GAME_STATE_DUEL] = NEW GameStateDuel(this); - mGameStates[GAME_STATE_DUEL]->Create(); + mGameStates[GAME_STATE_OPTIONS] = NEW GameStateOptions(this); + mGameStates[GAME_STATE_OPTIONS]->Create(); - mGameStates[GAME_STATE_SHOP] = NEW GameStateShop(this); - mGameStates[GAME_STATE_SHOP]->Create(); + mGameStates[GAME_STATE_AWARDS] = NEW GameStateAwards(this); + mGameStates[GAME_STATE_AWARDS]->Create(); - mGameStates[GAME_STATE_OPTIONS] = NEW GameStateOptions(this); - mGameStates[GAME_STATE_OPTIONS]->Create(); + mGameStates[GAME_STATE_STORY] = NEW GameStateStory(this); + mGameStates[GAME_STATE_STORY]->Create(); - mGameStates[GAME_STATE_AWARDS] = NEW GameStateAwards(this); - mGameStates[GAME_STATE_AWARDS]->Create(); + mGameStates[GAME_STATE_TRANSITION] = NULL; - mGameStates[GAME_STATE_STORY] = NEW GameStateStory(this); - mGameStates[GAME_STATE_STORY]->Create(); + mCurrentState = NULL; + mNextState = mGameStates[GAME_STATE_MENU]; - mGameStates[GAME_STATE_TRANSITION] = NULL; + //Set Audio volume + JSoundSystem::GetInstance()->SetSfxVolume(options[Options::SFXVOLUME].number); + JSoundSystem::GetInstance()->SetMusicVolume(options[Options::MUSICVOLUME].number); - mCurrentState = NULL; - mNextState = mGameStates[GAME_STATE_MENU]; + DebugTrace("size of MTGCard: "<< sizeof(MTGCard)); + DebugTrace("size of CardPrimitive: "<< sizeof(CardPrimitive)); - //Set Audio volume - JSoundSystem::GetInstance()->SetSfxVolume(options[Options::SFXVOLUME].number); - JSoundSystem::GetInstance()->SetMusicVolume(options[Options::MUSICVOLUME].number); - - DebugTrace("size of MTGCard: "<< sizeof(MTGCard)); - DebugTrace("size of CardPrimitive: "<< sizeof(CardPrimitive)); - - LOG("Game Creation Done."); + LOG("Game Creation Done."); } - void GameApp::LoadGameStates() { } - void GameApp::Destroy() { - LOG("==Destroying GameApp=="); - for (int i=GAME_STATE_MENU;i<=GAME_STATE_MAX-1;i++) - { - if (mGameStates[i]){ - mGameStates[i]->Destroy(); - SAFE_DELETE(mGameStates[i]); + LOG("==Destroying GameApp=="); + for (int i = GAME_STATE_MENU; i <= GAME_STATE_MAX - 1; i++) + { + if (mGameStates[i]) + { + mGameStates[i]->Destroy(); + SAFE_DELETE(mGameStates[i]); + } } - } - if (collection){ - collection->destroyAllCards(); - SAFE_DELETE(collection); - } - delete(DeckStats::GetInstance()); + if (collection) + { + collection->destroyAllCards(); + SAFE_DELETE(collection); + } + delete (DeckStats::GetInstance()); - SAFE_DELETE(Subtypes::subtypesList); - SAFE_DELETE(DeckMetaDataList::decksMetaData); + SAFE_DELETE(Subtypes::subtypesList); + SAFE_DELETE(DeckMetaDataList::decksMetaData); - playMusic("none"); + playMusic("none"); - Translator::EndInstance(); - WCFilterFactory::Destroy(); - SimpleMenu::destroy(); - DeckMenu::destroy(); - DeckEditorMenu::destroy(); + Translator::EndInstance(); + WCFilterFactory::Destroy(); + SimpleMenu::destroy(); + DeckMenu::destroy(); + DeckEditorMenu::destroy(); - options.theGame = NULL; - LOG("==Destroying GameApp Successful=="); + options.theGame = NULL; + LOG("==Destroying GameApp Successful=="); } - - void GameApp::Update() { - if (systemError.size()) return; - JGE* mEngine = JGE::GetInstance(); - if (mEngine->GetButtonState(JGE_BTN_MENU) && mEngine->GetButtonClick(JGE_BTN_CANCEL)) + if (systemError.size()) + return; + JGE* mEngine = JGE::GetInstance(); + if (mEngine->GetButtonState(JGE_BTN_MENU) && mEngine->GetButtonClick(JGE_BTN_CANCEL)) { - char s[80]; - sprintf(s, "ms0:/psp/photo/MTG%d.png", mScreenShotCount++); - JRenderer::GetInstance()->ScreenShot(s); + char s[80]; + sprintf(s, "ms0:/psp/photo/MTG%d.png", mScreenShotCount++); + JRenderer::GetInstance()->ScreenShot(s); } - //Exit when START and X ARE PRESSED SIMULTANEOUSLY - if (mEngine->GetButtonState(JGE_BTN_MENU) && mEngine->GetButtonState(JGE_BTN_SEC)){ - mEngine->End(); - return; - } - - //Restart Rendering engine when START and SQUARE ARE PRESSED SIMULTANEOUSLY - if (mEngine->GetButtonState(JGE_BTN_MENU) && mEngine->GetButtonState(JGE_BTN_PRI)) - JRenderer::Destroy(); - - float dt = mEngine->GetDelta(); - if (dt > 35.0f) // min 30 FPS ;) - dt = 35.0f; - - TransitionBase * mTrans = NULL; - if (mCurrentState){ - mCurrentState->Update(dt); - if(mGameStates[GAME_STATE_TRANSITION] == mCurrentState) - mTrans = (TransitionBase *) mGameStates[GAME_STATE_TRANSITION]; - } - //Check for finished transitions. - if(mTrans && mTrans->Finished()){ - mTrans->End(); - if(mTrans->to != NULL && !mTrans->bAnimationOnly){ - mCurrentState = mTrans->to; - SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]); - mCurrentState->Start(); + //Exit when START and X ARE PRESSED SIMULTANEOUSLY + if (mEngine->GetButtonState(JGE_BTN_MENU) && mEngine->GetButtonState(JGE_BTN_SEC)) + { + mEngine->End(); + return; } - else{ - mCurrentState = mTrans->from; - SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]); - } - } - if (mNextState != NULL) - { - if (mCurrentState != NULL) - mCurrentState->End(); - mCurrentState = mNextState; + //Restart Rendering engine when START and SQUARE ARE PRESSED SIMULTANEOUSLY + if (mEngine->GetButtonState(JGE_BTN_MENU) && mEngine->GetButtonState(JGE_BTN_PRI)) + JRenderer::Destroy(); + + float dt = mEngine->GetDelta(); + if (dt > 35.0f) // min 30 FPS ;) + dt = 35.0f; + + TransitionBase * mTrans = NULL; + if (mCurrentState) + { + mCurrentState->Update(dt); + if (mGameStates[GAME_STATE_TRANSITION] == mCurrentState) + mTrans = (TransitionBase *) mGameStates[GAME_STATE_TRANSITION]; + } + //Check for finished transitions. + if (mTrans && mTrans->Finished()) + { + mTrans->End(); + if (mTrans->to != NULL && !mTrans->bAnimationOnly) + { + mCurrentState = mTrans->to; + SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]); + mCurrentState->Start(); + } + else + { + mCurrentState = mTrans->from; + SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]); + } + } + if (mNextState != NULL) + { + if (mCurrentState != NULL) + mCurrentState->End(); + + mCurrentState = mNextState; #if defined (WIN32) || defined (LINUX) #else - /* - int maxLinear = ramAvailableLineareMax(); - int ram = ramAvailable(); - char buf[512]; - sprintf(buf, "Ram : linear max: %i - total : %i\n",maxLinear, ram); - fprintf(stderr,buf); - */ + /* + int maxLinear = ramAvailableLineareMax(); + int ram = ramAvailable(); + char buf[512]; + sprintf(buf, "Ram : linear max: %i - total : %i\n",maxLinear, ram); + fprintf(stderr,buf); + */ #endif - mCurrentState->Start(); - mNextState = NULL; + mCurrentState->Start(); + mNextState = NULL; } } - void GameApp::Render() { - if (systemError.size()){ - fprintf(stderr, "%s", systemError.c_str()); - WFont * mFont= resources.GetWFont(Fonts::MAIN_FONT); - if (mFont) mFont->DrawString(systemError.c_str(),1,1); - return; - } + if (systemError.size()) + { + fprintf(stderr, "%s", systemError.c_str()); + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + if (mFont) + mFont->DrawString(systemError.c_str(), 1, 1); + return; + } - JRenderer * renderer = JRenderer::GetInstance(); - renderer->ClearScreen(ARGB(0,0,0,0)); + JRenderer * renderer = JRenderer::GetInstance(); + renderer->ClearScreen(ARGB(0,0,0,0)); - if (mCurrentState) - mCurrentState->Render(); + if (mCurrentState) + mCurrentState->Render(); #ifdef DEBUG_CACHE - resources.DebugRender(); + resources.DebugRender(); #endif #ifdef DEBUG - JGE* mEngine = JGE::GetInstance(); - float fps = mEngine->GetFPS(); - totalFPS += fps; - nbUpdates+=1; - WFont * mFont= resources.GetWFont(Fonts::MAIN_FONT); - char buf[512]; - sprintf(buf, "avg:%.02f - %.02f fps",totalFPS/nbUpdates, fps); - if (mFont) { - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(buf, 10, SCREEN_HEIGHT-15); - } + JGE* mEngine = JGE::GetInstance(); + float fps = mEngine->GetFPS(); + totalFPS += fps; + nbUpdates+=1; + WFont * mFont= resources.GetWFont(Fonts::MAIN_FONT); + char buf[512]; + sprintf(buf, "avg:%.02f - %.02f fps",totalFPS/nbUpdates, fps); + if (mFont) + { + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(buf, 10, SCREEN_HEIGHT-15); + } #endif } void GameApp::SetNextState(int state) { - mNextState = mGameStates[state]; + mNextState = mGameStates[state]; } -void GameApp::Pause(){ +void GameApp::Pause() +{ } -void GameApp::Resume(){ +void GameApp::Resume() +{ } -void GameApp::DoTransition(int trans, int tostate, float dur, bool animonly){ - TransitionBase * tb = NULL; - GameState * toState = NULL; - if(options[Options::TRANSITIONS].number != 0){ - if(tostate != GAME_STATE_NONE) - SetNextState(tostate); - return; - } +void GameApp::DoTransition(int trans, int tostate, float dur, bool animonly) +{ + TransitionBase * tb = NULL; + GameState * toState = NULL; + if (options[Options::TRANSITIONS].number != 0) + { + if (tostate != GAME_STATE_NONE) + SetNextState(tostate); + return; + } - if(tostate > GAME_STATE_NONE && tostate < GAME_STATE_MAX) - toState = mGameStates[tostate]; + if (tostate > GAME_STATE_NONE && tostate < GAME_STATE_MAX) + toState = mGameStates[tostate]; - if(mGameStates[GAME_STATE_TRANSITION]){ - tb =(TransitionBase*) mGameStates[GAME_STATE_TRANSITION]; - if(toState) - tb->to = toState; //Additional calls to transition merely update the destination. - return; - } + if (mGameStates[GAME_STATE_TRANSITION]) + { + tb = (TransitionBase*) mGameStates[GAME_STATE_TRANSITION]; + if (toState) + tb->to = toState; //Additional calls to transition merely update the destination. + return; + } - if(dur < 0) - dur = DEFAULT_DURATION; // Default to this value. - switch(trans){ + if (dur < 0) + dur = DEFAULT_DURATION; // Default to this value. + switch (trans) + { case TRANSITION_FADE_IN: - tb = NEW TransitionFade(this,mCurrentState,toState,dur,true); - break; + tb = NEW TransitionFade(this, mCurrentState, toState, dur, true); + break; case TRANSITION_FADE: default: - tb = NEW TransitionFade(this,mCurrentState,toState,dur,false); - } - if(tb){ - tb->bAnimationOnly = animonly; - mGameStates[GAME_STATE_TRANSITION] = tb; - mGameStates[GAME_STATE_TRANSITION]->Start(); - mCurrentState = tb; //The old current state is ended inside our transition. - } else if(toState) { //Somehow failed, just do standard SetNextState behaviour - mNextState = toState; - } + tb = NEW TransitionFade(this, mCurrentState, toState, dur, false); + } + if (tb) + { + tb->bAnimationOnly = animonly; + mGameStates[GAME_STATE_TRANSITION] = tb; + mGameStates[GAME_STATE_TRANSITION]->Start(); + mCurrentState = tb; //The old current state is ended inside our transition. + } + else if (toState) + { //Somehow failed, just do standard SetNextState behavior + mNextState = toState; + } } - -void GameApp::DoAnimation(int trans, float dur){ - DoTransition(trans,GAME_STATE_NONE,dur,true); +void GameApp::DoAnimation(int trans, float dur) +{ + DoTransition(trans, GAME_STATE_NONE, dur, true); } -void GameApp::playMusic(string filename, bool loop) { - if (filename.compare(currentMusicFile) == 0) - return; +void GameApp::playMusic(string filename, bool loop) +{ + if (filename.compare(currentMusicFile) == 0) + return; - if (music) { - JSoundSystem::GetInstance()->StopMusic(music); - SAFE_DELETE(music); - } + if (music) + { + JSoundSystem::GetInstance()->StopMusic(music); + SAFE_DELETE(music); + } - if (HasMusic && options[Options::MUSICVOLUME].number > 0){ - music = resources.ssLoadMusic(filename.c_str()); - if (music) JSoundSystem::GetInstance()->PlayMusic(music, loop); - currentMusicFile = filename; - } + if (HasMusic && options[Options::MUSICVOLUME].number > 0) + { + music = resources.ssLoadMusic(filename.c_str()); + if (music) + JSoundSystem::GetInstance()->PlayMusic(music, loop); + currentMusicFile = filename; + } } diff --git a/projects/mtg/src/GameLauncher.cpp b/projects/mtg/src/GameLauncher.cpp index 9fa840245..925f1affd 100644 --- a/projects/mtg/src/GameLauncher.cpp +++ b/projects/mtg/src/GameLauncher.cpp @@ -18,20 +18,19 @@ static char GameName[] = "Wagic"; //------------------------------------------------------------------------------------- JApp* JGameLauncher::GetGameApp() { - return NEW GameApp(); -}; - + return NEW GameApp(); +} +; //------------------------------------------------------------------------------------- char *JGameLauncher::GetName() { - return GameName; + return GameName; } - //------------------------------------------------------------------------------------- u32 JGameLauncher::GetInitFlags() { - return JINIT_FLAG_NORMAL; + return JINIT_FLAG_NORMAL; } diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index f9ae30db7..944e587d9 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -11,652 +11,778 @@ GameObserver * GameObserver::mInstance = NULL; - GameObserver* GameObserver::GetInstance() { - return mInstance; + return mInstance; } void GameObserver::EndInstance() { - SAFE_DELETE(mInstance); + SAFE_DELETE(mInstance); } -void GameObserver::Init(Player * _players[], int _nbplayers){ - mInstance = NEW GameObserver(_players, _nbplayers); +void GameObserver::Init(Player * _players[], int _nbplayers) +{ + mInstance = NEW GameObserver(_players, _nbplayers); } - -GameObserver::GameObserver(Player * _players[], int _nb_players){ - for (int i = 0; i < _nb_players;i ++){ - players[i] = _players[i]; - } - currentPlayer = NULL; - currentActionPlayer = NULL; - isInterrupting = NULL; - currentPlayerId = 0; - nbPlayers = _nb_players; - currentGamePhase = -1; - targetChooser = NULL; - cardWaitingForTargets = NULL; - waitForExtraPayment = NULL; - reaction = 0; - gameOver = NULL; - phaseRing = NULL; - replacementEffects = NEW ReplacementEffects(); - combatStep = BLOCKERS; - mRules = NULL; -} - -int GameObserver::getCurrentGamePhase(){ - return currentGamePhase; -} - - -Player * GameObserver::opponent(){ - int index = (currentPlayerId+1)%nbPlayers; - return players[index]; -} - - -void GameObserver::nextPlayer(){ - turn++; - currentPlayerId = (currentPlayerId+1)%nbPlayers; - currentPlayer = players[currentPlayerId]; - currentActionPlayer = currentPlayer; - combatStep = BLOCKERS; -} -void GameObserver::nextGamePhase(){ - Phase * cPhaseOld = phaseRing->getCurrentPhase(); - if (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE) - if (FIRST_STRIKE == combatStep || END_FIRST_STRIKE == combatStep || DAMAGE == combatStep) { - nextCombatStep(); return; - } - - if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS) - if (BLOCKERS == combatStep || TRIGGERS == combatStep) { nextCombatStep(); return; } - - phaseRing->forward(); - - //Go directly to end of combat if no attackers - if (cPhaseOld->id == Constants::MTG_PHASE_COMBATATTACKERS && !(currentPlayer->game->inPlay->getNextAttacker(NULL))){ - phaseRing->forward(); - phaseRing->forward(); - } - - Phase * cPhase = phaseRing->getCurrentPhase(); - currentGamePhase = cPhase->id; - - if (Constants::MTG_PHASE_COMBATDAMAGE == currentGamePhase) - nextCombatStep(); - - if (currentPlayer != cPhase->player) nextPlayer(); - - - //init begin of turn - if (currentGamePhase == Constants::MTG_PHASE_BEFORE_BEGIN){ - cleanupPhase(); - currentPlayer->canPutLandsIntoPlay = 1; - currentPlayer->castedspellsthisturn = 0; - currentPlayer->opponent()->castedspellsthisturn = 0; - currentPlayer->castcount = 0; - currentPlayer->nocreatureinstant = 0; - currentPlayer->nospellinstant = 0; - currentPlayer->onlyoneinstant = 0; - currentPlayer->damageCount = 0; - currentPlayer->preventable = 0; - mLayers->actionLayer()->cleanGarbage(); //clean abilities history for this turn; - mLayers->stackLayer()->garbageCollect(); //clean stack history for this turn; - mLayers->actionLayer()->Update(0); - for (int i=0; i < 2; i++){ - delete (players[i]->game->garbage); - players[i]->game->garbage = NEW MTGGameZone(); - players[i]->game->garbage->setOwner(players[i]); +GameObserver::GameObserver(Player * _players[], int _nb_players) +{ + for (int i = 0; i < _nb_players; i++) + { + players[i] = _players[i]; } + currentPlayer = NULL; + currentActionPlayer = NULL; + isInterrupting = NULL; + currentPlayerId = 0; + nbPlayers = _nb_players; + currentGamePhase = -1; + targetChooser = NULL; + cardWaitingForTargets = NULL; + waitForExtraPayment = NULL; + reaction = 0; + gameOver = NULL; + phaseRing = NULL; + replacementEffects = NEW ReplacementEffects(); combatStep = BLOCKERS; - return nextGamePhase(); - } - - for (int i = 0; i < 2; ++i) - players[i]->getManaPool()->init(); - - if (currentGamePhase == Constants::MTG_PHASE_AFTER_EOT){ - //Auto Hand cleaning, in case the player didn't do it himself - while(currentPlayer->game->hand->nb_cards > 7 && currentPlayer->nomaxhandsize < 1) - currentPlayer->game->putInGraveyard(currentPlayer->game->hand->cards[0]); - mLayers->actionLayer()->Update(0); - return nextGamePhase(); - } - - //Phase Specific actions - switch(currentGamePhase){ - case Constants::MTG_PHASE_UNTAP: - untapPhase(); - break; - case Constants::MTG_PHASE_DRAW: - //mLayers->stackLayer()->addDraw(currentPlayer,1); - break; - case Constants::MTG_PHASE_COMBATBLOCKERS: - receiveEvent(NEW WEventAttackersChosen()); - break; - default: - break; - } + mRules = NULL; } -int GameObserver::cancelCurrentAction(){ - SAFE_DELETE(targetChooser); - return mLayers->actionLayer()->cancelCurrentAction(); +int GameObserver::getCurrentGamePhase() +{ + return currentGamePhase; +} + +Player * GameObserver::opponent() +{ + int index = (currentPlayerId + 1) % nbPlayers; + return players[index]; +} + +void GameObserver::nextPlayer() +{ + turn++; + currentPlayerId = (currentPlayerId + 1) % nbPlayers; + currentPlayer = players[currentPlayerId]; + currentActionPlayer = currentPlayer; + combatStep = BLOCKERS; +} +void GameObserver::nextGamePhase() +{ + Phase * cPhaseOld = phaseRing->getCurrentPhase(); + if (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE) + if (FIRST_STRIKE == combatStep || END_FIRST_STRIKE == combatStep || DAMAGE == combatStep) + { + nextCombatStep(); + return; + } + + if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS) + if (BLOCKERS == combatStep || TRIGGERS == combatStep) + { + nextCombatStep(); + return; + } + + phaseRing->forward(); + + //Go directly to end of combat if no attackers + if (cPhaseOld->id == Constants::MTG_PHASE_COMBATATTACKERS && !(currentPlayer->game->inPlay->getNextAttacker(NULL))) + { + phaseRing->forward(); + phaseRing->forward(); + } + + Phase * cPhase = phaseRing->getCurrentPhase(); + currentGamePhase = cPhase->id; + + if (Constants::MTG_PHASE_COMBATDAMAGE == currentGamePhase) + nextCombatStep(); + + if (currentPlayer != cPhase->player) + nextPlayer(); + + //init begin of turn + if (currentGamePhase == Constants::MTG_PHASE_BEFORE_BEGIN) + { + cleanupPhase(); + currentPlayer->canPutLandsIntoPlay = 1; + currentPlayer->castedspellsthisturn = 0; + currentPlayer->opponent()->castedspellsthisturn = 0; + currentPlayer->castcount = 0; + currentPlayer->nocreatureinstant = 0; + currentPlayer->nospellinstant = 0; + currentPlayer->onlyoneinstant = 0; + currentPlayer->damageCount = 0; + currentPlayer->preventable = 0; + mLayers->actionLayer()->cleanGarbage(); //clean abilities history for this turn; + mLayers->stackLayer()->garbageCollect(); //clean stack history for this turn; + mLayers->actionLayer()->Update(0); + for (int i = 0; i < 2; i++) + { + delete (players[i]->game->garbage); + players[i]->game->garbage = NEW MTGGameZone(); + players[i]->game->garbage->setOwner(players[i]); + } + combatStep = BLOCKERS; + return nextGamePhase(); + } + + for (int i = 0; i < 2; ++i) + players[i]->getManaPool()->init(); + + if (currentGamePhase == Constants::MTG_PHASE_AFTER_EOT) + { + //Auto Hand cleaning, in case the player didn't do it himself + while (currentPlayer->game->hand->nb_cards > 7 && currentPlayer->nomaxhandsize < 1) + currentPlayer->game->putInGraveyard(currentPlayer->game->hand->cards[0]); + mLayers->actionLayer()->Update(0); + return nextGamePhase(); + } + + //Phase Specific actions + switch (currentGamePhase) + { + case Constants::MTG_PHASE_UNTAP: + untapPhase(); + break; + case Constants::MTG_PHASE_DRAW: + //mLayers->stackLayer()->addDraw(currentPlayer,1); + break; + case Constants::MTG_PHASE_COMBATBLOCKERS: + receiveEvent(NEW WEventAttackersChosen()); + break; + default: + break; + } +} + +int GameObserver::cancelCurrentAction() +{ + SAFE_DELETE(targetChooser); + return mLayers->actionLayer()->cancelCurrentAction(); } void GameObserver::nextCombatStep() { - switch (combatStep) + switch (combatStep) { - case BLOCKERS : - receiveEvent(NEW WEventBlockersChosen()); - receiveEvent(NEW WEventCombatStepChange(combatStep = TRIGGERS)); - return; + case BLOCKERS: + receiveEvent(NEW WEventBlockersChosen()); + receiveEvent(NEW WEventCombatStepChange(combatStep = TRIGGERS)); + return; - case TRIGGERS : receiveEvent(NEW WEventCombatStepChange(combatStep = ORDER)); return; - case ORDER : receiveEvent(NEW WEventCombatStepChange(combatStep = FIRST_STRIKE)); return; - case FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = END_FIRST_STRIKE)); return; - case END_FIRST_STRIKE : receiveEvent(NEW WEventCombatStepChange(combatStep = DAMAGE)); return; - case DAMAGE : receiveEvent(NEW WEventCombatStepChange(combatStep = END_DAMAGE)); return; - case END_DAMAGE : ; // Nothing : go to next phase + case TRIGGERS: + receiveEvent(NEW WEventCombatStepChange(combatStep = ORDER)); + return; + case ORDER: + receiveEvent(NEW WEventCombatStepChange(combatStep = FIRST_STRIKE)); + return; + case FIRST_STRIKE: + receiveEvent(NEW WEventCombatStepChange(combatStep = END_FIRST_STRIKE)); + return; + case END_FIRST_STRIKE: + receiveEvent(NEW WEventCombatStepChange(combatStep = DAMAGE)); + return; + case DAMAGE: + receiveEvent(NEW WEventCombatStepChange(combatStep = END_DAMAGE)); + return; + case END_DAMAGE: + ; // Nothing : go to next phase } } -void GameObserver::userRequestNextGamePhase(){ - if (mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)) return; - if (getCurrentTargetChooser()) return; +void GameObserver::userRequestNextGamePhase() +{ + if (mLayers->stackLayer()->getNext(NULL, 0, NOT_RESOLVED)) + return; + if (getCurrentTargetChooser()) + return; - bool executeNextPhaseImmediately = true; + bool executeNextPhaseImmediately = true; - Phase * cPhaseOld = phaseRing->getCurrentPhase(); - if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) || - (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS)|| - cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE || - opponent()->isAI() || - options[Options::optionInterrupt(currentGamePhase)].number) - { - executeNextPhaseImmediately = false; - } + Phase * cPhaseOld = phaseRing->getCurrentPhase(); + if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) || (cPhaseOld->id + == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS) || cPhaseOld->id + == Constants::MTG_PHASE_COMBATDAMAGE || opponent()->isAI() + || options[Options::optionInterrupt(currentGamePhase)].number) + { + executeNextPhaseImmediately = false; + } - if (executeNextPhaseImmediately) - { - nextGamePhase(); - } - else - { - mLayers->stackLayer()->AddNextGamePhase(); - } + if (executeNextPhaseImmediately) + { + nextGamePhase(); + } + else + { + mLayers->stackLayer()->AddNextGamePhase(); + } } -int GameObserver::forceShuffleLibraries(){ - int result = 0; - if (players[0]->game->library->needShuffle) +int GameObserver::forceShuffleLibraries() +{ + int result = 0; + if (players[0]->game->library->needShuffle) { - players[0]->game->library->shuffle(); - players[0]->game->library->needShuffle = false; - ++result; + players[0]->game->library->shuffle(); + players[0]->game->library->needShuffle = false; + ++result; } - if (players[1]->game->library->needShuffle) + if (players[1]->game->library->needShuffle) { - players[1]->game->library->shuffle(); - players[1]->game->library->needShuffle = false; - ++result; + players[1]->game->library->shuffle(); + players[1]->game->library->needShuffle = false; + ++result; } - return result; + return result; } -void GameObserver::startGame(Rules * rules){ - turn = 0; - mRules = rules; - if (rules) - rules->initPlayers(); - - options.automaticStyle(players[0],players[1]); +void GameObserver::startGame(Rules * rules) +{ + turn = 0; + mRules = rules; + if (rules) + rules->initPlayers(); - mLayers = NEW DuelLayers(); - mLayers->init(); + options.automaticStyle(players[0], players[1]); - currentPlayerId = 0; - currentPlayer = players[0]; - currentActionPlayer = currentPlayer; - phaseRing = NEW PhaseRing(players,nbPlayers); - if (rules) - rules->initGame(); + mLayers = NEW DuelLayers(); + mLayers->init(); - + currentPlayerId = 0; + currentPlayer = players[0]; + currentActionPlayer = currentPlayer; + phaseRing = NEW PhaseRing(players, nbPlayers); + if (rules) + rules->initGame(); - //Preload images from hand - if (!players[0]->isAI()){ - for (int i=0; i< players[0]->game->hand->nb_cards; i++){ - resources.RetrieveCard(players[0]->game->hand->cards[i],CACHE_THUMB); - resources.RetrieveCard(players[0]->game->hand->cards[i]); - } - } - - startedAt = time(0); - - - //Difficult mode special stuff - if (!players[0]->isAI() && players[1]->isAI()){ - int difficulty = options[Options::DIFFICULTY].number; - if (options[Options::DIFFICULTY_MODE_UNLOCKED].number && difficulty) { - Player * p = players[1]; - for (int level=0; level < difficulty; level ++){ - MTGCardInstance * card = NULL; - MTGGameZone * z = p->game->library; - for (int j = 0; jnb_cards; j++){ - MTGCardInstance * _card = z->cards[j]; - if (_card->hasType("land")){ - card = _card; - j = z->nb_cards; - } + //Preload images from hand + if (!players[0]->isAI()) + { + for (int i = 0; i < players[0]->game->hand->nb_cards; i++) + { + resources.RetrieveCard(players[0]->game->hand->cards[i], CACHE_THUMB); + resources.RetrieveCard(players[0]->game->hand->cards[i]); + } + } + + startedAt = time(0); + + //Difficult mode special stuff + if (!players[0]->isAI() && players[1]->isAI()) + { + int difficulty = options[Options::DIFFICULTY].number; + if (options[Options::DIFFICULTY_MODE_UNLOCKED].number && difficulty) + { + Player * p = players[1]; + for (int level = 0; level < difficulty; level++) + { + MTGCardInstance * card = NULL; + MTGGameZone * z = p->game->library; + for (int j = 0; j < z->nb_cards; j++) + { + MTGCardInstance * _card = z->cards[j]; + if (_card->hasType("land")) + { + card = _card; + j = z->nb_cards; + } + } + if (card) + { + MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); + Spell * spell = NEW Spell(copy); + spell->resolve(); + delete spell; + } + } } - if (card){ - MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); - Spell * spell = NEW Spell(copy); - spell->resolve(); - delete spell; - } - } } - } } -void GameObserver::addObserver(MTGAbility * observer){ - mLayers->actionLayer()->Add(observer); +void GameObserver::addObserver(MTGAbility * observer) +{ + mLayers->actionLayer()->Add(observer); } +void GameObserver::removeObserver(ActionElement * observer) +{ + if (observer) + mLayers->actionLayer()->moveToGarbage(observer); -void GameObserver::removeObserver(ActionElement * observer){ - if (observer)mLayers->actionLayer()->moveToGarbage(observer); - - else - {} //TODO log error + else + { + } //TODO log error } -GameObserver::~GameObserver(){ - LOG("==Destroying GameObserver=="); - SAFE_DELETE(targetChooser); - SAFE_DELETE(mLayers); - SAFE_DELETE(phaseRing); - SAFE_DELETE(replacementEffects); - for (int i = 0; i < nbPlayers; ++i){ - SAFE_DELETE(players[i]); - } - LOG("==GameObserver Destroyed=="); +GameObserver::~GameObserver() +{ + LOG("==Destroying GameObserver=="); + SAFE_DELETE(targetChooser); + SAFE_DELETE(mLayers); + SAFE_DELETE(phaseRing); + SAFE_DELETE(replacementEffects); + for (int i = 0; i < nbPlayers; ++i) + { + SAFE_DELETE(players[i]); + } + LOG("==GameObserver Destroyed=="); } -void GameObserver::Update(float dt){ - Player * player = currentPlayer; - if (Constants::MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep) - player = player->opponent(); +void GameObserver::Update(float dt) +{ + Player * player = currentPlayer; + if (Constants::MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep) + player = player->opponent(); - currentActionPlayer = player; - if (isInterrupting) player = isInterrupting; - mLayers->Update(dt,player); + currentActionPlayer = player; + if (isInterrupting) + player = isInterrupting; + mLayers->Update(dt, player); - while (mLayers->actionLayer()->stuffHappened){ - mLayers->actionLayer()->Update(0); - } - stateEffects(); - oldGamePhase = currentGamePhase; + while (mLayers->actionLayer()->stuffHappened) + { + mLayers->actionLayer()->Update(0); + } + stateEffects(); + oldGamePhase = currentGamePhase; - - if (combatStep == TRIGGERS) - { - if (!mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)) - { - mLayers->stackLayer()->AddNextCombatStep(); - } - } + if (combatStep == TRIGGERS) + { + if (!mLayers->stackLayer()->getNext(NULL, 0, NOT_RESOLVED)) + { + mLayers->stackLayer()->AddNextCombatStep(); + } + } //Auto skip Phases - int skipLevel = (player->playMode == Player::MODE_TEST_SUITE) ? Constants::ASKIP_NONE : - options[Options::ASPHASES].number; - int nrCreatures = currentPlayer->game->inPlay->countByType("Creature"); + int skipLevel = (player->playMode == Player::MODE_TEST_SUITE) ? Constants::ASKIP_NONE : options[Options::ASPHASES].number; + int nrCreatures = currentPlayer->game->inPlay->countByType("Creature"); - if (skipLevel == Constants::ASKIP_SAFE || skipLevel == Constants::ASKIP_FULL) { - if ((opponent()->isAI() && !(isInterrupting)) && - ( - currentGamePhase == Constants::MTG_PHASE_UNTAP - || currentGamePhase == Constants::MTG_PHASE_DRAW - || currentGamePhase == Constants::MTG_PHASE_COMBATBEGIN - || ((currentGamePhase == Constants::MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0)) - || currentGamePhase == Constants::MTG_PHASE_COMBATEND - || currentGamePhase == Constants::MTG_PHASE_ENDOFTURN - || ((currentGamePhase == Constants::MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8)) - )) - userRequestNextGamePhase(); - } - if (skipLevel == Constants::ASKIP_FULL) { - if ((opponent()->isAI() && !(isInterrupting)) && - (currentGamePhase == Constants::MTG_PHASE_UPKEEP - || currentGamePhase == Constants::MTG_PHASE_COMBATDAMAGE - )) - userRequestNextGamePhase(); + if (skipLevel == Constants::ASKIP_SAFE || skipLevel == Constants::ASKIP_FULL) + { + if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == Constants::MTG_PHASE_UNTAP || currentGamePhase + == Constants::MTG_PHASE_DRAW || currentGamePhase == Constants::MTG_PHASE_COMBATBEGIN || ((currentGamePhase + == Constants::MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0)) || currentGamePhase + == Constants::MTG_PHASE_COMBATEND || currentGamePhase == Constants::MTG_PHASE_ENDOFTURN + || ((currentGamePhase == Constants::MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8)))) + userRequestNextGamePhase(); + } + if (skipLevel == Constants::ASKIP_FULL) + { + if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == Constants::MTG_PHASE_UPKEEP || currentGamePhase + == Constants::MTG_PHASE_COMBATDAMAGE)) + userRequestNextGamePhase(); - } + } } - + //applies damage to creatures after updates //Players life test void GameObserver::stateEffects() { - if (mLayers->stackLayer()->count(0,NOT_RESOLVED) != 0) return; - if (mLayers->actionLayer()->menuObject) return; - if (targetChooser || mLayers->actionLayer()->isWaitingForAnswer()) return; - for (int i =0; i < 2; i++){ - MTGGameZone * zone = players[i]->game->inPlay; - for (int j = zone->nb_cards-1 ; j>=0; j--){ - MTGCardInstance * card = zone->cards[j]; - card->afterDamage(); + if (mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0) + return; + if (mLayers->actionLayer()->menuObject) + return; + if (targetChooser || mLayers->actionLayer()->isWaitingForAnswer()) + return; + for (int i = 0; i < 2; i++) + { + MTGGameZone * zone = players[i]->game->inPlay; + for (int j = zone->nb_cards - 1; j >= 0; j--) + { + MTGCardInstance * card = zone->cards[j]; + card->afterDamage(); - //Remove auras that don't have a valid target anymore - if (card->target && !isInPlay(card->target) && !card->hasType("equipment")){ - players[i]->game->putInGraveyard(card); - } + //Remove auras that don't have a valid target anymore + if (card->target && !isInPlay(card->target) && !card->hasType("equipment")) + { + players[i]->game->putInGraveyard(card); + } + } } - } - for (int i =0; i < 2; i++) - if (players[i]->life <= 0){ - int cantlosers = 0; - MTGGameZone * z = players[i]->game->inPlay; - int nbcards = z->nb_cards; - for (int j = 0; j < nbcards; ++j){ - MTGCardInstance * c = z->cards[j]; - if (c->has(Constants::CANTLOSE) || c->has(Constants::CANTLIFELOSE)){ - cantlosers++; - } - } - MTGGameZone * k = players[i]->opponent()->game->inPlay; - int onbcards = k->nb_cards; - for (int m = 0; m < onbcards; ++m){ - MTGCardInstance * e = k->cards[m]; - if (e->has(Constants::CANTWIN)){ - cantlosers++; - } - } - if(cantlosers < 1){ - gameOver = players[i]; - } - } + for (int i = 0; i < 2; i++) + if (players[i]->life <= 0) + { + int cantlosers = 0; + MTGGameZone * z = players[i]->game->inPlay; + int nbcards = z->nb_cards; + for (int j = 0; j < nbcards; ++j) + { + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::CANTLOSE) || c->has(Constants::CANTLIFELOSE)) + { + cantlosers++; + } + } + MTGGameZone * k = players[i]->opponent()->game->inPlay; + int onbcards = k->nb_cards; + for (int m = 0; m < onbcards; ++m) + { + MTGCardInstance * e = k->cards[m]; + if (e->has(Constants::CANTWIN)) + { + cantlosers++; + } + } + if (cantlosers < 1) + { + gameOver = players[i]; + } + } - for (int i =0; i < 2; i++) - if (players[i]->poisonCount >= 10) gameOver = players[i]; + for (int i = 0; i < 2; i++) + if (players[i]->poisonCount >= 10) + gameOver = players[i]; } - void GameObserver::Render() { - mLayers->Render(); - if (targetChooser || mLayers->actionLayer()->isWaitingForAnswer()) - JRenderer::GetInstance()->DrawRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(255,255,0,0)); - if (waitForExtraPayment) - waitForExtraPayment->Render(); - for (int i = 0; i < nbPlayers; ++i){ - players[i]->Render(); - } -} - - - - -void GameObserver::ButtonPressed(PlayGuiObject * target){ - DebugTrace("GAMEOBSERVER Click"); - if (CardView* cardview = dynamic_cast(target)){ - MTGCardInstance * card = cardview->getCard(); - cardClick(card, card); - } - else if (GuiLibrary* library = dynamic_cast(target)){ - if (library->showCards){ - library->toggleDisplay(); - forceShuffleLibraries(); - } else { - TargetChooser * _tc = this->getCurrentTargetChooser(); - if (_tc && _tc->targetsZone(library->zone)){ - library->toggleDisplay(); - library->zone->needShuffle = true; - } - } - } - else if (GuiGraveyard* graveyard = dynamic_cast(target)) - graveyard->toggleDisplay(); -//opponenthand - else if (GuiOpponentHand* opponentHand = dynamic_cast(target)) - if (opponentHand->showCards){ - opponentHand->toggleDisplay(); - } else { - TargetChooser * _tc = this->getCurrentTargetChooser(); - if (_tc && _tc->targetsZone(opponentHand->zone)){ - opponentHand->toggleDisplay(); - } - } -//end opponenthand - else if (GuiAvatar* avatar = dynamic_cast(target)){ - cardClick(NULL, avatar->player); - } -} - -void GameObserver::stackObjectClicked(Interruptible * action){ - if (targetChooser != NULL){ - int result = targetChooser->toggleTarget(action); - if (result == TARGET_OK_FULL){ - cardClick(cardWaitingForTargets); - }else{ - return; - } - }else{ - reaction = mLayers->actionLayer()->isReactingToTargetClick(action); - if (reaction == -1) mLayers->actionLayer()->reactToTargetClick(action); - } -} - -void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){ - Player * clickedPlayer = NULL; - if (!card) clickedPlayer = ((Player *)object); - if (targetChooser){ - int result; - if (card) { - if (card == cardWaitingForTargets){ - int _result = targetChooser->ForceTargetListReady(); - if (_result){ - result = TARGET_OK_FULL; - }else{ - result = targetChooser->targetsReadyCheck(); - } - }else{ - result = targetChooser->toggleTarget(card); - } - }else{ - result = targetChooser->toggleTarget(clickedPlayer); - } - if (result == TARGET_OK_FULL) - card = cardWaitingForTargets; - else - return; - } - - if (waitForExtraPayment){ - if (card){ - waitForExtraPayment->tryToSetPayment(card); - } - if (waitForExtraPayment->isPaymentSet()){ - mLayers->actionLayer()->reactToClick(waitForExtraPayment->action, waitForExtraPayment->source); - waitForExtraPayment = NULL; - } - return; - } - - if (ORDER == combatStep) + mLayers->Render(); + if (targetChooser || mLayers->actionLayer()->isWaitingForAnswer()) + JRenderer::GetInstance()->DrawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(255,255,0,0)); + if (waitForExtraPayment) + waitForExtraPayment->Render(); + for (int i = 0; i < nbPlayers; ++i) { - card->defenser->raiseBlockerRankOrder(card); - return; + players[i]->Render(); + } +} + +void GameObserver::ButtonPressed(PlayGuiObject * target) +{ + DebugTrace("GAMEOBSERVER Click"); + if (CardView* cardview = dynamic_cast(target)) + { + MTGCardInstance * card = cardview->getCard(); + cardClick(card, card); + } + else if (GuiLibrary* library = dynamic_cast(target)) + { + if (library->showCards) + { + library->toggleDisplay(); + forceShuffleLibraries(); + } + else + { + TargetChooser * _tc = this->getCurrentTargetChooser(); + if (_tc && _tc->targetsZone(library->zone)) + { + library->toggleDisplay(); + library->zone->needShuffle = true; + } + } + } + else if (GuiGraveyard* graveyard = dynamic_cast(target)) + graveyard->toggleDisplay(); + //opponenthand + else if (GuiOpponentHand* opponentHand = dynamic_cast(target)) + if (opponentHand->showCards) + { + opponentHand->toggleDisplay(); + } + else + { + TargetChooser * _tc = this->getCurrentTargetChooser(); + if (_tc && _tc->targetsZone(opponentHand->zone)) + { + opponentHand->toggleDisplay(); + } + } + //end opponenthand + else if (GuiAvatar* avatar = dynamic_cast(target)) + { + cardClick(NULL, avatar->player); + } +} + +void GameObserver::stackObjectClicked(Interruptible * action) +{ + if (targetChooser != NULL) + { + int result = targetChooser->toggleTarget(action); + if (result == TARGET_OK_FULL) + { + cardClick(cardWaitingForTargets); + } + else + { + return; + } + } + else + { + reaction = mLayers->actionLayer()->isReactingToTargetClick(action); + if (reaction == -1) + mLayers->actionLayer()->reactToTargetClick(action); + } +} + +void GameObserver::cardClick(MTGCardInstance * card, Targetable * object) +{ + Player * clickedPlayer = NULL; + if (!card) + clickedPlayer = ((Player *) object); + if (targetChooser) + { + int result; + if (card) + { + if (card == cardWaitingForTargets) + { + int _result = targetChooser->ForceTargetListReady(); + if (_result) + { + result = TARGET_OK_FULL; + } + else + { + result = targetChooser->targetsReadyCheck(); + } + } + else + { + result = targetChooser->toggleTarget(card); + } + } + else + { + result = targetChooser->toggleTarget(clickedPlayer); + } + if (result == TARGET_OK_FULL) + card = cardWaitingForTargets; + else + return; } - if (card && card->paymenttype <= 0){//card played as normal. - - /* Fix for Issue http://code.google.com/p/wagic/issues/detail?id=270 - put into play is hopefully the only ability causing that kind of trouble - If the same kind of issue occurs with other abilities, let's think of a cleaner solution - */ - if (targetChooser) { - MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY); - a->reactToClick(card); - return; + if (waitForExtraPayment) + { + if (card) + { + waitForExtraPayment->tryToSetPayment(card); + } + if (waitForExtraPayment->isPaymentSet()) + { + mLayers->actionLayer()->reactToClick(waitForExtraPayment->action, waitForExtraPayment->source); + waitForExtraPayment = NULL; + } + return; } - reaction = mLayers->actionLayer()->isReactingToClick(card); - if (reaction == -1) mLayers->actionLayer()->reactToClick(card); - } - /* added same fix for buyback and alternative cost, the varible "paymenttype = int" only serves one purpose, to tell this bug fix what menu item you clicked on...all alternative cost or play methods suffered from the fix because if the card contained "target=" it would automatically force the play method to putinplayrule...even charge you the original mana cost.*/ - else if (card && card->paymenttype == 1){//this is alternitive cost - if (targetChooser) { - MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::ALTERNATIVE_COST); - a->reactToClick(card); - return; + if (ORDER == combatStep) + { + card->defenser->raiseBlockerRankOrder(card); + return; } - reaction = mLayers->actionLayer()->isReactingToClick(card); - if (reaction == -1) mLayers->actionLayer()->reactToClick(card); - } -//-------------- - else if (card && card->paymenttype == 2){//this is buyback - if (targetChooser) { - MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::BUYBACK_COST); - a->reactToClick(card); - return; + if (card && card->paymenttype <= 0) + {//card played as normal. + + /* Fix for Issue http://code.google.com/p/wagic/issues/detail?id=270 + put into play is hopefully the only ability causing that kind of trouble + If the same kind of issue occurs with other abilities, let's think of a cleaner solution + */ + if (targetChooser) + { + MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY); + a->reactToClick(card); + return; + } + + reaction = mLayers->actionLayer()->isReactingToClick(card); + if (reaction == -1) + mLayers->actionLayer()->reactToClick(card); + } + /* added same fix for buyback and alternative cost, the varible "paymenttype = int" only serves one purpose, to tell this bug fix what menu item you clicked on...all alternative cost or play methods suffered from the fix because if the card contained "target=" it would automatically force the play method to putinplayrule...even charge you the original mana cost.*/ + else if (card && card->paymenttype == 1) + {//this is alternitive cost + if (targetChooser) + { + MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::ALTERNATIVE_COST); + a->reactToClick(card); + return; + } + + reaction = mLayers->actionLayer()->isReactingToClick(card); + if (reaction == -1) + mLayers->actionLayer()->reactToClick(card); + } + //-------------- + else if (card && card->paymenttype == 2) + {//this is buyback + if (targetChooser) + { + MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::BUYBACK_COST); + a->reactToClick(card); + return; + } + + reaction = mLayers->actionLayer()->isReactingToClick(card); + if (reaction == -1) + mLayers->actionLayer()->reactToClick(card); + } + //===================== + else if (card && card->paymenttype == 3) + {//this is Flashback + if (targetChooser) + { + MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::FLASHBACK_COST); + a->reactToClick(card); + return; + } + + reaction = mLayers->actionLayer()->isReactingToClick(card); + if (reaction == -1) + mLayers->actionLayer()->reactToClick(card); + } + //===================== + else if (card && card->paymenttype == 4) + {//this is retrace + if (targetChooser) + { + MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::RETRACE_COST); + a->reactToClick(card); + return; + } + + reaction = mLayers->actionLayer()->isReactingToClick(card); + if (reaction == -1) + mLayers->actionLayer()->reactToClick(card); + } + //===================== + else + {//this handles abilities on a menu...not just when card is being played + reaction = mLayers->actionLayer()->isReactingToTargetClick(object); + if (reaction == -1) + mLayers->actionLayer()->reactToTargetClick(object); } - reaction = mLayers->actionLayer()->isReactingToClick(card); - if (reaction == -1) mLayers->actionLayer()->reactToClick(card); - } - //===================== - else if (card && card->paymenttype == 3){//this is Flashback - if (targetChooser) { - MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::FLASHBACK_COST); - a->reactToClick(card); - return; + if (reaction == -1) + return; + + if (!card) + return; + + //Current player's hand + if (currentPlayer->game->hand->hasCard(card) && currentGamePhase == Constants::MTG_PHASE_CLEANUP + && currentPlayer->game->hand->nb_cards > 7 && currentPlayer->nomaxhandsize < 1) + { + currentPlayer->game->putInGraveyard(card); } - - reaction = mLayers->actionLayer()->isReactingToClick(card); - if (reaction == -1) mLayers->actionLayer()->reactToClick(card); - } - //===================== - else if (card && card->paymenttype == 4){//this is retrace - if (targetChooser) { - MTGAbility * a = mLayers->actionLayer()->getAbility(MTGAbility::RETRACE_COST); - a->reactToClick(card); - return; + else if (reaction) + { + if (reaction == 1) + { + mLayers->actionLayer()->reactToClick(card); + } + else + { + mLayers->actionLayer()->setMenuObject(object); + } } - - reaction = mLayers->actionLayer()->isReactingToClick(card); - if (reaction == -1) mLayers->actionLayer()->reactToClick(card); - } - //===================== - else{//this handles abilities on a menu...not just when card is being played - reaction = mLayers->actionLayer()->isReactingToTargetClick(object); - if (reaction == -1) mLayers->actionLayer()->reactToTargetClick(object); - } - - if (reaction == -1) return; - - if (!card) return; - - //Current player's hand - if (currentPlayer->game->hand->hasCard(card) && currentGamePhase == Constants::MTG_PHASE_CLEANUP && currentPlayer->game->hand->nb_cards > 7 && currentPlayer->nomaxhandsize < 1){ - currentPlayer->game->putInGraveyard(card); - }else if (reaction){ - if (reaction == 1){ - mLayers->actionLayer()->reactToClick(card); - }else{ - mLayers->actionLayer()->setMenuObject(object); + else if (card->isTapped() && card->controller() == currentPlayer) + { + untap(card); } - }else if (card->isTapped() && card->controller() == currentPlayer){ - untap(card); - } - - } - -int GameObserver::untap(MTGCardInstance * card) { - if (!card->isUntapping()){ - return 0; - } - if (card->has(Constants::DOESNOTUNTAP)) return 0; - if (card->frozen > 0) return 0; - card->attemptUntap(); - return 1; +int GameObserver::untap(MTGCardInstance * card) +{ + if (!card->isUntapping()) + { + return 0; + } + if (card->has(Constants::DOESNOTUNTAP)) + return 0; + if (card->frozen > 0) + return 0; + card->attemptUntap(); + return 1; } -TargetChooser * GameObserver::getCurrentTargetChooser(){ - TargetChooser * _tc = mLayers->actionLayer()->getCurrentTargetChooser(); - if (_tc) return _tc; - return targetChooser; +TargetChooser * GameObserver::getCurrentTargetChooser() +{ + TargetChooser * _tc = mLayers->actionLayer()->getCurrentTargetChooser(); + if (_tc) + return _tc; + return targetChooser; } - - /* Returns true if the card is in one of the player's play zone */ -int GameObserver::isInPlay(MTGCardInstance * card){ - for (int i = 0; i < 2; i++){ - if (players[i]->game->isInPlay(card)) return 1; - } - return 0; -} - -void GameObserver::draw(){ - currentPlayer->game->drawFromLibrary(); -} - -void GameObserver::cleanupPhase(){ - currentPlayer->cleanupPhase(); - opponent()->cleanupPhase(); -} - -void GameObserver::untapPhase(){ - currentPlayer->inPlay()->untapAll(); -} - -int GameObserver::receiveEvent(WEvent * e){ - if (!e) return 0; - eventsQueue.push(e); - if (eventsQueue.size() > 1) return -1; //resolving events can generate more events - int result = 0; - while(eventsQueue.size()){ - WEvent * ev = eventsQueue.front(); - result += mLayers->receiveEvent(ev); - for (int i = 0; i < 2; ++i){ - result += players[i]->receiveEvent(ev); +int GameObserver::isInPlay(MTGCardInstance * card) +{ + for (int i = 0; i < 2; i++) + { + if (players[i]->game->isInPlay(card)) + return 1; } - SAFE_DELETE(ev); - eventsQueue.pop(); - } - return result; + return 0; } -Player * GameObserver::currentlyActing(){ - if (isInterrupting) return isInterrupting; - return currentActionPlayer; +void GameObserver::draw() +{ + currentPlayer->game->drawFromLibrary(); +} + +void GameObserver::cleanupPhase() +{ + currentPlayer->cleanupPhase(); + opponent()->cleanupPhase(); +} + +void GameObserver::untapPhase() +{ + currentPlayer->inPlay()->untapAll(); +} + +int GameObserver::receiveEvent(WEvent * e) +{ + if (!e) + return 0; + eventsQueue.push(e); + if (eventsQueue.size() > 1) + return -1; //resolving events can generate more events + int result = 0; + while (eventsQueue.size()) + { + WEvent * ev = eventsQueue.front(); + result += mLayers->receiveEvent(ev); + for (int i = 0; i < 2; ++i) + { + result += players[i]->receiveEvent(ev); + } + SAFE_DELETE(ev); + eventsQueue.pop(); + } + return result; +} + +Player * GameObserver::currentlyActing() +{ + if (isInterrupting) + return isInterrupting; + return currentActionPlayer; } //TODO CORRECT THIS MESS -int GameObserver::targetListIsSet(MTGCardInstance * card){ - if (targetChooser == NULL){ - TargetChooserFactory tcf; - targetChooser = tcf.createTargetChooser(card); - cardWaitingForTargets = card; - if (targetChooser == NULL){ - return 1; +int GameObserver::targetListIsSet(MTGCardInstance * card) +{ + if (targetChooser == NULL) + { + TargetChooserFactory tcf; + targetChooser = tcf.createTargetChooser(card); + cardWaitingForTargets = card; + if (targetChooser == NULL) + { + return 1; + } } - } - return (targetChooser->targetListSet()); + return (targetChooser->targetListSet()); } diff --git a/projects/mtg/src/GameOptions.cpp b/projects/mtg/src/GameOptions.cpp index e2e00ac3c..52f245035 100644 --- a/projects/mtg/src/GameOptions.cpp +++ b/projects/mtg/src/GameOptions.cpp @@ -64,895 +64,1024 @@ const string Options::optionNames[] = { "aw_collector", }; -int Options::getID(string name){ - if (0 == name.size()) INVALID_OPTION; +int Options::getID(string name) +{ + if (0 == name.size()) + INVALID_OPTION; - std::transform(name.begin(),name.end(),name.begin(),::tolower); + std::transform(name.begin(), name.end(), name.begin(), ::tolower); - //Is it a named option? - for(int x = 0; x < LAST_NAMED; x++){ - string lower = Options::optionNames[x]; - std::transform(lower.begin(),lower.end(),lower.begin(),::tolower); + //Is it a named option? + for (int x = 0; x < LAST_NAMED; x++) + { + string lower = Options::optionNames[x]; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); - if(lower == name) - return x; - } - - //Is it an unlocked set? - size_t un = strlen("unlocked_"); - if(un < name.size()){ - string setname = name.substr(un); - if(setlist.size()){ - int unlocked = setlist[setname]; - if(unlocked != -1) - return Options::optionSet(unlocked); + if (lower == name) + return x; } - } - //Failure. - return INVALID_OPTION; -} + //Is it an unlocked set? + size_t un = strlen("unlocked_"); + if (un < name.size()) + { + string setname = name.substr(un); + if (setlist.size()) + { + int unlocked = setlist[setname]; + if (unlocked != -1) + return Options::optionSet(unlocked); + } + } -string Options::getName(int option){ - //Invalid options - if(option < 0) - return ""; - - //Standard named options - if(option < LAST_NAMED) - return optionNames[option]; - - //Unlocked sets. - int setID = option - SET_UNLOCKS; - char buf[512]; - if(setID < 0 || setID > setlist.size()) - return ""; - - sprintf(buf,"unlocked_%s",setlist[setID].c_str()); - return buf; - - //Failed. - return ""; -} - -int Options::optionSet(int setID){ - //Sanity check if possible - if(setID < 0 || (setID > setlist.size())) + //Failure. return INVALID_OPTION; - - return SET_UNLOCKS + setID; } -int Options::optionInterrupt(int gamePhase){ - //Huge, nearly illegible switch block spread out to improve readability. - switch(gamePhase){ - case Constants::MTG_PHASE_BEFORE_BEGIN: +string Options::getName(int option) +{ + //Invalid options + if (option < 0) + return ""; + + //Standard named options + if (option < LAST_NAMED) + return optionNames[option]; + + //Unlocked sets. + int setID = option - SET_UNLOCKS; + char buf[512]; + if (setID < 0 || setID > setlist.size()) + return ""; + + sprintf(buf, "unlocked_%s", setlist[setID].c_str()); + return buf; + + //Failed. + return ""; +} + +int Options::optionSet(int setID) +{ + //Sanity check if possible + if (setID < 0 || (setID > setlist.size())) + return INVALID_OPTION; + + return SET_UNLOCKS + setID; +} + +int Options::optionInterrupt(int gamePhase) +{ + //Huge, nearly illegible switch block spread out to improve readability. + switch (gamePhase) + { + case Constants::MTG_PHASE_BEFORE_BEGIN: return INTERRUPT_BEFOREBEGIN; - case Constants::MTG_PHASE_UNTAP: + case Constants::MTG_PHASE_UNTAP: return INTERRUPT_UNTAP; - case Constants::MTG_PHASE_UPKEEP: + case Constants::MTG_PHASE_UPKEEP: return INTERRUPT_UPKEEP; - case Constants::MTG_PHASE_DRAW: + case Constants::MTG_PHASE_DRAW: return INTERRUPT_DRAW; - case Constants::MTG_PHASE_FIRSTMAIN: + case Constants::MTG_PHASE_FIRSTMAIN: return INTERRUPT_FIRSTMAIN; - case Constants::MTG_PHASE_COMBATBEGIN: + case Constants::MTG_PHASE_COMBATBEGIN: return INTERRUPT_BEGINCOMBAT; - case Constants::MTG_PHASE_COMBATATTACKERS: + case Constants::MTG_PHASE_COMBATATTACKERS: return INTERRUPT_ATTACKERS; - case Constants::MTG_PHASE_COMBATBLOCKERS: + case Constants::MTG_PHASE_COMBATBLOCKERS: return INTERRUPT_BLOCKERS; - case Constants::MTG_PHASE_COMBATDAMAGE: + case Constants::MTG_PHASE_COMBATDAMAGE: return INTERRUPT_DAMAGE; - case Constants::MTG_PHASE_COMBATEND: + case Constants::MTG_PHASE_COMBATEND: return INTERRUPT_ENDCOMBAT; - case Constants::MTG_PHASE_SECONDMAIN: + case Constants::MTG_PHASE_SECONDMAIN: return INTERRUPT_SECONDMAIN; - case Constants::MTG_PHASE_ENDOFTURN: + case Constants::MTG_PHASE_ENDOFTURN: return INTERRUPT_ENDTURN; - case Constants::MTG_PHASE_CLEANUP: + case Constants::MTG_PHASE_CLEANUP: return INTERRUPT_CLEANUP; - case Constants::MTG_PHASE_AFTER_EOT: + case Constants::MTG_PHASE_AFTER_EOT: return INTERRUPT_AFTEREND; - } - - return INVALID_OPTION; -} - -GameOption::GameOption(int value) : number(value){} -GameOption::GameOption(string value) : number(0), str(value) {} -GameOption::GameOption(int num, string str) : number(num), str(str) {} - -bool GameOption::isDefault(){ - string test = str; - std::transform(test.begin(),test.end(),test.begin(),::tolower); - - if(!test.size() || test == "default") - return true; - - return false; -} - -PIXEL_TYPE GameOption::asColor(PIXEL_TYPE fallback){ - unsigned char color[4]; - string temp; - int subpixel=0; - - //The absolute shortest a color could be is 5 characters: "0,0,0" (implicit 255 alpha) - if(str.length() < 5) - return fallback; - - for(size_t i=0;i 3) - return fallback; - temp += str[i]; - } - if(temp != "") - color[subpixel] = (unsigned char) atoi(temp.c_str()); - if(subpixel == 2) - color[3] = 255; - - return ARGB(color[3],color[0],color[1],color[2]); + return INVALID_OPTION; } -bool GameOption::read(string input){ - bool bNumeric = true; - - if(!input.size()) - return true; //Default reader doesn't care about invalid formatting. - - //Is it a number? - for(size_t x=0;xwrite(&file, name); + for (size_t i = 0; i < str.length(); i++) + { + if (isspace(str[i])) + continue; + if (str[i] == ',') + { + if (temp == "") + return fallback; + color[subpixel] = (unsigned char) atoi(temp.c_str()); + temp = ""; + subpixel++; + continue; + } + else if (!isdigit(str[i])) + return fallback; + if (subpixel > 3) + return fallback; + temp += str[i]; } - for(vector::size_type t=0;tdef = OptionHandDirection::getInstance(); - go = goEnum; - break; - case Options::CLOSEDHAND: - goEnum = NEW GameOptionEnum(); - goEnum->def = OptionClosedHand::getInstance(); - go = goEnum; - break; - case Options::MANADISPLAY: - goEnum = NEW GameOptionEnum(); - goEnum->def = OptionManaDisplay::getInstance(); - go = goEnum; - break; - case Options::MAX_GRADE: - goEnum = NEW GameOptionEnum(); - goEnum->def = OptionMaxGrade::getInstance(); - go = goEnum; - break; - case Options::ASPHASES: - goEnum = NEW GameOptionEnum(); - goEnum->def = OptionASkipPhase::getInstance(); - go = goEnum; - break; - case Options::KEY_BINDINGS: - go = NEW GameOptionKeyBindings(); - break; - case Options::ECON_DIFFICULTY: - goEnum = NEW GameOptionEnum(); - goEnum->def = OptionEconDifficulty::getInstance(); - go = goEnum; - break; - default: - if(x >= Options::BEGIN_AWARDS) - go = NEW GameOptionAward(); - else - go = NEW GameOption(); - break; + //Is it a number? + for (size_t x = 0; x < input.size(); x++) + { + if (!isdigit(input[x])) + { + bNumeric = false; + break; + } } - values.push_back(go); - x++; - } - return values[optionID]; + if (bNumeric) + number = atoi(input.c_str()); + else + str = input; + return true; +} +string GameOption::menuStr() +{ + if (number) + { + char buf[12]; + sprintf(buf, "%d", number); + } + + if (str.size()) + return str; + + return "0"; +} +bool GameOption::write(std::ofstream * file, string name) +{ + char writer[1024]; + + if (!file) + return false; + + if (str == "") + { + if (number == 0) //This is absolutely default. No need to write it. + return true; + + //It's a number! + sprintf(writer, "%s=%d\n", name.c_str(), number); + } + else + sprintf(writer, "%s=%s\n", name.c_str(), str.c_str()); + + (*file) << writer; + return true; } -GameOptions::~GameOptions(){ - for(vector::iterator it=values.begin();it!=values.end();it++) - SAFE_DELETE(*it); - values.clear(); +GameOptions::GameOptions(string filename) +{ + mFilename = filename; + GameOptions::load(); +} + +int GameOptions::load() +{ + std::ifstream file(mFilename.c_str()); + std::string s; + + if (file) + { + while (std::getline(file, s)) + { + if (!s.size()) + continue; + if (s[s.size() - 1] == '\r') + s.erase(s.size() - 1); //Handle DOS files + int found = s.find("="); + string name = s.substr(0, found); + string val = s.substr(found + 1); + int id = Options::getID(name); + if (id == INVALID_OPTION) + { + unknown.push_back(s); + continue; + } + + (*this)[id].read(val); + } + file.close(); + } + // (PSY) Make sure that cheatmode is switched off for ineligible profiles: + if (options[Options::ACTIVE_PROFILE].str != SECRET_PROFILE) + (*this)[Options::CHEATMODE].number = 0; + + //Default values. Anywhere else to put those ? + if (!(*this)[Options::MAX_GRADE].number) + (*this)[Options::MAX_GRADE].number = Constants::GRADE_BORDERLINE; + + return 1; +} +int GameOptions::save() +{ + // (PSY) Make sure that cheatmode is switched off for ineligible profiles: + if (options[Options::ACTIVE_PROFILE].str != SECRET_PROFILE) + (*this)[Options::CHEATMODE].number = 0; + + std::ofstream file(mFilename.c_str()); + if (file) + { + for (int x = 0; x < (int) values.size(); x++) + { + //Check that this is a valid option. + string name = Options::getName(x); + GameOption * opt = get(x); + if (!name.size() || !opt) + continue; + + //Save it. + opt->write(&file, name); + } + + for (vector::size_type t = 0; t < unknown.size(); t++) + file << unknown[t] << "\n"; + file.close(); + } + return 1; +} + +GameOption& GameOptions::operator[](int optionID) +{ + GameOption * go = get(optionID); + if (!go) + return GameSettings::invalid_option; + + return *go; +} + +GameOption * GameOptions::get(int optionID) +{ + //Invalid options! + if (optionID < 0) + return NULL; + + //Option doesn't exist, so build it + int x = (int) values.size(); + values.reserve(optionID); + + while (x <= optionID) + { + GameOption * go = NULL; + GameOptionEnum * goEnum = NULL; + switch (x) + { + //Enum options + case Options::HANDDIRECTION: + goEnum = NEW GameOptionEnum(); + goEnum->def = OptionHandDirection::getInstance(); + go = goEnum; + break; + case Options::CLOSEDHAND: + goEnum = NEW GameOptionEnum(); + goEnum->def = OptionClosedHand::getInstance(); + go = goEnum; + break; + case Options::MANADISPLAY: + goEnum = NEW GameOptionEnum(); + goEnum->def = OptionManaDisplay::getInstance(); + go = goEnum; + break; + case Options::MAX_GRADE: + goEnum = NEW GameOptionEnum(); + goEnum->def = OptionMaxGrade::getInstance(); + go = goEnum; + break; + case Options::ASPHASES: + goEnum = NEW GameOptionEnum(); + goEnum->def = OptionASkipPhase::getInstance(); + go = goEnum; + break; + case Options::KEY_BINDINGS: + go = NEW GameOptionKeyBindings(); + break; + case Options::ECON_DIFFICULTY: + goEnum = NEW GameOptionEnum(); + goEnum->def = OptionEconDifficulty::getInstance(); + go = goEnum; + break; + default: + if (x >= Options::BEGIN_AWARDS) + go = NEW GameOptionAward(); + else + go = NEW GameOption(); + break; + } + values.push_back(go); + x++; + } + + return values[optionID]; +} + +GameOptions::~GameOptions() +{ + for (vector::iterator it = values.begin(); it != values.end(); it++) + SAFE_DELETE(*it); + values.clear(); } GameSettings options; GameSettings::GameSettings() { - styleMan = NULL; - globalOptions = NULL; - theGame = NULL; - profileOptions = NULL; - //reloadProfile should be before using options. + styleMan = NULL; + globalOptions = NULL; + theGame = NULL; + profileOptions = NULL; + //reloadProfile should be before using options. } -WStyle * GameSettings::getStyle() { - if(!styleMan) styleMan = new StyleManager(); - return styleMan->get(); +WStyle * GameSettings::getStyle() +{ + if (!styleMan) + styleMan = new StyleManager(); + return styleMan->get(); } -StyleManager * GameSettings::getStyleMan() { - if(!styleMan) styleMan = new StyleManager(); - return styleMan; +StyleManager * GameSettings::getStyleMan() +{ + if (!styleMan) + styleMan = new StyleManager(); + return styleMan; } -void GameSettings::automaticStyle(Player * p1, Player * p2){ - if(!styleMan) styleMan = new StyleManager(); - MTGDeck * decks[2]; - for(int i=0;i<2;i++){ - decks[i] = new MTGDeck(GameApp::collection); - Player * p; if(i == 0) p = p1; else p = p2; - map::iterator it; - for(it = p->game->library->cardsMap.begin();it != p->game->library->cardsMap.end();it++){ - decks[i]->add(it->first); +void GameSettings::automaticStyle(Player * p1, Player * p2) +{ + if (!styleMan) + styleMan = new StyleManager(); + MTGDeck * decks[2]; + for (int i = 0; i < 2; i++) + { + decks[i] = new MTGDeck(GameApp::collection); + Player * p; + if (i == 0) + p = p1; + else + p = p2; + map::iterator it; + for (it = p->game->library->cardsMap.begin(); it != p->game->library->cardsMap.end(); it++) + { + decks[i]->add(it->first); + } + } + styleMan->determineActive(decks[0], decks[1]); + for (int i = 0; i < 2; i++) + { + SAFE_DELETE(decks[i]); } - } - styleMan->determineActive(decks[0],decks[1]); - for(int i=0;i<2;i++){ - SAFE_DELETE(decks[i]); - } } - -GameSettings::~GameSettings(){ - SAFE_DELETE(globalOptions); - SAFE_DELETE(profileOptions); - SAFE_DELETE(keypad); - SAFE_DELETE(styleMan); +GameSettings::~GameSettings() +{ + SAFE_DELETE(globalOptions); + SAFE_DELETE(profileOptions); + SAFE_DELETE(keypad); + SAFE_DELETE(styleMan); } -bool GameSettings::newAward(){ - if(!profileOptions) +bool GameSettings::newAward() +{ + if (!profileOptions) + return false; + + for (int x = Options::BEGIN_AWARDS; x < Options::SET_UNLOCKS + setlist.size(); x++) + { + GameOptionAward * goa = dynamic_cast (profileOptions->get(x)); + if (!goa) + continue; + if (!goa->isViewed()) + return true; + } return false; - - for(int x=Options::BEGIN_AWARDS;x < Options::SET_UNLOCKS + setlist.size();x++){ - GameOptionAward * goa = dynamic_cast(profileOptions->get(x)); - if(!goa) - continue; - if(!goa->isViewed()) - return true; - } - return false; } GameOption GameSettings::invalid_option = GameOption(0); -GameOption& GameSettings::operator[](int optionID){ - GameOption * go = get(optionID); - if(!go) - return invalid_option; - - return *go; -} - -GameOption* GameSettings::get(int optionID){ - string option_name = Options::getName(optionID); - - if(optionID < 0) - return &invalid_option; - else if(globalOptions && optionID <= Options::LAST_GLOBAL) - return globalOptions->get(optionID); - else if(profileOptions) - return profileOptions->get(optionID); - - return &invalid_option; -} - - -int GameSettings::save(){ - if(globalOptions) - globalOptions->save(); - - if(profileOptions){ - //Force our directories to exist. - MAKEDIR(JGE_GET_RES("profiles").c_str()); - string temp = profileFile("","",false,false); - MAKEDIR(temp.c_str()); - temp+="/stats"; - MAKEDIR(temp.c_str()); - temp = profileFile(PLAYER_SETTINGS,"",false); - - profileOptions->save(); - } - - checkProfile(); - - return 1; -} - -string GameSettings::profileFile(string filename, string fallback,bool sanity, bool relative) +GameOption& GameSettings::operator[](int optionID) { - char buf[512]; - string profile = (*this)[Options::ACTIVE_PROFILE].str; + GameOption * go = get(optionID); + if (!go) + return invalid_option; - if(!(*this)[Options::ACTIVE_PROFILE].isDefault()) { - //No file, return root of profile directory - if(filename == ""){ - sprintf(buf,"%sprofiles/%s",( relative ? "" : JGE_GET_RES("").c_str() ),profile.c_str()); - return buf; - } - //Return file - sprintf(buf,JGE_GET_RES("profiles/%s/%s").c_str(),profile.c_str(),filename.c_str()); - if(fileExists(buf)){ - if(relative) - sprintf(buf,"profiles/%s/%s",profile.c_str(),filename.c_str()); - return buf; - } - } - else{ - //Use the default directory. - sprintf(buf,"%splayer%s%s",(relative ? "" :JGE_GET_RES("").c_str()),(filename == "" ? "" : "/"), filename.c_str()); - return buf; - } - - //Don't fallback if sanity checking is disabled.. - if(!sanity){ - sprintf(buf,"%sprofiles/%s%s%s",(relative ? "" : JGE_GET_RES("").c_str()),profile.c_str(),(filename == "" ? "" : "/"), filename.c_str()); - return buf; - } - - //No fallback directory. This is often a crash. - if(fallback == "") - return ""; - - sprintf(buf,"%s%s%s%s",(relative ? "" : JGE_GET_RES("").c_str()),fallback.c_str(),(filename == "" ? "" : "/"), filename.c_str()); - return buf; + return *go; } -void GameSettings::reloadProfile(bool images){ +GameOption* GameSettings::get(int optionID) +{ + string option_name = Options::getName(optionID); + + if (optionID < 0) + return &invalid_option; + else if (globalOptions && optionID <= Options::LAST_GLOBAL) + return globalOptions->get(optionID); + else if (profileOptions) + return profileOptions->get(optionID); + + return &invalid_option; +} + +int GameSettings::save() +{ + if (globalOptions) + globalOptions->save(); + + if (profileOptions) + { + //Force our directories to exist. + MAKEDIR(JGE_GET_RES("profiles").c_str()); + string temp = profileFile("", "", false, false); + MAKEDIR(temp.c_str()); + temp += "/stats"; + MAKEDIR(temp.c_str()); + temp = profileFile(PLAYER_SETTINGS, "", false); + + profileOptions->save(); + } + + checkProfile(); + + return 1; +} + +string GameSettings::profileFile(string filename, string fallback, bool sanity, bool relative) +{ + char buf[512]; + string profile = (*this)[Options::ACTIVE_PROFILE].str; + + if (!(*this)[Options::ACTIVE_PROFILE].isDefault()) + { + //No file, return root of profile directory + if (filename == "") + { + sprintf(buf, "%sprofiles/%s", (relative ? "" : JGE_GET_RES("").c_str()), profile.c_str()); + return buf; + } + //Return file + sprintf(buf, JGE_GET_RES("profiles/%s/%s").c_str(), profile.c_str(), filename.c_str()); + if (fileExists(buf)) + { + if (relative) + sprintf(buf, "profiles/%s/%s", profile.c_str(), filename.c_str()); + return buf; + } + } + else + { + //Use the default directory. + sprintf(buf, "%splayer%s%s", (relative ? "" : JGE_GET_RES("").c_str()), (filename == "" ? "" : "/"), filename.c_str()); + return buf; + } + + //Don't fallback if sanity checking is disabled.. + if (!sanity) + { + sprintf(buf, "%sprofiles/%s%s%s", (relative ? "" : JGE_GET_RES("").c_str()), profile.c_str(), (filename == "" ? "" : "/"), + filename.c_str()); + return buf; + } + + //No fallback directory. This is often a crash. + if (fallback == "") + return ""; + + sprintf(buf, "%s%s%s%s", (relative ? "" : JGE_GET_RES("").c_str()), fallback.c_str(), (filename == "" ? "" : "/"), + filename.c_str()); + return buf; +} + +void GameSettings::reloadProfile(bool images) +{ SAFE_DELETE(profileOptions); checkProfile(); - if(images) - resources.Refresh(); //Update images + if (images) + resources.Refresh(); //Update images } -void GameSettings::checkProfile(){ - if(!globalOptions) - globalOptions = NEW GameOptions(JGE_GET_RES(GLOBAL_SETTINGS)); +void GameSettings::checkProfile() +{ + if (!globalOptions) + globalOptions = NEW GameOptions(JGE_GET_RES(GLOBAL_SETTINGS)); //If it doesn't exist, load current profile. - if(!profileOptions){ - profileOptions = NEW GameOptions(profileFile(PLAYER_SETTINGS,"",false)); - //Backwards compatability hack for unlocked modes. - for(int x=Options::BEGIN_AWARDS;x(globalOptions->get(x)); - if(goa){ - GameOptionAward * dupe = dynamic_cast(profileOptions->get(x)); - if(dupe && goa->number && !dupe->number) dupe->giveAward(); + if (!profileOptions) + { + profileOptions = NEW GameOptions(profileFile(PLAYER_SETTINGS, "", false)); + //Backwards compatability hack for unlocked modes. + for (int x = Options::BEGIN_AWARDS; x < Options::LAST_NAMED; x++) + { + GameOptionAward * goa = dynamic_cast (globalOptions->get(x)); + if (goa) + { + GameOptionAward * dupe = dynamic_cast (profileOptions->get(x)); + if (dupe && goa->number && !dupe->number) + dupe->giveAward(); + } } - } } //Validation of collection, etc, only happens if the game is up. - if(theGame == NULL || theGame->collection == NULL) - return; + if (theGame == NULL || theGame->collection == NULL) + return; - string pcFile = profileFile(PLAYER_COLLECTION,"",false); - if(!pcFile.size() || !fileExists(pcFile.c_str())) + string pcFile = profileFile(PLAYER_COLLECTION, "", false); + if (!pcFile.size() || !fileExists(pcFile.c_str())) { - //If we had any default settings, we'd set them here. + //If we had any default settings, we'd set them here. - //Make the proper directories - if(profileOptions){ - //Force our directories to exist. - MAKEDIR(JGE_GET_RES("profiles").c_str()); - string temp = profileFile("","",false,false); - MAKEDIR(temp.c_str()); - temp+="/stats"; - MAKEDIR(temp.c_str()); - temp = profileFile(PLAYER_SETTINGS,"",false); + //Make the proper directories + if (profileOptions) + { + //Force our directories to exist. + MAKEDIR(JGE_GET_RES("profiles").c_str()); + string temp = profileFile("", "", false, false); + MAKEDIR(temp.c_str()); + temp += "/stats"; + MAKEDIR(temp.c_str()); + temp = profileFile(PLAYER_SETTINGS, "", false); - profileOptions->save(); - } + profileOptions->save(); + } } + //Find the set for which we have the most variety + int setId = -1; + int maxcards = 0; + int ok = 0; + for (int i = 0; i < setlist.size(); i++) + { + int value = theGame->collection->countBySet(i); + if (value > maxcards) + { + maxcards = value; + setId = i; + } + if (options[Options::optionSet(i)].number) + { + ok = 1; + break; + } + } + if (!ok && setId >= 0) + { + //Save this set as "unlocked" + (*profileOptions)[Options::optionSet(setId)] = 1; + profileOptions->save(); - //Find the set for which we have the most variety - int setId = -1; - int maxcards = 0; - int ok = 0; - for (int i=0; i< setlist.size(); i++){ - int value = theGame->collection->countBySet(i); - if (value > maxcards){ - maxcards = value; - setId = i; - } - if(options[Options::optionSet(i)].number){ - ok = 1; - break; - } - } - if(!ok && setId >= 0){ - //Save this set as "unlocked" - (*profileOptions)[Options::optionSet(setId)]=1; - profileOptions->save(); - - //Give the player their first deck - createUsersFirstDeck(setId); - } - getStyleMan()->determineActive(NULL,NULL); + //Give the player their first deck + createUsersFirstDeck(setId); + } + getStyleMan()->determineActive(NULL, NULL); } -void GameSettings::createUsersFirstDeck(int setId){ +void GameSettings::createUsersFirstDeck(int setId) +{ - if(theGame == NULL || theGame->collection == NULL) - return; + if (theGame == NULL || theGame->collection == NULL) + return; - MTGDeck *mCollection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION,"",false).c_str(), theGame->collection); - if(mCollection->totalCards() > 0) - return; + MTGDeck *mCollection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION, "", false).c_str(), theGame->collection); + if (mCollection->totalCards() > 0) + return; - //10 lands of each - int sets[] = {setId}; - if (!mCollection->addRandomCards(10, sets,1, Constants::RARITY_L,"Forest")) - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Forest"); - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Plains")) - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Plains"); - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Swamp")) - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Swamp"); - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Mountain")) - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Mountain"); - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Island")) - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Island"); + //10 lands of each + int sets[] = { setId }; + if (!mCollection->addRandomCards(10, sets, 1, Constants::RARITY_L, "Forest")) + mCollection->addRandomCards(10, 0, 0, Constants::RARITY_L, "Forest"); + if (!mCollection->addRandomCards(10, sets, 1, Constants::RARITY_L, "Plains")) + mCollection->addRandomCards(10, 0, 0, Constants::RARITY_L, "Plains"); + if (!mCollection->addRandomCards(10, sets, 1, Constants::RARITY_L, "Swamp")) + mCollection->addRandomCards(10, 0, 0, Constants::RARITY_L, "Swamp"); + if (!mCollection->addRandomCards(10, sets, 1, Constants::RARITY_L, "Mountain")) + mCollection->addRandomCards(10, 0, 0, Constants::RARITY_L, "Mountain"); + if (!mCollection->addRandomCards(10, sets, 1, Constants::RARITY_L, "Island")) + mCollection->addRandomCards(10, 0, 0, Constants::RARITY_L, "Island"); - //Starter Deck - mCollection->addRandomCards(3, sets,1,Constants::RARITY_R,NULL); - mCollection->addRandomCards(9, sets,1,Constants::RARITY_U,NULL); - mCollection->addRandomCards(48, sets,1,Constants::RARITY_C,NULL); + //Starter Deck + mCollection->addRandomCards(3, sets, 1, Constants::RARITY_R, NULL); + mCollection->addRandomCards(9, sets, 1, Constants::RARITY_U, NULL); + mCollection->addRandomCards(48, sets, 1, Constants::RARITY_C, NULL); - //Boosters - for (int i = 0; i< 2; i++){ - mCollection->addRandomCards(1, sets,1,Constants::RARITY_R); - mCollection->addRandomCards(3, sets,1,Constants::RARITY_U); - mCollection->addRandomCards(11, sets,1,Constants::RARITY_C); - } - mCollection->save(); - SAFE_DELETE(mCollection); + //Boosters + for (int i = 0; i < 2; i++) + { + mCollection->addRandomCards(1, sets, 1, Constants::RARITY_R); + mCollection->addRandomCards(3, sets, 1, Constants::RARITY_U); + mCollection->addRandomCards(11, sets, 1, Constants::RARITY_C); + } + mCollection->save(); + SAFE_DELETE(mCollection); } -void GameSettings::keypadTitle(string set){ - if(keypad != NULL) - keypad->title = set; +void GameSettings::keypadTitle(string set) +{ + if (keypad != NULL) + keypad->title = set; } -SimplePad * GameSettings::keypadStart(string input, string * _dest,bool _cancel, bool _numpad, int _x,int _y ){ - if(keypad == NULL) - keypad = NEW SimplePad(); - keypad->bShowCancel = _cancel; - keypad->bShowNumpad = _numpad; - keypad->mX = _x; - keypad->mY = _y; - keypad->Start(input,_dest); - return keypad; +SimplePad * GameSettings::keypadStart(string input, string * _dest, bool _cancel, bool _numpad, int _x, int _y) +{ + if (keypad == NULL) + keypad = NEW SimplePad(); + keypad->bShowCancel = _cancel; + keypad->bShowNumpad = _numpad; + keypad->mX = _x; + keypad->mY = _y; + keypad->Start(input, _dest); + return keypad; } -string GameSettings::keypadFinish(){ - if(keypad == NULL) - return ""; - return keypad->Finish(); +string GameSettings::keypadFinish() +{ + if (keypad == NULL) + return ""; + return keypad->Finish(); } -void GameSettings::keypadShutdown(){ - SAFE_DELETE(keypad); +void GameSettings::keypadShutdown() +{ + SAFE_DELETE(keypad); } //EnumDefinition -int EnumDefinition::findIndex(int value){ - vector::iterator it; - for(it = values.begin();it!=values.end();it++){ - if(it->first == value) - return it - values.begin(); - } +int EnumDefinition::findIndex(int value) +{ + vector::iterator it; + for (it = values.begin(); it != values.end(); it++) + { + if (it->first == value) + return it - values.begin(); + } - return INVALID_ID; //Failed! + return INVALID_ID; //Failed! } //GameOptionEnum -string GameOptionEnum::menuStr(){ - if(def){ - int idx = def->findIndex(number); - if(idx != INVALID_ID) - return def->values[idx].second; - } - - char buf[32]; - sprintf(buf,"%d",number); - return buf; -} - -bool GameOptionEnum::write(std::ofstream * file, string name){ - if(!file || !def || number <= 0 || number >= (int) def->values.size()) - return false; - - (*file) << name << "=" << menuStr() << endl; - return true; -} - -bool GameOptionEnum::read(string input){ - if(!def) - return false; - - number = 0; - std::transform(input.begin(),input.end(),input.begin(),::tolower); - - vector::iterator it; - for(it=def->values.begin();it != def->values.end();it++){ - string v = it->second; - std::transform(v.begin(),v.end(),v.begin(),::tolower); - if(v == input){ - number = it->first; - return true; +string GameOptionEnum::menuStr() +{ + if (def) + { + int idx = def->findIndex(number); + if (idx != INVALID_ID) + return def->values[idx].second; } - } - return false; + char buf[32]; + sprintf(buf, "%d", number); + return buf; +} + +bool GameOptionEnum::write(std::ofstream * file, string name) +{ + if (!file || !def || number <= 0 || number >= (int) def->values.size()) + return false; + + (*file) << name << "=" << menuStr() << endl; + return true; +} + +bool GameOptionEnum::read(string input) +{ + if (!def) + return false; + + number = 0; + std::transform(input.begin(), input.end(), input.begin(), ::tolower); + + vector::iterator it; + for (it = def->values.begin(); it != def->values.end(); it++) + { + string v = it->second; + std::transform(v.begin(), v.end(), v.begin(), ::tolower); + if (v == input) + { + number = it->first; + return true; + } + } + + return false; } //Enum Definitions OptionMaxGrade OptionMaxGrade::mDef; -OptionMaxGrade::OptionMaxGrade(){ - mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_SUPPORTED, "1: 100% Supported")); - mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_BORDERLINE, "0: Borderline (99% OK)")); - mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_UNOFFICIAL, "-1: Unofficial (unverified cards)")); - mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_CRAPPY, "-2: Crappy (bugs)")); - mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_UNSUPPORTED, "-3: Unsupported")); - mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_DANGEROUS, "-4: Dangerous (risk of crash)")); +OptionMaxGrade::OptionMaxGrade() +{ + mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_SUPPORTED, "1: 100% Supported")); + mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_BORDERLINE, "0: Borderline (99% OK)")); + mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_UNOFFICIAL, "-1: Unofficial (unverified cards)")); + mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_CRAPPY, "-2: Crappy (bugs)")); + mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_UNSUPPORTED, "-3: Unsupported")); + mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_DANGEROUS, "-4: Dangerous (risk of crash)")); -}; +} +; OptionASkipPhase OptionASkipPhase::mDef; -OptionASkipPhase::OptionASkipPhase(){ - mDef.values.push_back(EnumDefinition::assoc(Constants::ASKIP_NONE, "Off")); - mDef.values.push_back(EnumDefinition::assoc(Constants::ASKIP_SAFE, "Safe")); - mDef.values.push_back(EnumDefinition::assoc(Constants::ASKIP_FULL, "Full")); -}; +OptionASkipPhase::OptionASkipPhase() +{ + mDef.values.push_back(EnumDefinition::assoc(Constants::ASKIP_NONE, "Off")); + mDef.values.push_back(EnumDefinition::assoc(Constants::ASKIP_SAFE, "Safe")); + mDef.values.push_back(EnumDefinition::assoc(Constants::ASKIP_FULL, "Full")); +} +; OptionClosedHand OptionClosedHand::mDef; -OptionClosedHand::OptionClosedHand(){ +OptionClosedHand::OptionClosedHand() +{ mDef.values.push_back(EnumDefinition::assoc(INVISIBLE, "invisible")); mDef.values.push_back(EnumDefinition::assoc(VISIBLE, "visible")); -}; +} +; OptionHandDirection OptionHandDirection::mDef; -OptionHandDirection::OptionHandDirection(){ +OptionHandDirection::OptionHandDirection() +{ mDef.values.push_back(EnumDefinition::assoc(VERTICAL, "vertical")); mDef.values.push_back(EnumDefinition::assoc(HORIZONTAL, "horizontal")); -}; +} +; OptionManaDisplay OptionManaDisplay::mDef; -OptionManaDisplay::OptionManaDisplay(){ +OptionManaDisplay::OptionManaDisplay() +{ mDef.values.push_back(EnumDefinition::assoc(DYNAMIC, "Eye candy")); mDef.values.push_back(EnumDefinition::assoc(STATIC, "Simple")); mDef.values.push_back(EnumDefinition::assoc(BOTH, "Both")); -}; +} +; OptionVolume OptionVolume::mDef; -OptionVolume::OptionVolume(){ +OptionVolume::OptionVolume() +{ mDef.values.push_back(EnumDefinition::assoc(MUTE, "Mute")); mDef.values.push_back(EnumDefinition::assoc(MAX, "Max")); -}; +} +; OptionDifficulty OptionDifficulty::mDef; -OptionDifficulty::OptionDifficulty(){ +OptionDifficulty::OptionDifficulty() +{ mDef.values.push_back(EnumDefinition::assoc(NORMAL, "Normal")); mDef.values.push_back(EnumDefinition::assoc(HARD, "Hard")); mDef.values.push_back(EnumDefinition::assoc(HARDER, "Harder")); mDef.values.push_back(EnumDefinition::assoc(EVIL, "Evil")); -}; +} +; OptionEconDifficulty OptionEconDifficulty::mDef; -OptionEconDifficulty::OptionEconDifficulty(){ - mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_NORMAL, "Normal")); - mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_HARD, "Hard")); - mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_LUCK, "Luck")); - mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_EASY, "Easy")); -}; +OptionEconDifficulty::OptionEconDifficulty() +{ + mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_NORMAL, "Normal")); + mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_HARD, "Hard")); + mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_LUCK, "Luck")); + mDef.values.push_back(EnumDefinition::assoc(Constants::ECON_EASY, "Easy")); +} +; //GameOptionAward -GameOptionAward::GameOptionAward(){ - achieved = time(NULL); - number = 0; - viewed = false; -} -bool GameOptionAward::read(string input){ - //This is quick and dirty. - bool bNumeric = true; - achieved = time(NULL); - tm * at = localtime(&achieved); - viewed = false; - - size_t inlen = input.size(); - if(!inlen) - return true; //Default reader doesn't care about invalid formatting. - else if(inlen < 8 || input != "0") //Regardless of what garbage this is fed, a non-zero value is "Awarded" - number = 1; - - size_t w = input.find("V"); - - if(w != string::npos) - viewed = true; - - //TODO: Something cleaner. - int tvals[5]; - int i; - for(i=0;i<5;i++) - tvals[i] = 0; - - string buf; - for (size_t t=0,i=0; t < input.size();t++) - { - if(!isdigit(input[t])) - { - if(!isspace(input[t]) && buf.size()) - { - tvals[i] = atoi(buf.c_str()); - if(tvals[i] < 0) - tvals[i] = 0; - buf.clear(); - i++; //Advance through input. - } - } - else - buf+= input[t]; - - if (i >= 5) - break; - } - - if(tvals[0] >= 1900) - tvals[0] -= 1900; - if(tvals[1] > 0) - tvals[1]--; - at->tm_year = tvals[0]; - at->tm_mon = tvals[1]; - at->tm_mday = tvals[2]; - if(tvals[3]) - at->tm_hour = tvals[3]; - if(tvals[4]) - at->tm_min = tvals[4]; - at->tm_isdst = -1; - - achieved = mktime(at); - if(achieved == -1) +GameOptionAward::GameOptionAward() +{ achieved = time(NULL); - return true; + number = 0; + viewed = false; } +bool GameOptionAward::read(string input) +{ + //This is quick and dirty. + bool bNumeric = true; + achieved = time(NULL); + tm * at = localtime(&achieved); + viewed = false; -bool GameOptionAward::write(std::ofstream * file, string name){ - char writer[1024]; + size_t inlen = input.size(); + if (!inlen) + return true; //Default reader doesn't care about invalid formatting. + else if (inlen < 8 || input != "0") //Regardless of what garbage this is fed, a non-zero value is "Awarded" + number = 1; - if(!file) - return false; + size_t w = input.find("V"); - if(number == 0) //Is not unlocked. Don't write. + if (w != string::npos) + viewed = true; + + //TODO: Something cleaner. + int tvals[5]; + int i; + for (i = 0; i < 5; i++) + tvals[i] = 0; + + string buf; + for (size_t t = 0, i = 0; t < input.size(); t++) + { + if (!isdigit(input[t])) + { + if (!isspace(input[t]) && buf.size()) + { + tvals[i] = atoi(buf.c_str()); + if (tvals[i] < 0) + tvals[i] = 0; + buf.clear(); + i++; //Advance through input. + } + } + else + buf += input[t]; + + if (i >= 5) + break; + } + + if (tvals[0] >= 1900) + tvals[0] -= 1900; + if (tvals[1] > 0) + tvals[1]--; + at->tm_year = tvals[0]; + at->tm_mon = tvals[1]; + at->tm_mday = tvals[2]; + if (tvals[3]) + at->tm_hour = tvals[3]; + if (tvals[4]) + at->tm_min = tvals[4]; + at->tm_isdst = -1; + + achieved = mktime(at); + if (achieved == -1) + achieved = time(NULL); return true; - - tm * at = localtime(&achieved); - if(!at) return false; //Hurrah for paranoia. - - - sprintf(writer,"%s=%d/%d/%d@%d:%d %s\n", name.c_str(), - at->tm_year + 1900, at->tm_mon + 1, at->tm_mday, at->tm_hour, at->tm_min, (viewed ? "V" : "")); - (*file)<tm_year + 1900, at->tm_mon + 1, at->tm_mday, at->tm_hour, + at->tm_min, (viewed ? "V" : "")); + (*file) << writer; + return true; +} +bool GameOptionAward::giveAward() +{ + if (number) + return false; + + achieved = time(NULL); + viewed = false; + number = 1; + options.save(); //TODO - Consider efficiency of this placement. + return true; +} + +bool GameOptionAward::isViewed() +{ + if (!number) + return true; + return viewed; +} +; +string GameOptionAward::menuStr() +{ + if (!number) + return _("Not unlocked."); + else if (achieved == 1) + return _("Unlocked."); + + char buf[256]; + Translator * t = Translator::GetInstance(); + tm * lt = localtime(&achieved); + if (!lt) + return "Error"; + strftime(buf, 255, _("%B %d, %I:%M%p %Y").c_str(), lt); + return buf; } static JButton u32_to_button(u32 b) { - if (b < JGE_BTN_MAX) return static_cast(b); - else return JGE_BTN_NONE; + if (b < JGE_BTN_MAX) + return static_cast (b); + else + return JGE_BTN_NONE; } -bool GameOptionKeyBindings::read(string input){ - istringstream iss(input); - vector< pair > assoc; +bool GameOptionKeyBindings::read(string input) +{ + istringstream iss(input); + vector > assoc; - while (iss.good()) - { - stringstream s; - iss.get(*(s.rdbuf()), ','); - iss.get(); + while (iss.good()) + { + stringstream s; + iss.get(*(s.rdbuf()), ','); + iss.get(); - LocalKeySym local; char sep; u32 button; - s >> local >> sep >> button; - if (':' != sep) return false; - assoc.push_back(make_pair(local, u32_to_button(button))); - } + LocalKeySym local; + char sep; + u32 button; + s >> local >> sep >> button; + if (':' != sep) + return false; + assoc.push_back(make_pair(local, u32_to_button(button))); + } - if (assoc.empty()) return false; + if (assoc.empty()) + return false; - JGE* j = JGE::GetInstance(); + JGE* j = JGE::GetInstance(); - j->ClearBindings(); - for (vector< pair >::const_iterator it = assoc.begin(); it != assoc.end(); ++it) - j->BindKey(it->first, it->second); + j->ClearBindings(); + for (vector >::const_iterator it = assoc.begin(); it != assoc.end(); ++it) + j->BindKey(it->first, it->second); - return true; + return true; } -bool GameOptionKeyBindings::write(std::ofstream* file, string name) { - JGE* j = JGE::GetInstance(); - *file << name << "="; - JGE::keybindings_it start = j->KeyBindings_begin(), end = j->KeyBindings_end(); - if (start != end) { *file << start->first << ":" << start->second; ++start; } - for (JGE::keybindings_it it = start; it != end; ++it) - *file << "," << it->first << ":" << it->second; - *file << endl; - return true; +bool GameOptionKeyBindings::write(std::ofstream* file, string name) +{ + JGE* j = JGE::GetInstance(); + *file << name << "="; + JGE::keybindings_it start = j->KeyBindings_begin(), end = j->KeyBindings_end(); + if (start != end) + { + *file << start->first << ":" << start->second; + ++start; + } + for (JGE::keybindings_it it = start; it != end; ++it) + *file << "," << it->first << ":" << it->second; + *file << endl; + return true; } diff --git a/projects/mtg/src/GameState.cpp b/projects/mtg/src/GameState.cpp index 5aab7ab68..e23a06885 100644 --- a/projects/mtg/src/GameState.cpp +++ b/projects/mtg/src/GameState.cpp @@ -13,103 +13,104 @@ // TODO: revise sorting strategy to allow other types of sorting. Currently, it is hardwired to use // sortByName to do the sorting. This was done since the menu item display is done in insertion order. -vector GameState::fillDeckMenu( SimpleMenu * _menu, const string& path, const string& smallDeckPrefix, Player * statsPlayer){ - bool translate = _menu->autoTranslate; - _menu->autoTranslate = false; - vector deckMetaDataVector = getValidDeckMetaData( path, smallDeckPrefix, statsPlayer ); - renderDeckMenu( _menu, deckMetaDataVector); - _menu->autoTranslate = translate; - - return deckMetaDataVector; -} - -vector GameState::fillDeckMenu( DeckMenu * _menu, const string& path, const string& smallDeckPrefix, Player * statsPlayer){ - bool translate = _menu->autoTranslate; - _menu->autoTranslate = false; - vector deckMetaDataVector = getValidDeckMetaData( path, smallDeckPrefix, statsPlayer ); - renderDeckMenu( _menu, deckMetaDataVector); - _menu->autoTranslate = translate; - - return deckMetaDataVector; -} - - -vector GameState::getValidDeckMetaData( const string& path, const string& smallDeckPrefix, Player * statsPlayer) +vector GameState::fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix, + Player * statsPlayer) { - vector retList; - - DeckMetaDataList * metas = DeckMetaDataList::decksMetaData; - int found = 1; - int nbDecks = 1; - while (found){ - found = 0; - std::ostringstream filename; - filename << path << "/deck" << nbDecks << ".txt"; - DeckMetaData * meta = metas->get(filename.str(), statsPlayer); - if (meta) + bool translate = _menu->autoTranslate; + _menu->autoTranslate = false; + vector deckMetaDataVector = getValidDeckMetaData(path, smallDeckPrefix, statsPlayer); + renderDeckMenu(_menu, deckMetaDataVector); + _menu->autoTranslate = translate; + + return deckMetaDataVector; +} + +vector GameState::fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix, + Player * statsPlayer) +{ + bool translate = _menu->autoTranslate; + _menu->autoTranslate = false; + vector deckMetaDataVector = getValidDeckMetaData(path, smallDeckPrefix, statsPlayer); + renderDeckMenu(_menu, deckMetaDataVector); + _menu->autoTranslate = translate; + + return deckMetaDataVector; +} + +vector GameState::getValidDeckMetaData(const string& path, const string& smallDeckPrefix, Player * statsPlayer) +{ + vector retList; + + DeckMetaDataList * metas = DeckMetaDataList::decksMetaData; + int found = 1; + int nbDecks = 1; + while (found) { - found = 1; - if (statsPlayer){ - std::ostringstream smallDeckName; - smallDeckName << smallDeckPrefix << "_deck" << nbDecks; - meta->loadStatsForPlayer( statsPlayer, smallDeckName.str()); - } - else - { - std::ostringstream playerStatsDeckName; - playerStatsDeckName << "stats/player_deck" << nbDecks << ".txt"; - string deckstats = options.profileFile(playerStatsDeckName.str()); - meta->loadStatsForPlayer( NULL, deckstats ); - } + found = 0; + std::ostringstream filename; + filename << path << "/deck" << nbDecks << ".txt"; + DeckMetaData * meta = metas->get(filename.str(), statsPlayer); + if (meta) + { + found = 1; + if (statsPlayer) + { + std::ostringstream smallDeckName; + smallDeckName << smallDeckPrefix << "_deck" << nbDecks; + meta->loadStatsForPlayer(statsPlayer, smallDeckName.str()); + } + else + { + std::ostringstream playerStatsDeckName; + playerStatsDeckName << "stats/player_deck" << nbDecks << ".txt"; + string deckstats = options.profileFile(playerStatsDeckName.str()); + meta->loadStatsForPlayer(NULL, deckstats); + } - retList.push_back( meta ); - nbDecks++; + retList.push_back(meta); + nbDecks++; + } + meta = NULL; } - meta = NULL; - } - std::sort( retList.begin(), retList.end(), sortByName); + std::sort(retList.begin(), retList.end(), sortByName); - return retList; + return retList; } - // build a menu with the given deck list and return a vector of the deck ids created. -void GameState::renderDeckMenu ( SimpleMenu * _menu, const vector& deckMetaDataList ) +void GameState::renderDeckMenu(SimpleMenu * _menu, const vector& deckMetaDataList) { - int deckNumber = 1; - for (vector::const_iterator i = deckMetaDataList.begin(); i != deckMetaDataList.end(); i++) - { - DeckMetaData * deckMetaData = *i; - string deckName = deckMetaData -> getName(); - string deckDescription = deckMetaData -> getDescription(); - _menu->Add( deckNumber++ ,deckName.c_str(), deckDescription.c_str()); - } + int deckNumber = 1; + for (vector::const_iterator i = deckMetaDataList.begin(); i != deckMetaDataList.end(); i++) + { + DeckMetaData * deckMetaData = *i; + string deckName = deckMetaData -> getName(); + string deckDescription = deckMetaData -> getDescription(); + _menu->Add(deckNumber++, deckName.c_str(), deckDescription.c_str()); + } } - // build a menu with the given deck list and return a vector of the deck ids created. -void GameState::renderDeckMenu ( DeckMenu * _menu, const vector& deckMetaDataList ) +void GameState::renderDeckMenu(DeckMenu * _menu, const vector& deckMetaDataList) { - int deckNumber = 1; - for (vector::const_iterator i = deckMetaDataList.begin(); i != deckMetaDataList.end(); i++) - { - DeckMetaData * deckMetaData = *i; - string deckName = deckMetaData -> getName(); - string deckDescription = deckMetaData -> getDescription(); - //int deckId = deckMetaData -> getDeckId(); //do we need this? - _menu->Add( deckNumber++ ,deckName.c_str(), deckDescription.c_str(), false, deckMetaData); - } + int deckNumber = 1; + for (vector::const_iterator i = deckMetaDataList.begin(); i != deckMetaDataList.end(); i++) + { + DeckMetaData * deckMetaData = *i; + string deckName = deckMetaData -> getName(); + string deckDescription = deckMetaData -> getDescription(); + //int deckId = deckMetaData -> getDeckId(); //do we need this? + _menu->Add(deckNumber++, deckName.c_str(), deckDescription.c_str(), false, deckMetaData); + } } - // deck sorting routines -bool sortByName( DeckMetaData * d1, DeckMetaData * d2 ) +bool sortByName(DeckMetaData * d1, DeckMetaData * d2) { - return strcmp( d1->getName().c_str(), d2->getName().c_str()) < 0; + return strcmp(d1->getName().c_str(), d2->getName().c_str()) < 0; } - //end deck sorting routine diff --git a/projects/mtg/src/GameStateAwards.cpp b/projects/mtg/src/GameStateAwards.cpp index dd5778cdf..1cb5f6896 100644 --- a/projects/mtg/src/GameStateAwards.cpp +++ b/projects/mtg/src/GameStateAwards.cpp @@ -1,6 +1,6 @@ /* - This is where the player views their awards, etc. -*/ + This is where the player views their awards, etc. + */ #include "PrecompiledHeader.h" #include @@ -12,113 +12,117 @@ #include "GameOptions.h" #include "DeckDataWrapper.h" -enum ENUM_AWARDS_STATE{ - STATE_LISTVIEW, - STATE_DETAILS, +enum ENUM_AWARDS_STATE +{ + STATE_LISTVIEW, STATE_DETAILS, }; namespace { - const int kBackToTrophiesID = 2; - const int kBackToMainMenuID = 1; + const int kBackToTrophiesID = 2; + const int kBackToMainMenuID = 1; } -GameStateAwards::GameStateAwards(GameApp* parent): GameState(parent){ +GameStateAwards::GameStateAwards(GameApp* parent) : + GameState(parent) +{ } -GameStateAwards::~GameStateAwards() { +GameStateAwards::~GameStateAwards() +{ } void GameStateAwards::End() { - SAFE_DELETE(menu); - SAFE_DELETE(detailview); - SAFE_DELETE(listview); - SAFE_DELETE(setSrc); + SAFE_DELETE(menu); + SAFE_DELETE(detailview); + SAFE_DELETE(listview); + SAFE_DELETE(setSrc); - if(saveMe) - options.save(); + if (saveMe) + options.save(); } void GameStateAwards::Start() -{ - mParent->DoAnimation(TRANSITION_FADE_IN); - char buf[256]; - mState = STATE_LISTVIEW; - options.checkProfile(); +{ + mParent->DoAnimation(TRANSITION_FADE_IN); + char buf[256]; + mState = STATE_LISTVIEW; + options.checkProfile(); - menu = NULL; - saveMe = options.newAward(); + menu = NULL; + saveMe = options.newAward(); - listview = NEW WGuiList("Listview"); - listview->setX(210); - listview->setWidth(SCREEN_WIDTH - 220); - detailview = NULL; - WGuiAward * aw; - WGuiButton * btn; - - WGuiHeader * wgh = NEW WGuiHeader("Achievements"); - listview->Add(wgh); + listview = NEW WGuiList("Listview"); + listview->setX(210); + listview->setWidth(SCREEN_WIDTH - 220); + detailview = NULL; + WGuiAward * aw; + WGuiButton * btn; - aw = NEW WGuiAward(Options::DIFFICULTY_MODE_UNLOCKED,"Difficulty Modes","Achieved a 66% victory ratio."); - btn = NEW WGuiButton(aw,-103,Options::DIFFICULTY_MODE_UNLOCKED,this); - listview->Add(btn); + WGuiHeader * wgh = NEW WGuiHeader("Achievements"); + listview->Add(wgh); - aw = NEW WGuiAward(Options::MOMIR_MODE_UNLOCKED,"Momir Mode","Won with exactly 8 lands."); - btn = NEW WGuiButton(aw,-103,Options::MOMIR_MODE_UNLOCKED,this); - listview->Add(btn); - - aw = NEW WGuiAward(Options::EVILTWIN_MODE_UNLOCKED,"Evil Twin Mode","Won with same army size."); - btn = NEW WGuiButton(aw,-103,Options::EVILTWIN_MODE_UNLOCKED,this); - listview->Add(btn); - - aw = NEW WGuiAward(Options::RANDOMDECK_MODE_UNLOCKED,"Random Deck Mode","Won against a higher difficulty."); - btn = NEW WGuiButton(aw,-103,Options::RANDOMDECK_MODE_UNLOCKED,this); - listview->Add(btn); - - aw = NEW WGuiAward(Options::AWARD_COLLECTOR,"Valuable Collection","Collection valued over 10,000c.","Collection Info"); - btn = NEW WGuiButton(aw,-103,Options::AWARD_COLLECTOR,this); - listview->Add(btn); - - wgh = NEW WGuiHeader(""); - listview->Add(wgh); - - int locked = 0; - for (int i = 0; i < setlist.size(); i++){ - MTGSetInfo * si = setlist.getInfo(i); - if(!si) - continue; - if(!options[Options::optionSet(i)].number){ - locked++; - continue; - } - - if(!si->author.size()) - sprintf(buf,_("%i cards.").c_str(),si->totalCards()); - else if(si->year > 0) - sprintf(buf,_("%s (%i): %i cards").c_str(),si->author.c_str(),si->year,si->totalCards()); - else - sprintf(buf,_("%s: %i cards.").c_str(),si->author.c_str(),si->totalCards()); - - - aw = NEW WGuiAward(Options::optionSet(i),si->getName(),buf,"Card Spoiler"); - aw->mFlags = WGuiItem::NO_TRANSLATE; - btn = NEW WGuiButton(aw,-103,Options::optionSet(i),this); + aw = NEW WGuiAward(Options::DIFFICULTY_MODE_UNLOCKED, "Difficulty Modes", "Achieved a 66% victory ratio."); + btn = NEW WGuiButton(aw, -103, Options::DIFFICULTY_MODE_UNLOCKED, this); listview->Add(btn); - } - if(locked) - sprintf(buf,_("%i locked sets remain.").c_str(),locked); - else - sprintf(buf,_("Unlocked all %i sets.").c_str(),setlist.size()); - - wgh->setDisplay(buf); - wgh->mFlags = WGuiItem::NO_TRANSLATE; - listview->Entering(JGE_BTN_NONE); - detailview = NULL; - setSrc = NULL; - showMenu = false; + aw = NEW WGuiAward(Options::MOMIR_MODE_UNLOCKED, "Momir Mode", "Won with exactly 8 lands."); + btn = NEW WGuiButton(aw, -103, Options::MOMIR_MODE_UNLOCKED, this); + listview->Add(btn); + + aw = NEW WGuiAward(Options::EVILTWIN_MODE_UNLOCKED, "Evil Twin Mode", "Won with same army size."); + btn = NEW WGuiButton(aw, -103, Options::EVILTWIN_MODE_UNLOCKED, this); + listview->Add(btn); + + aw = NEW WGuiAward(Options::RANDOMDECK_MODE_UNLOCKED, "Random Deck Mode", "Won against a higher difficulty."); + btn = NEW WGuiButton(aw, -103, Options::RANDOMDECK_MODE_UNLOCKED, this); + listview->Add(btn); + + aw = NEW WGuiAward(Options::AWARD_COLLECTOR, "Valuable Collection", "Collection valued over 10,000c.", "Collection Info"); + btn = NEW WGuiButton(aw, -103, Options::AWARD_COLLECTOR, this); + listview->Add(btn); + + wgh = NEW WGuiHeader(""); + listview->Add(wgh); + + int locked = 0; + for (int i = 0; i < setlist.size(); i++) + { + MTGSetInfo * si = setlist.getInfo(i); + if (!si) + continue; + if (!options[Options::optionSet(i)].number) + { + locked++; + continue; + } + + if (!si->author.size()) + sprintf(buf, _("%i cards.").c_str(), si->totalCards()); + else if (si->year > 0) + sprintf(buf, _("%s (%i): %i cards").c_str(), si->author.c_str(), si->year, si->totalCards()); + else + sprintf(buf, _("%s: %i cards.").c_str(), si->author.c_str(), si->totalCards()); + + aw = NEW WGuiAward(Options::optionSet(i), si->getName(), buf, "Card Spoiler"); + aw->mFlags = WGuiItem::NO_TRANSLATE; + btn = NEW WGuiButton(aw, -103, Options::optionSet(i), this); + listview->Add(btn); + } + if (locked) + sprintf(buf, _("%i locked sets remain.").c_str(), locked); + else + sprintf(buf, _("Unlocked all %i sets.").c_str(), setlist.size()); + + wgh->setDisplay(buf); + wgh->mFlags = WGuiItem::NO_TRANSLATE; + + listview->Entering(JGE_BTN_NONE); + detailview = NULL; + setSrc = NULL; + showMenu = false; } void GameStateAwards::Create() @@ -128,227 +132,251 @@ void GameStateAwards::Destroy() { } - void GameStateAwards::Render() { JRenderer * r = JRenderer::GetInstance(); r->ClearScreen(ARGB(0,0,0,0)); - JQuad * mBg = resources.RetrieveTempQuad("awardback.jpg",TEXTURE_SUB_5551); - if(mBg) - r->RenderQuad(mBg, 0, 0); - - switch(mState){ - case STATE_LISTVIEW: - if(listview) - listview->Render(); + JQuad * mBg = resources.RetrieveTempQuad("awardback.jpg", TEXTURE_SUB_5551); + if (mBg) + r->RenderQuad(mBg, 0, 0); + + switch (mState) + { + case STATE_LISTVIEW: + if (listview) + listview->Render(); break; - case STATE_DETAILS: - if(detailview) - detailview->Render(); + case STATE_DETAILS: + if (detailview) + detailview->Render(); break; } - - if(showMenu && menu) - menu->Render(); + + if (showMenu && menu) + menu->Render(); } void GameStateAwards::Update(float dt) { - if(mEngine->GetButtonClick(JGE_BTN_CANCEL)) - options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; + if (mEngine->GetButtonClick(JGE_BTN_CANCEL)) + options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; - if(showMenu){ - menu->Update(dt); - } - else{ - JButton key; - while ((key = JGE::GetInstance()->ReadButton())){ - switch(key){ - case JGE_BTN_MENU: - showMenu = true; - SAFE_DELETE(menu); - menu = NEW SimpleMenu(-102, this,Fonts::MENU_FONT, 50,170); - if(mState == STATE_DETAILS) - menu->Add(kBackToTrophiesID, "Back to Trophies"); - menu->Add(kBackToMainMenuID, "Back to Main Menu"); - menu->Add(kCancelMenuID, "Cancel"); - break; - case JGE_BTN_PREV: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - break; - case JGE_BTN_SEC: - if(mState == STATE_LISTVIEW) - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - else{ - mState = STATE_LISTVIEW; - SAFE_DELETE(detailview); - } - break; - default: - if(mState == STATE_LISTVIEW && listview){ - listview->CheckUserInput(key); - listview->Update(dt); - } - else if(mState == STATE_DETAILS && detailview){ - detailview->CheckUserInput(key); - detailview->Update(dt); - } - break; - } + if (showMenu) + { + menu->Update(dt); } - } - if(setSrc) - setSrc->Update(dt); + else + { + JButton key; + while ((key = JGE::GetInstance()->ReadButton())) + { + switch (key) + { + case JGE_BTN_MENU: + showMenu = true; + SAFE_DELETE(menu); + menu = NEW SimpleMenu(-102, this, Fonts::MENU_FONT, 50, 170); + if (mState == STATE_DETAILS) + menu->Add(kBackToTrophiesID, "Back to Trophies"); + menu->Add(kBackToMainMenuID, "Back to Main Menu"); + menu->Add(kCancelMenuID, "Cancel"); + break; + case JGE_BTN_PREV: + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + break; + case JGE_BTN_SEC: + if (mState == STATE_LISTVIEW) + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + else + { + mState = STATE_LISTVIEW; + SAFE_DELETE(detailview); + } + break; + default: + if (mState == STATE_LISTVIEW && listview) + { + listview->CheckUserInput(key); + listview->Update(dt); + } + else if (mState == STATE_DETAILS && detailview) + { + detailview->CheckUserInput(key); + detailview->Update(dt); + } + break; + } + } + } + if (setSrc) + setSrc->Update(dt); } -bool GameStateAwards::enterSet(int setid){ - MTGSetInfo * si = setlist.getInfo(setid); - map::iterator it; +bool GameStateAwards::enterSet(int setid) +{ + MTGSetInfo * si = setlist.getInfo(setid); + map::iterator it; - if(!si) - return false; + if (!si) + return false; - SAFE_DELETE(detailview); - SAFE_DELETE(setSrc); + SAFE_DELETE(detailview); + SAFE_DELETE(setSrc); - setSrc = NEW WSrcCards(); - setSrc->addFilter(NEW WCFilterSet(setid)); - setSrc->loadMatches(mParent->collection); - setSrc->bakeFilters(); - setSrc->Sort(WSrcCards::SORT_COLLECTOR); + setSrc = NEW WSrcCards(); + setSrc->addFilter(NEW WCFilterSet(setid)); + setSrc->loadMatches(mParent->collection); + setSrc->bakeFilters(); + setSrc->Sort(WSrcCards::SORT_COLLECTOR); - detailview = NEW WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP); - - WGuiList * spoiler = NEW WGuiList("Spoiler",setSrc); - spoiler->setX(210); - spoiler->setWidth(SCREEN_WIDTH - 220); - for(int t=0;tSize();t++){ - MTGCard * c = setSrc->getCard(t); - if(c) - spoiler->Add(NEW WGuiItem(c->data->name)); - } - setSrc->setOffset(0); - spoiler->Entering(JGE_BTN_NONE); - WGuiCardImage * wi = NEW WGuiCardImage(setSrc); - wi->setX(105); - wi->setY(137); - detailview->Add(wi); - detailview->Add(spoiler); - detailview->Entering(JGE_BTN_NONE); - return true; + detailview = NEW WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP); + + WGuiList * spoiler = NEW WGuiList("Spoiler", setSrc); + spoiler->setX(210); + spoiler->setWidth(SCREEN_WIDTH - 220); + for (int t = 0; t < setSrc->Size(); t++) + { + MTGCard * c = setSrc->getCard(t); + if (c) + spoiler->Add(NEW WGuiItem(c->data->name)); + } + setSrc->setOffset(0); + spoiler->Entering(JGE_BTN_NONE); + WGuiCardImage * wi = NEW WGuiCardImage(setSrc); + wi->setX(105); + wi->setY(137); + detailview->Add(wi); + detailview->Add(spoiler); + detailview->Entering(JGE_BTN_NONE); + return true; } -bool GameStateAwards::enterStats(int option){ - if(option != Options::AWARD_COLLECTOR) - return false; - DeckDataWrapper* ddw = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), mParent->collection)); - if(!ddw) - return false; +bool GameStateAwards::enterStats(int option) +{ + if (option != Options::AWARD_COLLECTOR) + return false; + DeckDataWrapper* ddw = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), mParent->collection)); + if (!ddw) + return false; - SAFE_DELETE(detailview); - detailview = NEW WGuiList("Details"); - - detailview->Add(NEW WGuiHeader("Collection Stats")); - detailview->Entering(JGE_BTN_NONE); + SAFE_DELETE(detailview); + detailview = NEW WGuiList("Details"); - //Discover favorite set - if(setlist.size() > 0){ - int * counts = (int*)calloc(setlist.size(),sizeof(int)); - int setid = -1; - int dupes = 0; - MTGCard * many = NULL; - MTGCard * costly = NULL; - MTGCard * strong = NULL; - MTGCard * tough = NULL; + detailview->Add(NEW WGuiHeader("Collection Stats")); + detailview->Entering(JGE_BTN_NONE); - for (int t=0;tSize();t++){ - MTGCard * c = ddw->getCard(t); - if(!c) - continue; - int count = ddw->count(c); - if(!c->data->isLand() && (many == NULL || count > dupes)){ - many = c; - dupes = count; - } - counts[c->setId]+=count; - if(costly == NULL - || c->data->getManaCost()->getConvertedCost() > costly->data->getManaCost()->getConvertedCost()) - costly = c; + //Discover favorite set + if (setlist.size() > 0) + { + int * counts = (int*) calloc(setlist.size(), sizeof(int)); + int setid = -1; + int dupes = 0; + MTGCard * many = NULL; + MTGCard * costly = NULL; + MTGCard * strong = NULL; + MTGCard * tough = NULL; - if(c->data->isCreature() && (strong == NULL || c->data->getPower() > strong->data->getPower())) - strong = c; + for (int t = 0; t < ddw->Size(); t++) + { + MTGCard * c = ddw->getCard(t); + if (!c) + continue; + int count = ddw->count(c); + if (!c->data->isLand() && (many == NULL || count > dupes)) + { + many = c; + dupes = count; + } + counts[c->setId] += count; + if (costly == NULL || c->data->getManaCost()->getConvertedCost() > costly->data->getManaCost()->getConvertedCost()) + costly = c; - if(c->data->isCreature() && (tough == NULL || c->data->getToughness() > tough->data->getToughness())) - tough = c; + if (c->data->isCreature() && (strong == NULL || c->data->getPower() > strong->data->getPower())) + strong = c; + + if (c->data->isCreature() && (tough == NULL || c->data->getToughness() > tough->data->getToughness())) + tough = c; + } + for (int i = 0; i < setlist.size(); i++) + { + if (setid < 0 || counts[i] > counts[setid]) + setid = i; + } + free(counts); + + char buf[1024]; + sprintf(buf, _("Total Value: %ic").c_str(), ddw->totalPrice()); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE));//ddw->colors + + sprintf(buf, _("Total Cards (including duplicates): %i").c_str(), ddw->getCount(WSrcDeck::UNFILTERED_COPIES)); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE));//ddw->colors + + sprintf(buf, _("Unique Cards: %i").c_str(), ddw->getCount(WSrcDeck::UNFILTERED_UNIQUE)); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE)); + + if (many) + { + sprintf(buf, _("Most Duplicates: %i (%s)").c_str(), dupes, many->data->getName().c_str()); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE)); + } + if (setid >= 0) + { + sprintf(buf, _("Favorite Set: %s").c_str(), setlist[setid].c_str()); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE)); + } + if (costly) + { + sprintf(buf, _("Highest Mana Cost: %i (%s)").c_str(), costly->data->getManaCost()->getConvertedCost(), + costly->data->getName().c_str()); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE)); + } + if (strong) + { + sprintf(buf, _("Most Powerful: %i (%s)").c_str(), strong->data->getPower(), strong->data->getName().c_str()); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE)); + } + if (tough) + { + sprintf(buf, _("Toughest: %i (%s)").c_str(), tough->data->getToughness(), strong->data->getName().c_str()); + detailview->Add(NEW WGuiItem(buf, WGuiItem::NO_TRANSLATE)); + } } - for(int i=0;i counts[setid]) - setid = i; - } - free(counts); - char buf[1024]; - sprintf(buf,_("Total Value: %ic").c_str(),ddw->totalPrice()); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE));//ddw->colors - - sprintf(buf,_("Total Cards (including duplicates): %i").c_str(),ddw->getCount(WSrcDeck::UNFILTERED_COPIES)); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE));//ddw->colors - - sprintf(buf,_("Unique Cards: %i").c_str(),ddw->getCount(WSrcDeck::UNFILTERED_UNIQUE)); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE)); - - if(many){ - sprintf(buf,_("Most Duplicates: %i (%s)").c_str(),dupes,many->data->getName().c_str()); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE)); - } - if(setid >= 0){ - sprintf(buf,_("Favorite Set: %s").c_str(),setlist[setid].c_str()); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE)); - } - if(costly){ - sprintf(buf,_("Highest Mana Cost: %i (%s)").c_str(),costly->data->getManaCost()->getConvertedCost(),costly->data->getName().c_str()); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE)); - } - if(strong){ - sprintf(buf,_("Most Powerful: %i (%s)").c_str(),strong->data->getPower(),strong->data->getName().c_str()); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE)); - } - if(tough){ - sprintf(buf,_("Toughest: %i (%s)").c_str(),tough->data->getToughness(),strong->data->getName().c_str()); - detailview->Add(NEW WGuiItem(buf,WGuiItem::NO_TRANSLATE)); - } - } - - SAFE_DELETE(ddw->parent); - SAFE_DELETE(ddw); - return true; + SAFE_DELETE(ddw->parent); + SAFE_DELETE(ddw); + return true; } void GameStateAwards::ButtonPressed(int controllerId, int controlId) { - if(controllerId == -102) - switch (controlId){ - case kBackToMainMenuID: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - showMenu = false; - break; - case kBackToTrophiesID: - mState = STATE_LISTVIEW; - SAFE_DELETE(detailview); - showMenu = false; - break; - case 3: - showMenu = false; - break; - } - else if(controllerId == -103){ - int setid = controlId-Options::SET_UNLOCKS; + if (controllerId == -102) + switch (controlId) + { + case kBackToMainMenuID: + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + showMenu = false; + break; + case kBackToTrophiesID: + mState = STATE_LISTVIEW; + SAFE_DELETE(detailview); + showMenu = false; + break; + case 3: + showMenu = false; + break; + } + else if (controllerId == -103) + { + int setid = controlId - Options::SET_UNLOCKS; - if(controlId >= Options::SET_UNLOCKS && enterSet(setid)){ - mState = STATE_DETAILS; - mDetailItem = controlId; - - }else if(controlId == Options::AWARD_COLLECTOR && enterStats(controlId)){ - mState = STATE_DETAILS; - } - } + if (controlId >= Options::SET_UNLOCKS && enterSet(setid)) + { + mState = STATE_DETAILS; + mDetailItem = controlId; + + } + else if (controlId == Options::AWARD_COLLECTOR && enterStats(controlId)) + { + mState = STATE_DETAILS; + } + } } diff --git a/projects/mtg/src/GameStateDeckViewer.cpp b/projects/mtg/src/GameStateDeckViewer.cpp index 8be86cec1..2831429c9 100644 --- a/projects/mtg/src/GameStateDeckViewer.cpp +++ b/projects/mtg/src/GameStateDeckViewer.cpp @@ -19,1605 +19,1820 @@ #include "DeckEditorMenu.h" #include "SimpleMenu.h" - //!! helper function; this is probably handled somewhere in the code already. // If not, should be placed in general library -void StringExplode(string str, string separator, vector* results){ - size_t found; - found = str.find_first_of(separator); - while (found != string::npos){ - if (found > 0) - results->push_back(str.substr(0,found)); - str = str.substr(found+1); +void StringExplode(string str, string separator, vector* results) +{ + size_t found; found = str.find_first_of(separator); - } - if (str.length() > 0) - results->push_back(str); -} - -GameStateDeckViewer::GameStateDeckViewer(GameApp* parent): GameState(parent) { - bgMusic = NULL; - nbDecks = 0; - deckNum = 0; - useFilter = 0; - isAIDeckSave = false; - mSwitching = false; - welcome_menu = NULL; - myCollection = NULL; - myDeck = NULL; - filterMenu = NULL; - source = NULL; - hudAlpha = 0; - subMenu = NULL; - mRotation = 0; - mSlide = 0; - mAlpha = 255; - menu = NULL; - stw = NULL; -} - -GameStateDeckViewer::~GameStateDeckViewer() { - SAFE_DELETE(bgMusic); - if(myDeck){ - SAFE_DELETE(myDeck->parent); - SAFE_DELETE(myDeck); - } - if(myCollection){ - SAFE_DELETE(myCollection->parent); - SAFE_DELETE(myCollection); - } - SAFE_DELETE(stw); - SAFE_DELETE(filterMenu); -} - - -void GameStateDeckViewer::rotateCards(int direction){ - int left = direction; - if (left) - displayed_deck->next(); - else - displayed_deck->prev(); - loadIndexes(); - - int total = displayed_deck->Size(); - if (total) { - lastPos = getCurrentPos(); - lastTotal = total; - } - int i = 0; -} -void GameStateDeckViewer::rebuildFilters(){ - if(!filterMenu) filterMenu = NEW WGuiFilters("Filter by...",NULL); - if(source) SAFE_DELETE(source); - source = NEW WSrcDeckViewer(myDeck,myCollection); - filterMenu->setSrc(source); - if(displayed_deck != myDeck) source->swapSrc(); - filterMenu->Finish(true); - updateStats(); -} -void GameStateDeckViewer::updateFilters(){ - if(!displayed_deck) return; - - filterMenu->recolorFilter(useFilter-1); - filterMenu->Finish(true); - int totalAfter = displayed_deck->Size(); - if (totalAfter && lastTotal) { - - //This part is a hack. I don't understand why in some cases "displayed_deck's" currentPos is not 0 at this stage + while (found != string::npos) { - while (int currentPos = displayed_deck->getOffset()) { - if (currentPos > 0) displayed_deck->prev(); - else displayed_deck->next(); - } + if (found > 0) + results->push_back(str.substr(0, found)); + str = str.substr(found + 1); + found = str.find_first_of(separator); } + if (str.length() > 0) + results->push_back(str); +} - int pos = (totalAfter * lastPos) / lastTotal ; - for (int i = 0; i < pos - 3 ; ++i){ // "-3" because card "0" is displayed at position 3 initially - displayed_deck->next(); +GameStateDeckViewer::GameStateDeckViewer(GameApp* parent) : + GameState(parent) +{ + bgMusic = NULL; + nbDecks = 0; + deckNum = 0; + useFilter = 0; + isAIDeckSave = false; + mSwitching = false; + welcome_menu = NULL; + myCollection = NULL; + myDeck = NULL; + filterMenu = NULL; + source = NULL; + hudAlpha = 0; + subMenu = NULL; + mRotation = 0; + mSlide = 0; + mAlpha = 255; + menu = NULL; + stw = NULL; +} + +GameStateDeckViewer::~GameStateDeckViewer() +{ + SAFE_DELETE(bgMusic); + if (myDeck) + { + SAFE_DELETE(myDeck->parent); + SAFE_DELETE(myDeck); } - } - updateStats(); - return; -} -void GameStateDeckViewer::loadIndexes(){ - for (int i = 0; i < 7; i++){ - cardIndex[i] = displayed_deck->getCard(i); - } + if (myCollection) + { + SAFE_DELETE(myCollection->parent); + SAFE_DELETE(myCollection); + } + SAFE_DELETE(stw); + SAFE_DELETE(filterMenu); } -void GameStateDeckViewer::switchDisplay(){ - if (displayed_deck == myCollection){ - displayed_deck = myDeck; - }else{ - displayed_deck = myCollection; - } - source->swapSrc(); - updateFilters(); - loadIndexes(); +void GameStateDeckViewer::rotateCards(int direction) +{ + int left = direction; + if (left) + displayed_deck->next(); + else + displayed_deck->prev(); + loadIndexes(); + + int total = displayed_deck->Size(); + if (total) + { + lastPos = getCurrentPos(); + lastTotal = total; + } + int i = 0; +} +void GameStateDeckViewer::rebuildFilters() +{ + if (!filterMenu) + filterMenu = NEW WGuiFilters("Filter by...", NULL); + if (source) + SAFE_DELETE(source); + source = NEW WSrcDeckViewer(myDeck, myCollection); + filterMenu->setSrc(source); + if (displayed_deck != myDeck) + source->swapSrc(); + filterMenu->Finish(true); + updateStats(); +} +void GameStateDeckViewer::updateFilters() +{ + if (!displayed_deck) + return; + + filterMenu->recolorFilter(useFilter - 1); + filterMenu->Finish(true); + int totalAfter = displayed_deck->Size(); + if (totalAfter && lastTotal) + { + + //This part is a hack. I don't understand why in some cases "displayed_deck's" currentPos is not 0 at this stage + { + while (int currentPos = displayed_deck->getOffset()) + { + if (currentPos > 0) + displayed_deck->prev(); + else + displayed_deck->next(); + } + } + + int pos = (totalAfter * lastPos) / lastTotal; + for (int i = 0; i < pos - 3; ++i) + { // "-3" because card "0" is displayed at position 3 initially + displayed_deck->next(); + } + } + updateStats(); + return; +} +void GameStateDeckViewer::loadIndexes() +{ + for (int i = 0; i < 7; i++) + { + cardIndex[i] = displayed_deck->getCard(i); + } } -void GameStateDeckViewer::updateDecks(){ - SAFE_DELETE(welcome_menu); - welcome_menu = NEW DeckEditorMenu( MENU_DECK_SELECTION, this, Fonts::OPTION_FONT, "Choose Deck To Edit"); - DeckManager * deckManager = DeckManager::GetInstance(); - vector playerDeckList = fillDeckMenu( welcome_menu,options.profileFile()); - - deckNum = 0; - newDeckname = ""; - nbDecks = playerDeckList.size() + 1; - welcome_menu->Add( MENU_ITEM_NEW_DECK, "--NEW--"); - if(options[Options::CHEATMODE].number && (!myCollection || myCollection->getCount(WSrcDeck::UNFILTERED_MIN_COPIES) < 4)) - welcome_menu->Add( MENU_ITEM_CHEAT_MODE, "--UNLOCK CARDS--" ); - welcome_menu->Add( MENU_ITEM_CANCEL, "Cancel"); - - // update the deckmanager with the latest information - deckManager->updateMetaDataList( &playerDeckList, false); - // is this necessary to ensure no memory leaks? - playerDeckList.clear(); +void GameStateDeckViewer::switchDisplay() +{ + if (displayed_deck == myCollection) + { + displayed_deck = myDeck; + } + else + { + displayed_deck = myCollection; + } + source->swapSrc(); + updateFilters(); + loadIndexes(); } +void GameStateDeckViewer::updateDecks() +{ + SAFE_DELETE(welcome_menu); + welcome_menu = NEW DeckEditorMenu(MENU_DECK_SELECTION, this, Fonts::OPTION_FONT, "Choose Deck To Edit"); + DeckManager * deckManager = DeckManager::GetInstance(); + vector playerDeckList = fillDeckMenu(welcome_menu, options.profileFile()); + + deckNum = 0; + newDeckname = ""; + nbDecks = playerDeckList.size() + 1; + welcome_menu->Add(MENU_ITEM_NEW_DECK, "--NEW--"); + if (options[Options::CHEATMODE].number && (!myCollection || myCollection->getCount(WSrcDeck::UNFILTERED_MIN_COPIES) < 4)) + welcome_menu->Add(MENU_ITEM_CHEAT_MODE, "--UNLOCK CARDS--"); + welcome_menu->Add(MENU_ITEM_CANCEL, "Cancel"); + + // update the deckmanager with the latest information + deckManager->updateMetaDataList(&playerDeckList, false); + // is this necessary to ensure no memory leaks? + playerDeckList.clear(); +} void GameStateDeckViewer::buildEditorMenu() { - ostringstream deckSummaryInformation; - deckSummaryInformation << "All changes are final." << endl; - - if ( menu ) - SAFE_DELETE( menu ); - //Build menu. - JRenderer::GetInstance()->FillRoundRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 100, ARGB(0, 0, 0, 0) ); - menu = NEW DeckEditorMenu( MENU_DECK_BUILDER, this, Fonts::OPTION_FONT, "Deck Editor", myDeck, stw ); + ostringstream deckSummaryInformation; + deckSummaryInformation << "All changes are final." << endl; + + if (menu) + SAFE_DELETE( menu ); + //Build menu. + JRenderer::GetInstance()->FillRoundRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 100, ARGB(0, 0, 0, 0) ); + menu = NEW DeckEditorMenu(MENU_DECK_BUILDER, this, Fonts::OPTION_FONT, "Deck Editor", myDeck, stw); + + menu->Add(MENU_ITEM_FILTER_BY, "Filter By...", "Narrow down the list of cards. "); + menu->Add(MENU_ITEM_SWITCH_DECKS_NO_SAVE, "Switch Decks", "Do not make any changes.\nView another deck."); + menu->Add(MENU_ITEM_SAVE_RENAME, "Rename Deck", "Change the name of the deck"); + menu->Add(MENU_ITEM_SAVE_RETURN_MAIN_MENU, "Save & Quit Editor", "Save changes.\nReturn to the main menu"); + menu->Add(MENU_ITEM_SAVE_AS_AI_DECK, "Save As AI Deck", deckSummaryInformation.str()); + menu->Add(MENU_ITEM_MAIN_MENU, "Quit Editor", "Do not make any changes to deck.\nReturn to the main menu."); + menu->Add(MENU_ITEM_EDITOR_CANCEL, "Cancel", "Close menu."); - menu->Add( MENU_ITEM_FILTER_BY, "Filter By...", "Narrow down the list of cards. "); - menu->Add( MENU_ITEM_SWITCH_DECKS_NO_SAVE, "Switch Decks", "Do not make any changes.\nView another deck."); - menu->Add( MENU_ITEM_SAVE_RENAME, "Rename Deck", "Change the name of the deck"); - menu->Add( MENU_ITEM_SAVE_RETURN_MAIN_MENU, "Save & Quit Editor", "Save changes.\nReturn to the main menu"); - menu->Add( MENU_ITEM_SAVE_AS_AI_DECK, "Save As AI Deck", deckSummaryInformation.str() ); - menu->Add( MENU_ITEM_MAIN_MENU, "Quit Editor", "Do not make any changes to deck.\nReturn to the main menu."); - menu->Add( MENU_ITEM_EDITOR_CANCEL, "Cancel", "Close menu."); - } void GameStateDeckViewer::Start() { - hudAlpha = 0; - mSwitching = false; - subMenu = NULL; - myDeck = NULL; - mStage = STAGE_WELCOME; - mRotation = 0; - mSlide = 0; - mAlpha = 255; - last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; - onScreenTransition = 0; - useFilter = 0; - lastPos = 0; - lastTotal = 0; + hudAlpha = 0; + mSwitching = false; + subMenu = NULL; + myDeck = NULL; + mStage = STAGE_WELCOME; + mRotation = 0; + mSlide = 0; + mAlpha = 255; + last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; + onScreenTransition = 0; + useFilter = 0; + lastPos = 0; + lastTotal = 0; - pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(),mParent->collection); - playerdata = NEW PlayerData(mParent->collection); - myCollection = NEW DeckDataWrapper(playerdata->collection); - myCollection->Sort(WSrcCards::SORT_ALPHA); - displayed_deck = myCollection; + pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(), mParent->collection); + playerdata = NEW PlayerData(mParent->collection); + myCollection = NEW DeckDataWrapper(playerdata->collection); + myCollection->Sort(WSrcCards::SORT_ALPHA); + displayed_deck = myCollection; //Icons - mIcons[Constants::MTG_COLOR_ARTIFACT] = resources.GetQuad("c_artifact"); - mIcons[Constants::MTG_COLOR_LAND] = resources.GetQuad("c_land"); - mIcons[Constants::MTG_COLOR_WHITE] = resources.GetQuad("c_white"); - mIcons[Constants::MTG_COLOR_RED] = resources.GetQuad("c_red"); - mIcons[Constants::MTG_COLOR_BLACK] = resources.GetQuad("c_black"); - mIcons[Constants::MTG_COLOR_BLUE] = resources.GetQuad("c_blue"); - mIcons[Constants::MTG_COLOR_GREEN] = resources.GetQuad("c_green"); - for (int i=0; i < 7; i++){ - mIcons[i]->SetHotSpot(16,16); - } + mIcons[Constants::MTG_COLOR_ARTIFACT] = resources.GetQuad("c_artifact"); + mIcons[Constants::MTG_COLOR_LAND] = resources.GetQuad("c_land"); + mIcons[Constants::MTG_COLOR_WHITE] = resources.GetQuad("c_white"); + mIcons[Constants::MTG_COLOR_RED] = resources.GetQuad("c_red"); + mIcons[Constants::MTG_COLOR_BLACK] = resources.GetQuad("c_black"); + mIcons[Constants::MTG_COLOR_BLUE] = resources.GetQuad("c_blue"); + mIcons[Constants::MTG_COLOR_GREEN] = resources.GetQuad("c_green"); + for (int i = 0; i < 7; i++) + { + mIcons[i]->SetHotSpot(16, 16); + } - //Grab a texture in VRAM. - pspIconsTexture = resources.RetrieveTexture("iconspsp.png", RETRIEVE_LOCK); + //Grab a texture in VRAM. + pspIconsTexture = resources.RetrieveTexture("iconspsp.png", RETRIEVE_LOCK); - char buf[512]; - for (int i=0; i < 8; i++){ - sprintf(buf,"iconspsp%d",i); - pspIcons[i] = resources.RetrieveQuad("iconspsp.png", (float)i*32, 0, 32, 32,buf); - pspIcons[i]->SetHotSpot(16,16); - } + char buf[512]; + for (int i = 0; i < 8; i++) + { + sprintf(buf, "iconspsp%d", i); + pspIcons[i] = resources.RetrieveQuad("iconspsp.png", (float) i * 32, 0, 32, 32, buf); + pspIcons[i]->SetHotSpot(16, 16); + } - backQuad = resources.GetQuad("back"); + backQuad = resources.GetQuad("back"); - //init welcome menu - updateDecks(); + //init welcome menu + updateDecks(); - GameApp::playMusic("track1.mp3"); - - loadIndexes(); - mEngine->ResetInput(); - JRenderer::GetInstance()->EnableVSync(true); - } + GameApp::playMusic("track1.mp3"); + loadIndexes(); + mEngine->ResetInput(); + JRenderer::GetInstance()->EnableVSync(true); +} void GameStateDeckViewer::End() { - JRenderer::GetInstance()->EnableVSync(false); + JRenderer::GetInstance()->EnableVSync(false); - SAFE_DELETE(welcome_menu); - SAFE_DELETE(menu); - SAFE_DELETE(subMenu); + SAFE_DELETE(welcome_menu); + SAFE_DELETE(menu); + SAFE_DELETE(subMenu); - resources.Release(pspIconsTexture); - if(myCollection){ - SAFE_DELETE(myCollection); - } - if(myDeck){ - SAFE_DELETE(myDeck->parent); - SAFE_DELETE(myDeck); - } - SAFE_DELETE(pricelist); - SAFE_DELETE(playerdata); - SAFE_DELETE(filterMenu); - SAFE_DELETE(source); -} - - -void GameStateDeckViewer::addRemove(MTGCard * card){ - if (!card) return; - if (displayed_deck->Remove(card,1,(displayed_deck==myDeck))){ - if (displayed_deck == myCollection){ - myDeck->Add(card); - myDeck->Sort(WSrcCards::SORT_ALPHA); - }else{ - myCollection->Add(card); + resources.Release(pspIconsTexture); + if (myCollection) + { + SAFE_DELETE(myCollection); } - } - myCollection->validate(); - myDeck->validate(); - stw->needUpdate = true; - loadIndexes(); + if (myDeck) + { + SAFE_DELETE(myDeck->parent); + SAFE_DELETE(myDeck); + } + SAFE_DELETE(pricelist); + SAFE_DELETE(playerdata); + SAFE_DELETE(filterMenu); + SAFE_DELETE(source); } -void GameStateDeckViewer::saveDeck(){ - myDeck->save(); - playerdata->save(); - pricelist->save(); +void GameStateDeckViewer::addRemove(MTGCard * card) +{ + if (!card) + return; + if (displayed_deck->Remove(card, 1, (displayed_deck == myDeck))) + { + if (displayed_deck == myCollection) + { + myDeck->Add(card); + myDeck->Sort(WSrcCards::SORT_ALPHA); + } + else + { + myCollection->Add(card); + } + } + myCollection->validate(); + myDeck->validate(); + stw->needUpdate = true; + loadIndexes(); +} + +void GameStateDeckViewer::saveDeck() +{ + myDeck->save(); + playerdata->save(); + pricelist->save(); } /** - save the deck in a readable format to allow people to edit the file offline -*/ -void GameStateDeckViewer::saveAsAIDeck( string deckName ) + save the deck in a readable format to allow people to edit the file offline + */ +void GameStateDeckViewer::saveAsAIDeck(string deckName) { - DeckManager * deckManager = DeckManager::GetInstance(); - vector aiDecks = GameState::getValidDeckMetaData( JGE_GET_RES("ai/baka"), "ai_baka", NULL); - int nbAiDecks = aiDecks.size() + 1; - aiDecks.clear(); + DeckManager * deckManager = DeckManager::GetInstance(); + vector aiDecks = GameState::getValidDeckMetaData(JGE_GET_RES("ai/baka"), "ai_baka", NULL); + int nbAiDecks = aiDecks.size() + 1; + aiDecks.clear(); - string defaultAiDeckName = "deck"; - std::ostringstream oss; - oss << "deck" << nbAiDecks; - defaultAiDeckName = oss.str(); - oss.str(""); - if ( myDeck->parent->meta_desc == "" ) - oss << endl << "Can you beat your own creations?" << endl << "User created AI Deck # " << nbAiDecks; - else - oss << myDeck->parent->meta_desc; - string deckDesc = oss.str(); - string filepath = JGE_GET_RES("ai/baka/"); - filepath.append( defaultAiDeckName ).append( ".txt" ); - DebugTrace("saving AI deck " << filepath); - myDeck->save( filepath, true, deckName, deckDesc); + string defaultAiDeckName = "deck"; + std::ostringstream oss; + oss << "deck" << nbAiDecks; + defaultAiDeckName = oss.str(); + oss.str(""); + if (myDeck->parent->meta_desc == "") + oss << endl << "Can you beat your own creations?" << endl << "User created AI Deck # " << nbAiDecks; + else + oss << myDeck->parent->meta_desc; + string deckDesc = oss.str(); + string filepath = JGE_GET_RES("ai/baka/"); + filepath.append(defaultAiDeckName).append(".txt"); + DebugTrace("saving AI deck " << filepath); + myDeck->save(filepath, true, deckName, deckDesc); } void GameStateDeckViewer::Update(float dt) { - int myD = (displayed_deck == myDeck); + int myD = (displayed_deck == myDeck); - if(options.keypadActive()){ - options.keypadUpdate(dt); - - if(newDeckname != ""){ - newDeckname = options.keypadFinish(); - - if(newDeckname != ""){ - if (isAIDeckSave) - { - saveAsAIDeck( newDeckname ); - isAIDeckSave = false; - } - else if(myDeck && myDeck->parent){ - myDeck->parent->meta_name = newDeckname; - saveDeck(); - } - mStage = STAGE_WAITING; - } - newDeckname = ""; - } - //Prevent screen from updating. - return; - } - hudAlpha = 255 - ((int) last_user_activity * 500); - if (hudAlpha < 0) hudAlpha = 0; - if (subMenu){ - subMenu->Update(dt); - if (subMenu->closed){ - SAFE_DELETE(subMenu); - } - return; - } - if (mStage == STAGE_WAITING || mStage == STAGE_ONSCREEN_MENU){ - switch (mEngine->ReadButton()) + if (options.keypadActive()) { - case JGE_BTN_LEFT : - last_user_activity = 0; - mStage = STAGE_TRANSITION_LEFT; - break; - case JGE_BTN_RIGHT : - last_user_activity = 0; - mStage = STAGE_TRANSITION_RIGHT; - break; - case JGE_BTN_UP : - last_user_activity = 0; - mStage = STAGE_TRANSITION_UP; - useFilter++; - if(useFilter >= MAX_SAVED_FILTERS) - useFilter = 0; - break; - case JGE_BTN_DOWN : - last_user_activity = 0; - mStage = STAGE_TRANSITION_DOWN; - useFilter--; - if(useFilter < 0) - useFilter = MAX_SAVED_FILTERS-1; - break; - case JGE_BTN_CANCEL: - options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; - break; - case JGE_BTN_PRI : - if (last_user_activity > 0.2) - { - last_user_activity = 0; - switchDisplay(); - } - break; - case JGE_BTN_OK : - last_user_activity = 0; - addRemove(cardIndex[2]); - break; - case JGE_BTN_SEC : - last_user_activity = 0; - SAFE_DELETE(subMenu); - char buffer[4096]; - { - MTGCard * card = cardIndex[2]; - if (card && displayed_deck->count(card)){ - price = pricelist->getSellPrice(card->getMTGId()); - sprintf(buffer,"%s : %i %s",_(card->data->getName()).c_str(),price,_("credits").c_str()); - subMenu = NEW SimpleMenu( MENU_CARD_PURCHASE, this, Fonts::MAIN_FONT, SCREEN_WIDTH-300, SCREEN_HEIGHT/2, buffer); - subMenu->Add( MENU_ITEM_YES,"Yes"); - subMenu->Add( MENU_ITEM_NO,"No","",true); + options.keypadUpdate(dt); + + if (newDeckname != "") + { + newDeckname = options.keypadFinish(); + + if (newDeckname != "") + { + if (isAIDeckSave) + { + saveAsAIDeck(newDeckname); + isAIDeckSave = false; + } + else if (myDeck && myDeck->parent) + { + myDeck->parent->meta_name = newDeckname; + saveDeck(); + } + mStage = STAGE_WAITING; + } + newDeckname = ""; } - } - stw->needUpdate = true; - break; - - case JGE_BTN_MENU : - mStage = STAGE_MENU; - buildEditorMenu(); - break; - case JGE_BTN_CTRL : - mStage = STAGE_FILTERS; - if(!filterMenu){ - filterMenu = NEW WGuiFilters("Filter by...",NULL); - if(source) SAFE_DELETE(source); - source = NEW WSrcDeckViewer(myDeck,myCollection); - filterMenu->setSrc(source); - if(displayed_deck != myDeck) source->swapSrc(); - } - filterMenu->Entering(JGE_BTN_NONE); - break; - case JGE_BTN_PREV : - if (last_user_activity < NO_USER_ACTIVITY_HELP_DELAY) - last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; - else if ((mStage == STAGE_ONSCREEN_MENU) && (--stw->currentPage < 0)) - stw->currentPage = stw->pageCount; - break; - case JGE_BTN_NEXT : - if (last_user_activity < NO_USER_ACTIVITY_HELP_DELAY) - last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; - else if ((mStage == STAGE_ONSCREEN_MENU) && (++stw->currentPage > stw->pageCount)) - stw->currentPage = 0; - break; - default : // no keypress - if (last_user_activity > NO_USER_ACTIVITY_HELP_DELAY){ - if (mStage != STAGE_ONSCREEN_MENU){ - mStage = STAGE_ONSCREEN_MENU; - onScreenTransition = 1; - } else { - if (onScreenTransition >0) - onScreenTransition-= 0.05f; - else - onScreenTransition = 0; - } - } else - last_user_activity+= dt; - } - - } if (mStage == STAGE_TRANSITION_RIGHT || mStage == STAGE_TRANSITION_LEFT) { - if (mStage == STAGE_TRANSITION_RIGHT){ - mRotation -= dt * MED_SPEED; - if (mRotation < -1.0f) { - do { - rotateCards(mStage); - mRotation += 1; - } while (mRotation < -1.0f); - mStage = STAGE_WAITING; - mRotation = 0; - } - } else if (mStage == STAGE_TRANSITION_LEFT) { - mRotation += dt * MED_SPEED; - if (mRotation > 1.0f){ - do { - rotateCards(mStage); - mRotation -= 1; - } while (mRotation > 1.0f); - mStage = STAGE_WAITING; - mRotation = 0; - } - } - } if (mStage == STAGE_TRANSITION_DOWN || mStage == STAGE_TRANSITION_UP) { - if (mStage == STAGE_TRANSITION_DOWN) { - mSlide -= 0.05f; - if (mSlide < -1.0f){ - updateFilters(); - loadIndexes(); - mSlide = 1; - } else if (mSlide > 0 && mSlide < 0.05) { - mStage = STAGE_WAITING; - mSlide = 0; - } - } if (mStage == STAGE_TRANSITION_UP) { - mSlide += 0.05f; - if (mSlide > 1.0f){ - updateFilters(); - loadIndexes(); - mSlide = -1; - } else if (mSlide < 0 && mSlide > -0.05) { - mStage = STAGE_WAITING; - mSlide = 0; - } - } - - - } else if (mStage == STAGE_WELCOME) - welcome_menu->Update(dt); - else if (mStage == STAGE_MENU) - menu->Update(dt); - else if(mStage == STAGE_FILTERS){ - JButton key = mEngine->ReadButton(); - if (filterMenu) { - if (key == JGE_BTN_CTRL) { - //useFilter = 0; - filterMenu->Finish(true); - filterMenu->Update(dt); - loadIndexes(); + //Prevent screen from updating. return; - } - if (!filterMenu->isFinished()) { - filterMenu->CheckUserInput(key); - filterMenu->Update(dt); - } - else { - mStage = STAGE_WAITING; - updateFilters(); - loadIndexes(); - } } - } + hudAlpha = 255 - ((int) last_user_activity * 500); + if (hudAlpha < 0) + hudAlpha = 0; + if (subMenu) + { + subMenu->Update(dt); + if (subMenu->closed) + { + SAFE_DELETE(subMenu); + } + return; + } + if (mStage == STAGE_WAITING || mStage == STAGE_ONSCREEN_MENU) + { + switch (mEngine->ReadButton()) + { + case JGE_BTN_LEFT: + last_user_activity = 0; + mStage = STAGE_TRANSITION_LEFT; + break; + case JGE_BTN_RIGHT: + last_user_activity = 0; + mStage = STAGE_TRANSITION_RIGHT; + break; + case JGE_BTN_UP: + last_user_activity = 0; + mStage = STAGE_TRANSITION_UP; + useFilter++; + if (useFilter >= MAX_SAVED_FILTERS) + useFilter = 0; + break; + case JGE_BTN_DOWN: + last_user_activity = 0; + mStage = STAGE_TRANSITION_DOWN; + useFilter--; + if (useFilter < 0) + useFilter = MAX_SAVED_FILTERS - 1; + break; + case JGE_BTN_CANCEL: + options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; + break; + case JGE_BTN_PRI: + if (last_user_activity > 0.2) + { + last_user_activity = 0; + switchDisplay(); + } + break; + case JGE_BTN_OK: + last_user_activity = 0; + addRemove(cardIndex[2]); + break; + case JGE_BTN_SEC: + last_user_activity = 0; + SAFE_DELETE(subMenu); + char buffer[4096]; + { + MTGCard * card = cardIndex[2]; + if (card && displayed_deck->count(card)) + { + price = pricelist->getSellPrice(card->getMTGId()); + sprintf(buffer, "%s : %i %s", _(card->data->getName()).c_str(), price, _("credits").c_str()); + const float menuXOffset = SCREEN_WIDTH_F - 300; + const float menuYOffset = SCREEN_HEIGHT_F / 2; + subMenu = NEW SimpleMenu(MENU_CARD_PURCHASE, this, Fonts::MAIN_FONT, menuXOffset, menuYOffset, buffer); + subMenu->Add(MENU_ITEM_YES, "Yes"); + subMenu->Add(MENU_ITEM_NO, "No", "", true); + } + } + stw->needUpdate = true; + break; + + case JGE_BTN_MENU: + mStage = STAGE_MENU; + buildEditorMenu(); + break; + case JGE_BTN_CTRL: + mStage = STAGE_FILTERS; + if (!filterMenu) + { + filterMenu = NEW WGuiFilters("Filter by...", NULL); + if (source) + SAFE_DELETE(source); + source = NEW WSrcDeckViewer(myDeck, myCollection); + filterMenu->setSrc(source); + if (displayed_deck != myDeck) + source->swapSrc(); + } + filterMenu->Entering(JGE_BTN_NONE); + break; + case JGE_BTN_PREV: + if (last_user_activity < NO_USER_ACTIVITY_HELP_DELAY) + last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; + else if ((mStage == STAGE_ONSCREEN_MENU) && (--stw->currentPage < 0)) + stw->currentPage = stw->pageCount; + break; + case JGE_BTN_NEXT: + if (last_user_activity < NO_USER_ACTIVITY_HELP_DELAY) + last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; + else if ((mStage == STAGE_ONSCREEN_MENU) && (++stw->currentPage > stw->pageCount)) + stw->currentPage = 0; + break; + default: // no keypress + if (last_user_activity > NO_USER_ACTIVITY_HELP_DELAY) + { + if (mStage != STAGE_ONSCREEN_MENU) + { + mStage = STAGE_ONSCREEN_MENU; + onScreenTransition = 1; + } + else + { + if (onScreenTransition > 0) + onScreenTransition -= 0.05f; + else + onScreenTransition = 0; + } + } + else + last_user_activity += dt; + } + + } + if (mStage == STAGE_TRANSITION_RIGHT || mStage == STAGE_TRANSITION_LEFT) + { + if (mStage == STAGE_TRANSITION_RIGHT) + { + mRotation -= dt * MED_SPEED; + if (mRotation < -1.0f) + { + do + { + rotateCards(mStage); + mRotation += 1; + } while (mRotation < -1.0f); + mStage = STAGE_WAITING; + mRotation = 0; + } + } + else if (mStage == STAGE_TRANSITION_LEFT) + { + mRotation += dt * MED_SPEED; + if (mRotation > 1.0f) + { + do + { + rotateCards(mStage); + mRotation -= 1; + } while (mRotation > 1.0f); + mStage = STAGE_WAITING; + mRotation = 0; + } + } + } + if (mStage == STAGE_TRANSITION_DOWN || mStage == STAGE_TRANSITION_UP) + { + if (mStage == STAGE_TRANSITION_DOWN) + { + mSlide -= 0.05f; + if (mSlide < -1.0f) + { + updateFilters(); + loadIndexes(); + mSlide = 1; + } + else if (mSlide > 0 && mSlide < 0.05) + { + mStage = STAGE_WAITING; + mSlide = 0; + } + } + if (mStage == STAGE_TRANSITION_UP) + { + mSlide += 0.05f; + if (mSlide > 1.0f) + { + updateFilters(); + loadIndexes(); + mSlide = -1; + } + else if (mSlide < 0 && mSlide > -0.05) + { + mStage = STAGE_WAITING; + mSlide = 0; + } + } + + } + else if (mStage == STAGE_WELCOME) + welcome_menu->Update(dt); + else if (mStage == STAGE_MENU) + menu->Update(dt); + else if (mStage == STAGE_FILTERS) + { + JButton key = mEngine->ReadButton(); + if (filterMenu) + { + if (key == JGE_BTN_CTRL) + { + //useFilter = 0; + filterMenu->Finish(true); + filterMenu->Update(dt); + loadIndexes(); + return; + } + if (!filterMenu->isFinished()) + { + filterMenu->CheckUserInput(key); + filterMenu->Update(dt); + } + else + { + mStage = STAGE_WAITING; + updateFilters(); + loadIndexes(); + } + } + } } +void GameStateDeckViewer::renderOnScreenBasicInfo() +{ + JRenderer *renderer = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + char buffer[256]; + int myD = (displayed_deck == myDeck); -void GameStateDeckViewer::renderOnScreenBasicInfo(){ - JRenderer *renderer = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - char buffer[256]; - int myD = (displayed_deck == myDeck); + float y = 0; + int allCopies, nowCopies; + nowCopies = displayed_deck->getCount(WSrcDeck::FILTERED_COPIES); + allCopies = displayed_deck->getCount(WSrcDeck::UNFILTERED_COPIES); + WCardFilter * wc = displayed_deck->getFiltersRoot(); - float y = 0; - int allCopies, nowCopies; - nowCopies = displayed_deck->getCount(WSrcDeck::FILTERED_COPIES); - allCopies = displayed_deck->getCount(WSrcDeck::UNFILTERED_COPIES); - WCardFilter * wc = displayed_deck->getFiltersRoot(); + if (wc) + sprintf(buffer, "%s %i of %i cards (%i unique)", (displayed_deck == myDeck) ? "DECK: " : " ", + nowCopies, allCopies, displayed_deck->getCount(WSrcDeck::FILTERED_UNIQUE)); + else + sprintf(buffer, "%s%i cards (%i unique)", (displayed_deck == myDeck) ? "DECK: " : " ", + allCopies, displayed_deck->getCount(WSrcDeck::UNFILTERED_UNIQUE)); - if(wc) - sprintf(buffer, "%s %i of %i cards (%i unique)", (displayed_deck == myDeck) ? "DECK: " : " ", nowCopies,allCopies, displayed_deck->getCount(WSrcDeck::FILTERED_UNIQUE)); - else - sprintf(buffer, "%s%i cards (%i unique)", (displayed_deck == myDeck) ? "DECK: " : " " , allCopies, displayed_deck->getCount(WSrcDeck::UNFILTERED_UNIQUE)); - float w = mFont->GetStringWidth(buffer); - renderer->FillRoundRect(SCREEN_WIDTH-(w+27),y+5,w+10,15,5,ARGB(128,0,0,0)); - - mFont->DrawString(buffer, SCREEN_WIDTH-22, y+15, JGETEXT_RIGHT); - if (useFilter != 0) - renderer->RenderQuad(mIcons[useFilter-1], SCREEN_WIDTH-10 , y + 15, 0.0f,0.5,0.5); + float w = mFont->GetStringWidth(buffer); + renderer->FillRoundRect(SCREEN_WIDTH - (w + 27), y + 5, w + 10, 15, 5, ARGB(128,0,0,0)); + + mFont->DrawString(buffer, SCREEN_WIDTH - 22, y + 15, JGETEXT_RIGHT); + if (useFilter != 0) + renderer->RenderQuad(mIcons[useFilter - 1], SCREEN_WIDTH - 10, y + 15, 0.0f, 0.5, 0.5); } //returns position of the current card (cusor) in the currently viewed color/filter -int GameStateDeckViewer::getCurrentPos() { - int total = displayed_deck->Size(); - - int currentPos = displayed_deck->getOffset(); - currentPos+= 2; //we start by displaying card number 3 - currentPos = currentPos % total + 1; - if (currentPos <0) currentPos = (total + currentPos); - if (!currentPos) currentPos = total; - return currentPos; +int GameStateDeckViewer::getCurrentPos() +{ + int total = displayed_deck->Size(); + + int currentPos = displayed_deck->getOffset(); + currentPos += 2; //we start by displaying card number 3 + currentPos = currentPos % total + 1; + if (currentPos < 0) + currentPos = (total + currentPos); + if (!currentPos) + currentPos = total; + return currentPos; } -void GameStateDeckViewer::renderSlideBar(){ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); +void GameStateDeckViewer::renderSlideBar() +{ + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - int total = displayed_deck->Size(); - if(total == 0) - return; + int total = displayed_deck->Size(); + if (total == 0) + return; - float filler = 15; - float y = SCREEN_HEIGHT_F-25; - float bar_size = SCREEN_WIDTH_F - 2*filler; - JRenderer * r = JRenderer::GetInstance(); - int currentPos = getCurrentPos(); + float filler = 15; + float y = SCREEN_HEIGHT_F - 25; + float bar_size = SCREEN_WIDTH_F - 2 * filler; + JRenderer * r = JRenderer::GetInstance(); + int currentPos = getCurrentPos(); - float cursor_pos = bar_size * currentPos / total; + float cursor_pos = bar_size * currentPos / total; - r->FillRoundRect(filler + 5,y+5,bar_size,0,3,ARGB(hudAlpha/2,0,0,0)); - r->DrawLine(filler+cursor_pos + 5 ,y+5,filler+cursor_pos + 5,y+10,ARGB(hudAlpha/2,0,0,0)); + r->FillRoundRect(filler + 5, y + 5, bar_size, 0, 3, ARGB(hudAlpha/2,0,0,0)); + r->DrawLine(filler + cursor_pos + 5, y + 5, filler + cursor_pos + 5, y + 10, ARGB(hudAlpha/2,0,0,0)); - r->FillRoundRect(filler,y,bar_size,0,3,ARGB(hudAlpha/2,128,128,128)); - r->DrawLine(filler+cursor_pos,y,filler+cursor_pos,y+5,ARGB(hudAlpha,255,255,255)); - char buffer[256]; - string deckname = _("Collection"); - if (displayed_deck == myDeck){ - deckname = _("Deck"); - } - sprintf(buffer,"%s - %i/%i", deckname.c_str(),currentPos, total); - mFont->SetColor(ARGB(hudAlpha,255,255,255)); - mFont->DrawString(buffer, SCREEN_WIDTH/2, y, JGETEXT_CENTER); - - - mFont->SetColor(ARGB(255,255,255,255)); -} - -void GameStateDeckViewer::renderDeckBackground(){ - int max1 = 0; - int maxC1 = 4; - int max2 = 0; - int maxC2 = 4; - - for (int i= 0; i < Constants::MTG_NB_COLORS -1; i++){ - int value = myDeck->getCount(i); - if (value > max1){ - max2 = max1; - maxC2 = maxC1; - max1 = value; - maxC1 = i; - }else if (value > max2){ - max2 = value; - maxC2 = i; + r->FillRoundRect(filler, y, bar_size, 0, 3, ARGB(hudAlpha/2,128,128,128)); + r->DrawLine(filler + cursor_pos, y, filler + cursor_pos, y + 5, ARGB(hudAlpha,255,255,255)); + char buffer[256]; + string deckname = _("Collection"); + if (displayed_deck == myDeck) + { + deckname = _("Deck"); } - } - if (max2 < max1/2){ - maxC2 = maxC1; - } + sprintf(buffer, "%s - %i/%i", deckname.c_str(), currentPos, total); + mFont->SetColor(ARGB(hudAlpha,255,255,255)); + mFont->DrawString(buffer, SCREEN_WIDTH / 2, y, JGETEXT_CENTER); - PIXEL_TYPE colors[] = - { - ARGB(255, Constants::_r[maxC1], Constants::_g[maxC1], Constants::_b[maxC1]), - ARGB(255, Constants::_r[maxC1], Constants::_g[maxC1], Constants::_b[maxC1]), - ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), - ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), - }; + mFont->SetColor(ARGB(255,255,255,255)); +} - JRenderer::GetInstance()->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,colors); +void GameStateDeckViewer::renderDeckBackground() +{ + int max1 = 0; + int maxC1 = 4; + int max2 = 0; + int maxC2 = 4; + + for (int i = 0; i < Constants::MTG_NB_COLORS - 1; i++) + { + int value = myDeck->getCount(i); + if (value > max1) + { + max2 = max1; + maxC2 = maxC1; + max1 = value; + maxC1 = i; + } + else if (value > max2) + { + max2 = value; + maxC2 = i; + } + } + if (max2 < max1 / 2) + { + maxC2 = maxC1; + } + PIXEL_TYPE colors[] = { ARGB(255, Constants::_r[maxC1], Constants::_g[maxC1], Constants::_b[maxC1]), + ARGB(255, Constants::_r[maxC1], Constants::_g[maxC1], Constants::_b[maxC1]), + ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), + ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), }; + + JRenderer::GetInstance()->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, colors); } -void GameStateDeckViewer::renderOnScreenMenu(){ +void GameStateDeckViewer::renderOnScreenMenu() +{ - WFont * font = resources.GetWFont(Fonts::MAIN_FONT); - font->SetColor(ARGB(255,255,255,255)); - JRenderer * r = JRenderer::GetInstance(); - float pspIconsSize = 0.5; - float fH = font->GetHeight() + 1; + WFont * font = resources.GetWFont(Fonts::MAIN_FONT); + font->SetColor(ARGB(255,255,255,255)); + JRenderer * r = JRenderer::GetInstance(); + float pspIconsSize = 0.5; + float fH = font->GetHeight() + 1; - float leftTransition = onScreenTransition*84; - float rightTransition = onScreenTransition*204; - float leftPspX = 40 - leftTransition; - float leftPspY = SCREEN_HEIGHT/2 - 20 ; - float rightPspX = SCREEN_WIDTH-100 + rightTransition; - float rightPspY = SCREEN_HEIGHT/2 - 20 ; + float leftTransition = onScreenTransition * 84; + float rightTransition = onScreenTransition * 204; + float leftPspX = 40 - leftTransition; + float leftPspY = SCREEN_HEIGHT / 2 - 20; + float rightPspX = SCREEN_WIDTH - 100 + rightTransition; + float rightPspY = SCREEN_HEIGHT / 2 - 20; + if (stw->currentPage == 0) + { + //FillRects + r->FillRect(0 - (onScreenTransition * 84), 0, 84, SCREEN_HEIGHT, ARGB(128,0,0,0)); + r->FillRect(SCREEN_WIDTH - 204 + (onScreenTransition * 204), 0, 200, SCREEN_HEIGHT, ARGB(128,0,0,0)); - if (stw->currentPage == 0) { - //FillRects - r->FillRect(0-(onScreenTransition*84),0,84,SCREEN_HEIGHT,ARGB(128,0,0,0)); - r->FillRect(SCREEN_WIDTH-204+(onScreenTransition*204),0,200,SCREEN_HEIGHT,ARGB(128,0,0,0)); + //LEFT PSP CIRCLE render + r->FillCircle(leftPspX, leftPspY, 40, ARGB(128,50,50,50)); + r->RenderQuad(pspIcons[0], leftPspX, leftPspY - 20, 0, pspIconsSize, pspIconsSize); + r->RenderQuad(pspIcons[1], leftPspX, leftPspY + 20, 0, pspIconsSize, pspIconsSize); + r->RenderQuad(pspIcons[2], leftPspX - 20, leftPspY, 0, pspIconsSize, pspIconsSize); + r->RenderQuad(pspIcons[3], leftPspX + 20, leftPspY, 0, pspIconsSize, pspIconsSize); - //LEFT PSP CIRCLE render - r->FillCircle(leftPspX,leftPspY,40,ARGB(128,50,50,50)); + font->DrawString(_("Prev."), leftPspX - 35, leftPspY - 15); + font->DrawString(_("Next"), leftPspX + 15, leftPspY - 15); + font->DrawString(_("card"), leftPspX - 35, leftPspY); + font->DrawString(_("card"), leftPspX + 15, leftPspY); + font->DrawString(_("Next edition"), leftPspX - 33, leftPspY - 35); + font->DrawString(_("Prev. edition"), leftPspX - 33, leftPspY + 25); - r->RenderQuad(pspIcons[0],leftPspX, leftPspY - 20,0,pspIconsSize,pspIconsSize); - r->RenderQuad(pspIcons[1],leftPspX, leftPspY + 20,0,pspIconsSize,pspIconsSize); - r->RenderQuad(pspIcons[2],leftPspX - 20, leftPspY,0,pspIconsSize,pspIconsSize); - r->RenderQuad(pspIcons[3],leftPspX + 20, leftPspY,0,pspIconsSize,pspIconsSize); + //RIGHT PSP CIRCLE render + r->FillCircle(rightPspX + (onScreenTransition * 204), rightPspY, 40, ARGB(128,50,50,50)); + r->RenderQuad(pspIcons[4], rightPspX + 20, rightPspY, 0, pspIconsSize, pspIconsSize); + r->RenderQuad(pspIcons[5], rightPspX, rightPspY - 20, 0, pspIconsSize, pspIconsSize); + r->RenderQuad(pspIcons[6], rightPspX - 20, rightPspY, 0, pspIconsSize, pspIconsSize); + r->RenderQuad(pspIcons[7], rightPspX, rightPspY + 20, 0, pspIconsSize, pspIconsSize); - font->DrawString(_("Prev."), leftPspX - 35, leftPspY-15); - font->DrawString(_("Next"), leftPspX + 15, leftPspY-15); - font->DrawString(_("card"), leftPspX - 35, leftPspY); - font->DrawString(_("card"), leftPspX + 15, leftPspY); - font->DrawString(_("Next edition"), leftPspX - 33, leftPspY - 35); - font->DrawString(_("Prev. edition"), leftPspX -33 , leftPspY +25); + font->DrawString(_("Toggle Images"), rightPspX - 35, rightPspY - 40); - //RIGHT PSP CIRCLE render - r->FillCircle(rightPspX+(onScreenTransition*204),rightPspY,40,ARGB(128,50,50,50)); - r->RenderQuad(pspIcons[4],rightPspX+20, rightPspY,0,pspIconsSize,pspIconsSize); - r->RenderQuad(pspIcons[5],rightPspX, rightPspY - 20,0,pspIconsSize,pspIconsSize); - r->RenderQuad(pspIcons[6],rightPspX-20, rightPspY,0,pspIconsSize,pspIconsSize); - r->RenderQuad(pspIcons[7],rightPspX, rightPspY + 20,0,pspIconsSize,pspIconsSize); - - font->DrawString(_("Toggle Images"), rightPspX - 35, rightPspY - 40); - - if (displayed_deck == myCollection){ - font->DrawString(_("Add card"), rightPspX + 20, rightPspY-15); - font->DrawString(_("View Deck"), rightPspX - 20 , rightPspY-15, JGETEXT_RIGHT); - }else{ - font->DrawString(_("Remove card"), rightPspX + 20, rightPspY-15); - font->DrawString(_("View Collection"), rightPspX - 20 , rightPspY-15, JGETEXT_RIGHT); - } - font->DrawString(_("Sell card"), rightPspX - 30 , rightPspY+20); - //Bottom menus - font->DrawString(_("menu"), SCREEN_WIDTH-35 +rightTransition, SCREEN_HEIGHT-15); - font->DrawString(_("filter"), SCREEN_WIDTH-95 +rightTransition, SCREEN_HEIGHT-15); - - - - //Your Deck Information - char buffer[300]; - int nb_letters = 0; - for (int j=0; jgetCount(j); - if (value > 0){ - sprintf(buffer, "%i", value); - font->DrawString(buffer, SCREEN_WIDTH-190+rightTransition + nb_letters*13, SCREEN_HEIGHT/2 + 40); - r->RenderQuad(mIcons[j],SCREEN_WIDTH-197+rightTransition + nb_letters*13 , SCREEN_HEIGHT/2 + 46,0,0.5,0.5); - if (value > 9){nb_letters += 3;}else{nb_letters+=2;} - } - } - int value = myDeck->getCount(WSrcDeck::UNFILTERED_COPIES); - sprintf(buffer, _("Your Deck: %i cards").c_str(), value); - font->DrawString(buffer, SCREEN_WIDTH-200+rightTransition, SCREEN_HEIGHT/2 + 25); - - if (displayed_deck == myCollection){ - font->DrawString(_("in: collection"), 5-leftTransition, 5); - font->DrawString(_("Use SQUARE to view your deck,"), SCREEN_WIDTH-200+rightTransition, 5); - }else{ - font->DrawString(_("in: deck"), 5-leftTransition, 5); - font->DrawString(_("Use SQUARE to view collection,"), SCREEN_WIDTH-200+rightTransition, 5); - } - font->DrawString(_("Press L/R to cycle through"), SCREEN_WIDTH-200+rightTransition, 5+fH); - font->DrawString(_("deck statistics."), SCREEN_WIDTH-200+rightTransition, 5+fH*2); - - } else { - if (stw->needUpdate) { - updateStats(); - } - - char buffer[300]; - - leftTransition = -(onScreenTransition/2)*SCREEN_WIDTH; - rightTransition = -leftTransition; - - r->FillRect(0+leftTransition,0,SCREEN_WIDTH/2,SCREEN_HEIGHT,ARGB(128,0,0,0)); - r->FillRect(SCREEN_WIDTH/2+rightTransition,0,SCREEN_WIDTH/2,SCREEN_HEIGHT,ARGB(128,0,0,0)); - r->FillRect(10+leftTransition,10,SCREEN_WIDTH/2-10,SCREEN_HEIGHT-20,ARGB(128,0,0,0)); - r->FillRect(SCREEN_WIDTH/2+rightTransition,10,SCREEN_WIDTH/2-10,SCREEN_HEIGHT-20,ARGB(128,0,0,0)); - font->DrawString(_("menu"), SCREEN_WIDTH-35 +rightTransition, SCREEN_HEIGHT-15); - font->DrawString(_("filter"), SCREEN_WIDTH-95 +rightTransition, SCREEN_HEIGHT-15); - - int nb_letters = 0; - float posX, posY; - DWORD graphColor; - - graphColor = ARGB(200, 155, 155, 155); - string STATS_TITLE_FORMAT = _("%i: %s"); - - switch (stw->currentPage) { - case 1: // Counts, price - // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Statistics Summary").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - - posY = 30; - posX = 180; - sprintf(buffer, _("Your Deck: %i cards").c_str(), stw->cardCount); - font->DrawString(buffer, 20 + leftTransition, posY); - posY += 10; - - // Counts by color - for (int j=0; jgetCount(j); - if (value > 0){ - sprintf(buffer, "%i", value); - font->DrawString(buffer, 38 + nb_letters*13 + leftTransition, posY + 5); - r->RenderQuad(mIcons[j], 30 + nb_letters*13 + leftTransition, posY + 11,0,0.5,0.5); - if (value > 9){nb_letters += 3;}else{nb_letters+=2;} - } - } - posY += 25; - - r->DrawLine(posX - 4 + leftTransition, posY - 1, posX - 4 + leftTransition, posY + 177, ARGB(128, 255, 255, 255)); - r->DrawLine(19 + leftTransition, posY - 1, 19 + leftTransition, posY + 177, ARGB(128, 255, 255, 255)); - r->DrawLine(posX + 40 + leftTransition, posY - 1, posX + 40 + leftTransition, posY + 177, ARGB(128, 255, 255, 255)); - - r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - - font->DrawString(_("Lands"), 20 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countLands); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 14; - r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - font->DrawString( _("Creatures"), 20 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countCreatures); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 14; - r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - font->DrawString(_("Spells"), 20 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countSpells); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 10; - font->DrawString(_("Instants"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countInstants); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 10; - font->DrawString(_("Enchantments"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countEnchantments); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 10; - font->DrawString(_("Sorceries"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countSorceries); - font->DrawString(buffer, posX + leftTransition, posY); - //sprintf(buffer, "Artifacts: %i", stw->countArtifacts); - //mFont->DrawString(buffer, 20, 123); - - posY += 14; - r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - - font->DrawString(_("Average converted mana cost"), 20 + leftTransition, posY); - sprintf(buffer, _("%2.2f").c_str(), stw->avgManaCost); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 14; - r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - font->DrawString(_("Probabilities"), 20 + leftTransition, posY); - - posY += 10; - font->DrawString(_("No land in 1st hand"), 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[0]); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 10; - font->DrawString(_("No land in 9 cards"), 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[2]); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 10; - font->DrawString(_("No creatures in 1st hand"), 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noCreaturesProbInTurn[0]); - font->DrawString(buffer, posX + leftTransition, posY); - - // Playgame Statistics - posY += 14; - r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - font->DrawString(_("Playgame statistics"), 20 + leftTransition, posY); - - posY += 10; - font->DrawString(_("Games played"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->gamesPlayed); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 10; - font->DrawString(_("Victory ratio"), 30 + leftTransition, posY); - sprintf(buffer, _("%i%%").c_str(), stw->percentVictories); - font->DrawString(buffer, posX + leftTransition, posY); - - posY += 15; - r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - font->DrawString(_("Total price (credits)"), 20 + leftTransition, posY); - sprintf(buffer, _("%i ").c_str(), stw->totalPrice); - font->DrawString(buffer, posX + leftTransition, posY); - r->DrawLine(20 + leftTransition, posY + 13, posX + 40 + leftTransition, posY + 13, ARGB(128, 255, 255, 255)); - - break; - - case 5: // Land statistics - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana production").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - - font->DrawString(_("Counts of manasources per type and color:"), 20 + leftTransition, 30); - - posY = 70; - - // Column titles - for (int j=0; jRenderQuad(mIcons[j], 52 + j*15 + leftTransition, posY - 10,0,0.5,0.5); + if (displayed_deck == myCollection) + { + font->DrawString(_("Add card"), rightPspX + 20, rightPspY - 15); + font->DrawString(_("View Deck"), rightPspX - 20, rightPspY - 15, JGETEXT_RIGHT); } - - //font->DrawString(_("C"), 30 + leftTransition, posY-16); - //font->DrawString(_("Ty"), 27 + leftTransition, posY-16); - - // Horizontal table lines - r->DrawLine(27 + leftTransition, posY - 20, 60 + (Constants::MTG_NB_COLORS-2)*15 + leftTransition, posY - 20, ARGB(128, 255, 255, 255)); - r->DrawLine(27 + leftTransition, posY - 1, 60 + (Constants::MTG_NB_COLORS-2)*15 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - r->DrawLine(27 + leftTransition, 2*10 + posY + 12, 60 + (Constants::MTG_NB_COLORS-2)*15 + leftTransition, 2*10 + posY + 12, ARGB(128, 255, 255, 255)); - r->DrawLine(27 + leftTransition, 3*10 + posY + 14, 60 + (Constants::MTG_NB_COLORS-2)*15 + leftTransition, 3*10 + posY + 14, ARGB(128, 255, 255, 255)); - - // Vertical table lines - r->DrawLine(26 + leftTransition, posY - 20, 26 + leftTransition, 3*10 + posY + 14, ARGB(128, 255, 255, 255)); - r->DrawLine(43 + leftTransition, posY - 20, 43 + leftTransition, 3*10 + posY + 14, ARGB(128, 255, 255, 255)); - r->DrawLine(60 + leftTransition + (Constants::MTG_NB_COLORS-2)*15, posY - 20, 60 + leftTransition + (Constants::MTG_NB_COLORS-2)*15, 3*10 + posY + 14, ARGB(128, 255, 255, 255)); - - font->DrawString(_("BL"), 27 + leftTransition, posY); - font->DrawString(_("NB"), 27 + leftTransition, posY+10); - font->DrawString(_("O"), 30 + leftTransition, posY+20); - font->DrawString(_("T"), 30 + leftTransition, posY+33); - - int curCount; - - for (int j=0; jcountBasicLandsPerColor[j]; - sprintf(buffer, (curCount==0?".":"%i"), curCount); - font->DrawString(buffer, 49 + leftTransition + j*15, posY); - - curCount = stw->countLandsPerColor[j]; - sprintf(buffer, (curCount==0?".":"%i"), curCount); - font->DrawString(buffer, 49 + leftTransition + j*15, posY+10); - - curCount = stw->countNonLandProducersPerColor[j]; - sprintf(buffer, (curCount==0?".":"%i"), curCount); - font->DrawString(buffer, 49 + leftTransition + j*15, posY+20); - - curCount = stw->countLandsPerColor[j] + stw->countBasicLandsPerColor[j] + stw->countNonLandProducersPerColor[j]; - sprintf(buffer, (curCount==0?".":"%i"), curCount); - font->DrawString(buffer, 49 + leftTransition + j*15, posY+33); + else + { + font->DrawString(_("Remove card"), rightPspX + 20, rightPspY - 15); + font->DrawString(_("View Collection"), rightPspX - 20, rightPspY - 15, JGETEXT_RIGHT); } + font->DrawString(_("Sell card"), rightPspX - 30, rightPspY + 20); + //Bottom menus + font->DrawString(_("menu"), SCREEN_WIDTH - 35 + rightTransition, SCREEN_HEIGHT - 15); + font->DrawString(_("filter"), SCREEN_WIDTH - 95 + rightTransition, SCREEN_HEIGHT - 15); - posY += 55; - font->DrawString(_("BL - Basic lands"), 20 + leftTransition, posY); - posY += 10; - font->DrawString(_("NB - Non-basic lands"), 20 + leftTransition, posY); - posY += 10; - font->DrawString(_("O - Other (non-land) manasources"), 26 + leftTransition, posY); - posY += 10; - font->DrawString(_("T - Totals"), 26 + leftTransition, posY); - - break; - - case 6: // Land statistics - in symbols - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana production - in mana symbols").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - font->DrawString(_("Total colored manasymbols in lands' production:"), 20 + leftTransition, 30); - - int totalProducedSymbols; - totalProducedSymbols = 0; - for (int i=1; icountLandsPerColor[i] + stw->countBasicLandsPerColor[i]; //!! Move to updatestats! - } - - posY = 50; - for (int i=1; icountLandsPerColor[i] + stw->countBasicLandsPerColor[i]>0) { - sprintf(buffer, _("%i").c_str(), stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i]); - font->DrawString(buffer, 20 + leftTransition, posY); - sprintf(buffer, _("(%i%%)").c_str(), (int)(100*(float)(stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i])/totalProducedSymbols)); - font->DrawString(buffer, 33 + leftTransition, posY); - posX = 72; - for (int j=0; jcountLandsPerColor[i] + stw->countBasicLandsPerColor[i]; j++) { - r->RenderQuad(mIcons[i], posX + leftTransition, posY+6, 0, 0.5, 0.5); - posX += ((j+1)%10==0)?17:13; - if ((((j+1)%30)==0) && (jcountLandsPerColor[i] + stw->countBasicLandsPerColor[i]-1)) { - posX = 72; - posY += 15; - } + //Your Deck Information + char buffer[300]; + int nb_letters = 0; + for (int j = 0; j < Constants::MTG_NB_COLORS; j++) + { + int value = myDeck->getCount(j); + if (value > 0) + { + sprintf(buffer, "%i", value); + font->DrawString(buffer, SCREEN_WIDTH - 190 + rightTransition + nb_letters * 13, SCREEN_HEIGHT / 2 + 40); + r->RenderQuad(mIcons[j], SCREEN_WIDTH - 197 + rightTransition + nb_letters * 13, SCREEN_HEIGHT / 2 + 46, 0, 0.5, + 0.5); + if (value > 9) + { + nb_letters += 3; + } + else + { + nb_letters += 2; + } } - posY += 17; - } + } + int value = myDeck->getCount(WSrcDeck::UNFILTERED_COPIES); + sprintf(buffer, _("Your Deck: %i cards").c_str(), value); + font->DrawString(buffer, SCREEN_WIDTH - 200 + rightTransition, SCREEN_HEIGHT / 2 + 25); + + if (displayed_deck == myCollection) + { + font->DrawString(_("in: collection"), 5 - leftTransition, 5); + font->DrawString(_("Use SQUARE to view your deck,"), SCREEN_WIDTH - 200 + rightTransition, 5); + } + else + { + font->DrawString(_("in: deck"), 5 - leftTransition, 5); + font->DrawString(_("Use SQUARE to view collection,"), SCREEN_WIDTH - 200 + rightTransition, 5); + } + font->DrawString(_("Press L/R to cycle through"), SCREEN_WIDTH - 200 + rightTransition, 5 + fH); + font->DrawString(_("deck statistics."), SCREEN_WIDTH - 200 + rightTransition, 5 + fH * 2); + + } + else + { + if (stw->needUpdate) + { + updateStats(); } - break; + char buffer[300]; - case 2: // Mana cost detail - case 3: - case 4: - int (*countPerCost)[Constants::STATS_MAX_MANA_COST+1]; - int (*countPerCostAndColor)[Constants::STATS_MAX_MANA_COST+1][Constants::MTG_NB_COLORS+1]; - float avgCost; + leftTransition = -(onScreenTransition / 2) * SCREEN_WIDTH; + rightTransition = -leftTransition; - switch (stw->currentPage) { // Nested switch on the same variable. Oh yes. - case 2: // Total counts - // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - font->DrawString(_("Card counts per mana cost:"), 20 + leftTransition, 30); - avgCost = stw->avgManaCost; - countPerCost = &stw->countCardsPerCost; - countPerCostAndColor = &stw->countCardsPerCostAndColor; - break; - case 3: // Creature counts - // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail - Creatures").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - font->DrawString(_("Creature counts per mana cost:"), 20 + leftTransition, 30); - avgCost = stw->avgCreatureCost; - countPerCost = &stw->countCreaturesPerCost; - countPerCostAndColor = &stw->countCreaturesPerCostAndColor; - break; - case 4: // Spell counts - // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail - Spells").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - font->DrawString(_("Non-creature spell counts per mana cost:"), 20 + leftTransition, 30); - avgCost = stw->avgSpellCost; - countPerCost = &stw->countSpellsPerCost; - countPerCostAndColor = &stw->countSpellsPerCostAndColor; - break; - default: - countPerCost = NULL; - countPerCostAndColor = NULL; - avgCost = 0; - break; - } + r->FillRect(0 + leftTransition, 0, SCREEN_WIDTH / 2, SCREEN_HEIGHT, ARGB(128,0,0,0)); + r->FillRect(SCREEN_WIDTH / 2 + rightTransition, 0, SCREEN_WIDTH / 2, SCREEN_HEIGHT, ARGB(128,0,0,0)); + r->FillRect(10 + leftTransition, 10, SCREEN_WIDTH / 2 - 10, SCREEN_HEIGHT - 20, ARGB(128,0,0,0)); + r->FillRect(SCREEN_WIDTH / 2 + rightTransition, 10, SCREEN_WIDTH / 2 - 10, SCREEN_HEIGHT - 20, ARGB(128,0,0,0)); + font->DrawString(_("menu"), SCREEN_WIDTH - 35 + rightTransition, SCREEN_HEIGHT - 15); + font->DrawString(_("filter"), SCREEN_WIDTH - 95 + rightTransition, SCREEN_HEIGHT - 15); - posY = 70; + int nb_letters = 0; + float posX, posY; + DWORD graphColor; - // Column titles - for (int j=0; jRenderQuad(mIcons[j], 67 + j*15 + leftTransition, posY - 10,0,0.5,0.5); - } + graphColor = ARGB(200, 155, 155, 155); + string STATS_TITLE_FORMAT = _("%i: %s"); - font->DrawString(_("C"), 30 + leftTransition, posY-16); - font->DrawString(_("#"), 45 + leftTransition, posY-16); + switch (stw->currentPage) + { + case 1: // Counts, price + // Title + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Statistics Summary").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); - // Horizontal table lines - r->DrawLine(27 + leftTransition, posY - 20, 75 + (Constants::MTG_NB_COLORS-2)*15 + leftTransition, posY - 20, ARGB(128, 255, 255, 255)); - r->DrawLine(27 + leftTransition, posY - 1, 75 + (Constants::MTG_NB_COLORS-2)*15 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - r->DrawLine(27 + leftTransition, Constants::STATS_MAX_MANA_COST*10 + posY + 12, 75 + (Constants::MTG_NB_COLORS-2)*15 + leftTransition, Constants::STATS_MAX_MANA_COST*10 + posY + 12, ARGB(128, 255, 255, 255)); - - // Vertical table lines - r->DrawLine(26 + leftTransition, posY - 20, 26 + leftTransition, Constants::STATS_MAX_MANA_COST*10 + posY + 12, ARGB(128, 255, 255, 255)); - r->DrawLine(41 + leftTransition, posY - 20, 41 + leftTransition, Constants::STATS_MAX_MANA_COST*10 + posY + 12, ARGB(128, 255, 255, 255)); - r->DrawLine(58 + leftTransition, posY - 20, 58 + leftTransition, Constants::STATS_MAX_MANA_COST*10 + posY + 12, ARGB(128, 255, 255, 255)); - r->DrawLine(75 + leftTransition + (Constants::MTG_NB_COLORS-2)*15, posY - 20, 75 + leftTransition + (Constants::MTG_NB_COLORS-2)*15, Constants::STATS_MAX_MANA_COST*10 + posY + 12, ARGB(128, 255, 255, 255)); - - for (int i=0; i<=Constants::STATS_MAX_MANA_COST; i++) { - sprintf(buffer, _("%i").c_str(), i); - font->DrawString(buffer, 30 + leftTransition, posY); - sprintf(buffer, ((*countPerCost)[i]>0)?_("%i").c_str():".", (*countPerCost)[i]); - font->DrawString(buffer, 45 + leftTransition, posY); - for (int j=0; j0)?_("%i").c_str():".", (*countPerCostAndColor)[i][j]); - font->DrawString(buffer, 64 + leftTransition + j*15, posY); - } - r->FillRect(77.f + leftTransition + (Constants::MTG_NB_COLORS-2)*15.0f, posY + 2.0f, (*countPerCost)[i]*5.0f, 8.0f, graphColor); - posY += 10; - } - - posY += 10; - sprintf(buffer, _("Average converted mana cost: %2.2f").c_str(), avgCost); - font->DrawString(buffer, 20 + leftTransition, posY); - posY += 15; - sprintf(buffer, _("C - Converted mana cost. Cards with cost>%i are included in the last row.").c_str(), Constants::STATS_MAX_MANA_COST); - font->DrawString(buffer, 20 + leftTransition, posY); - posY += 10; - font->DrawString(_("# - Total number of cards with given cost"), 20 + leftTransition, posY); - - break; - - case 8: - // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Probabilities").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - - // No lands detail - float graphScale, graphWidth; - graphWidth = 100; - graphScale = (stw->noLandsProbInTurn[0]==0) ? 0:(graphWidth/stw->noLandsProbInTurn[0]); - font->DrawString( _("No lands in first n cards:"), 20 + leftTransition, 30); - - posY = 50; - for (int i=0; iDrawString(buffer, 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[i]); - font->DrawString(buffer, 45 + leftTransition, posY); - r->FillRect(84 + leftTransition, posY + 2, graphScale*stw->noLandsProbInTurn[i], 8, graphColor); - posY += 10; - } - - // No creatures probability detail - posY += 10; - font->DrawString( _("No creatures in first n cards:"), 20 + leftTransition, posY); - posY += 20; - graphScale = (stw->noCreaturesProbInTurn[0]==0) ? 0:(graphWidth/stw->noCreaturesProbInTurn[0]); - - for (int i=0; iDrawString(buffer, 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noCreaturesProbInTurn[i]); - font->DrawString(buffer, 45 + leftTransition, posY); - r->FillRect(84 + leftTransition, posY + 2, graphScale*stw->noCreaturesProbInTurn[i], 8, graphColor); - posY += 10; - } - - break; - - case 7: // Total mana cost per color - // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost per color").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); - - font->DrawString(_("Total colored manasymbols in cards' casting costs:"), 20 + leftTransition, 30); - - posY = 50; - for (int i=1; itotalCostPerColor[i]>0) { - sprintf(buffer, _("%i").c_str(), stw->totalCostPerColor[i]); + posY = 30; + posX = 180; + sprintf(buffer, _("Your Deck: %i cards").c_str(), stw->cardCount); font->DrawString(buffer, 20 + leftTransition, posY); - sprintf(buffer, _("(%i%%)").c_str(), (int)(100*(float)stw->totalCostPerColor[i]/stw->totalColoredSymbols)); - font->DrawString(buffer, 33 + leftTransition, posY); - posX = 72; - for (int j=0; jtotalCostPerColor[i]; j++) { - r->RenderQuad(mIcons[i], posX + leftTransition, posY+6, 0, 0.5, 0.5); - posX += ((j+1)%10==0)?17:13; - if ((((j+1)%30)==0) && (jtotalCostPerColor[i]-1)) { - posX = 72; - posY += 15; - } + posY += 10; + + // Counts by color + for (int j = 0; j < Constants::MTG_NB_COLORS; j++) + { + int value = myDeck->getCount(j); + if (value > 0) + { + sprintf(buffer, "%i", value); + font->DrawString(buffer, 38 + nb_letters * 13 + leftTransition, posY + 5); + r->RenderQuad(mIcons[j], 30 + nb_letters * 13 + leftTransition, posY + 11, 0, 0.5, 0.5); + if (value > 9) + { + nb_letters += 3; + } + else + { + nb_letters += 2; + } + } } - posY += 17; - } - } - break; + posY += 25; - case 9: // Victory statistics - // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Victory statistics").c_str()); - font->DrawString(buffer, 10+leftTransition, 10); + r->DrawLine(posX - 4 + leftTransition, posY - 1, posX - 4 + leftTransition, posY + 177, ARGB(128, 255, 255, 255)); + r->DrawLine(19 + leftTransition, posY - 1, 19 + leftTransition, posY + 177, ARGB(128, 255, 255, 255)); + r->DrawLine(posX + 40 + leftTransition, posY - 1, posX + 40 + leftTransition, posY + 177, ARGB(128, 255, 255, 255)); - font->DrawString(_("Victories against AI:"), 20 + leftTransition, 30); + r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); - sprintf(buffer, _("Games played: %i").c_str(), stw->gamesPlayed); - font->DrawString(buffer, 20 + leftTransition, 45); - sprintf(buffer, _("Victory ratio: %i%%").c_str(), stw->percentVictories); - font->DrawString(buffer, 20 + leftTransition, 55); + font->DrawString(_("Lands"), 20 + leftTransition, posY); + sprintf(buffer, _("%i").c_str(), stw->countLands); + font->DrawString(buffer, posX + leftTransition, posY); - int AIsPerColumn = 19; - posY = 70; - posX = 20; + posY += 14; + r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); + font->DrawString(_("Creatures"), 20 + leftTransition, posY); + sprintf(buffer, _("%i").c_str(), stw->countCreatures); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 14; + r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); + font->DrawString(_("Spells"), 20 + leftTransition, posY); + sprintf(buffer, _("%i").c_str(), stw->countSpells); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 10; + font->DrawString(_("Instants"), 30 + leftTransition, posY); + sprintf(buffer, _("%i").c_str(), stw->countInstants); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 10; + font->DrawString(_("Enchantments"), 30 + leftTransition, posY); + sprintf(buffer, _("%i").c_str(), stw->countEnchantments); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 10; + font->DrawString(_("Sorceries"), 30 + leftTransition, posY); + sprintf(buffer, _("%i").c_str(), stw->countSorceries); + font->DrawString(buffer, posX + leftTransition, posY); + //sprintf(buffer, "Artifacts: %i", stw->countArtifacts); + //mFont->DrawString(buffer, 20, 123); + + posY += 14; + r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); + + font->DrawString(_("Average converted mana cost"), 20 + leftTransition, posY); + sprintf(buffer, _("%2.2f").c_str(), stw->avgManaCost); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 14; + r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); + font->DrawString(_("Probabilities"), 20 + leftTransition, posY); + + posY += 10; + font->DrawString(_("No land in 1st hand"), 30 + leftTransition, posY); + sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[0]); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 10; + font->DrawString(_("No land in 9 cards"), 30 + leftTransition, posY); + sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[2]); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 10; + font->DrawString(_("No creatures in 1st hand"), 30 + leftTransition, posY); + sprintf(buffer, _("%2.2f%%").c_str(), stw->noCreaturesProbInTurn[0]); + font->DrawString(buffer, posX + leftTransition, posY); + + // Playgame Statistics + posY += 14; + r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); + font->DrawString(_("Playgame statistics"), 20 + leftTransition, posY); + + posY += 10; + font->DrawString(_("Games played"), 30 + leftTransition, posY); + sprintf(buffer, _("%i").c_str(), stw->gamesPlayed); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 10; + font->DrawString(_("Victory ratio"), 30 + leftTransition, posY); + sprintf(buffer, _("%i%%").c_str(), stw->percentVictories); + font->DrawString(buffer, posX + leftTransition, posY); + + posY += 15; + r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); + font->DrawString(_("Total price (credits)"), 20 + leftTransition, posY); + sprintf(buffer, _("%i ").c_str(), stw->totalPrice); + font->DrawString(buffer, posX + leftTransition, posY); + r->DrawLine(20 + leftTransition, posY + 13, posX + 40 + leftTransition, posY + 13, ARGB(128, 255, 255, 255)); + + break; + + case 5: // Land statistics + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana production").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + + font->DrawString(_("Counts of manasources per type and color:"), 20 + leftTransition, 30); - // ToDo: Multiple pages when too many AI decks are present - for (int i=0; i<(int)stw->aiDeckStats.size(); i++) { - sprintf(buffer, _("%.14s").c_str(), stw->aiDeckNames.at(i).c_str()); - font->DrawString(buffer, posX + (i < 2*AIsPerColumn ? leftTransition : rightTransition), posY); - sprintf(buffer, _("%i/%i").c_str(), stw->aiDeckStats.at(i)->victories, stw->aiDeckStats.at(i)->nbgames); - font->DrawString(buffer, posX + (i < AIsPerColumn ? leftTransition : rightTransition) + 80, posY); - sprintf(buffer, _("%i%%").c_str(), stw->aiDeckStats.at(i)->percentVictories()); - font->DrawString(buffer, posX + (i < AIsPerColumn ? leftTransition : rightTransition) + 110, posY); - posY += 10; - if (((i+1)%AIsPerColumn)==0) { posY = 70; - posX += 155; - } + + // Column titles + for (int j = 0; j < Constants::MTG_NB_COLORS - 1; j++) + { + r->RenderQuad(mIcons[j], 52 + j * 15 + leftTransition, posY - 10, 0, 0.5, 0.5); + } + + //font->DrawString(_("C"), 30 + leftTransition, posY-16); + //font->DrawString(_("Ty"), 27 + leftTransition, posY-16); + + // Horizontal table lines + r->DrawLine(27 + leftTransition, posY - 20, 60 + (Constants::MTG_NB_COLORS - 2) * 15 + leftTransition, posY - 20, + ARGB(128, 255, 255, 255)); + r->DrawLine(27 + leftTransition, posY - 1, 60 + (Constants::MTG_NB_COLORS - 2) * 15 + leftTransition, posY - 1, + ARGB(128, 255, 255, 255)); + r->DrawLine(27 + leftTransition, 2 * 10 + posY + 12, 60 + (Constants::MTG_NB_COLORS - 2) * 15 + leftTransition, 2 * 10 + + posY + 12, ARGB(128, 255, 255, 255)); + r->DrawLine(27 + leftTransition, 3 * 10 + posY + 14, 60 + (Constants::MTG_NB_COLORS - 2) * 15 + leftTransition, 3 * 10 + + posY + 14, ARGB(128, 255, 255, 255)); + + // Vertical table lines + r->DrawLine(26 + leftTransition, posY - 20, 26 + leftTransition, 3 * 10 + posY + 14, ARGB(128, 255, 255, 255)); + r->DrawLine(43 + leftTransition, posY - 20, 43 + leftTransition, 3 * 10 + posY + 14, ARGB(128, 255, 255, 255)); + r->DrawLine(60 + leftTransition + (Constants::MTG_NB_COLORS - 2) * 15, posY - 20, 60 + leftTransition + + (Constants::MTG_NB_COLORS - 2) * 15, 3 * 10 + posY + 14, ARGB(128, 255, 255, 255)); + + font->DrawString(_("BL"), 27 + leftTransition, posY); + font->DrawString(_("NB"), 27 + leftTransition, posY + 10); + font->DrawString(_("O"), 30 + leftTransition, posY + 20); + font->DrawString(_("T"), 30 + leftTransition, posY + 33); + + int curCount; + + for (int j = 0; j < Constants::MTG_NB_COLORS - 1; j++) + { + curCount = stw->countBasicLandsPerColor[j]; + sprintf(buffer, (curCount == 0 ? "." : "%i"), curCount); + font->DrawString(buffer, 49 + leftTransition + j * 15, posY); + + curCount = stw->countLandsPerColor[j]; + sprintf(buffer, (curCount == 0 ? "." : "%i"), curCount); + font->DrawString(buffer, 49 + leftTransition + j * 15, posY + 10); + + curCount = stw->countNonLandProducersPerColor[j]; + sprintf(buffer, (curCount == 0 ? "." : "%i"), curCount); + font->DrawString(buffer, 49 + leftTransition + j * 15, posY + 20); + + curCount = stw->countLandsPerColor[j] + stw->countBasicLandsPerColor[j] + stw->countNonLandProducersPerColor[j]; + sprintf(buffer, (curCount == 0 ? "." : "%i"), curCount); + font->DrawString(buffer, 49 + leftTransition + j * 15, posY + 33); + } + + posY += 55; + font->DrawString(_("BL - Basic lands"), 20 + leftTransition, posY); + posY += 10; + font->DrawString(_("NB - Non-basic lands"), 20 + leftTransition, posY); + posY += 10; + font->DrawString(_("O - Other (non-land) manasources"), 26 + leftTransition, posY); + posY += 10; + font->DrawString(_("T - Totals"), 26 + leftTransition, posY); + + break; + + case 6: // Land statistics - in symbols + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana production - in mana symbols").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + font->DrawString(_("Total colored manasymbols in lands' production:"), 20 + leftTransition, 30); + + int totalProducedSymbols; + totalProducedSymbols = 0; + for (int i = 1; i < Constants::MTG_NB_COLORS - 1; i++) + { + totalProducedSymbols += stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i]; //!! Move to updatestats! + } + + posY = 50; + for (int i = 1; i < Constants::MTG_NB_COLORS - 1; i++) + { + if (stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i] > 0) + { + sprintf(buffer, _("%i").c_str(), stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i]); + font->DrawString(buffer, 20 + leftTransition, posY); + sprintf(buffer, _("(%i%%)").c_str(), (int) (100 * (float) (stw->countLandsPerColor[i] + + stw->countBasicLandsPerColor[i]) / totalProducedSymbols)); + font->DrawString(buffer, 33 + leftTransition, posY); + posX = 72; + for (int j = 0; j < stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i]; j++) + { + r->RenderQuad(mIcons[i], posX + leftTransition, posY + 6, 0, 0.5, 0.5); + posX += ((j + 1) % 10 == 0) ? 17 : 13; + if ((((j + 1) % 30) == 0) && (j < stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i] - 1)) + { + posX = 72; + posY += 15; + } + } + posY += 17; + } + } + + break; + + case 2: // Mana cost detail + case 3: + case 4: + int (*countPerCost)[Constants::STATS_MAX_MANA_COST + 1]; + int (*countPerCostAndColor)[Constants::STATS_MAX_MANA_COST + 1][Constants::MTG_NB_COLORS + 1]; + float avgCost; + + switch (stw->currentPage) + { // Nested switch on the same variable. Oh yes. + case 2: // Total counts + // Title + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + font->DrawString(_("Card counts per mana cost:"), 20 + leftTransition, 30); + avgCost = stw->avgManaCost; + countPerCost = &stw->countCardsPerCost; + countPerCostAndColor = &stw->countCardsPerCostAndColor; + break; + case 3: // Creature counts + // Title + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail - Creatures").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + font->DrawString(_("Creature counts per mana cost:"), 20 + leftTransition, 30); + avgCost = stw->avgCreatureCost; + countPerCost = &stw->countCreaturesPerCost; + countPerCostAndColor = &stw->countCreaturesPerCostAndColor; + break; + case 4: // Spell counts + // Title + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail - Spells").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + font->DrawString(_("Non-creature spell counts per mana cost:"), 20 + leftTransition, 30); + avgCost = stw->avgSpellCost; + countPerCost = &stw->countSpellsPerCost; + countPerCostAndColor = &stw->countSpellsPerCostAndColor; + break; + default: + countPerCost = NULL; + countPerCostAndColor = NULL; + avgCost = 0; + break; + } + + posY = 70; + + // Column titles + for (int j = 0; j < Constants::MTG_NB_COLORS - 1; j++) + { + r->RenderQuad(mIcons[j], 67 + j * 15 + leftTransition, posY - 10, 0, 0.5, 0.5); + } + + font->DrawString(_("C"), 30 + leftTransition, posY - 16); + font->DrawString(_("#"), 45 + leftTransition, posY - 16); + + // Horizontal table lines + r->DrawLine(27 + leftTransition, posY - 20, 75 + (Constants::MTG_NB_COLORS - 2) * 15 + leftTransition, posY - 20, + ARGB(128, 255, 255, 255)); + r->DrawLine(27 + leftTransition, posY - 1, 75 + (Constants::MTG_NB_COLORS - 2) * 15 + leftTransition, posY - 1, + ARGB(128, 255, 255, 255)); + r->DrawLine(27 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, 75 + (Constants::MTG_NB_COLORS - 2) + * 15 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, ARGB(128, 255, 255, 255)); + + // Vertical table lines + r->DrawLine(26 + leftTransition, posY - 20, 26 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, + ARGB(128, 255, 255, 255)); + r->DrawLine(41 + leftTransition, posY - 20, 41 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, + ARGB(128, 255, 255, 255)); + r->DrawLine(58 + leftTransition, posY - 20, 58 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, + ARGB(128, 255, 255, 255)); + r->DrawLine(75 + leftTransition + (Constants::MTG_NB_COLORS - 2) * 15, posY - 20, 75 + leftTransition + + (Constants::MTG_NB_COLORS - 2) * 15, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, + ARGB(128, 255, 255, 255)); + + for (int i = 0; i <= Constants::STATS_MAX_MANA_COST; i++) + { + sprintf(buffer, _("%i").c_str(), i); + font->DrawString(buffer, 30 + leftTransition, posY); + sprintf(buffer, ((*countPerCost)[i] > 0) ? _("%i").c_str() : ".", (*countPerCost)[i]); + font->DrawString(buffer, 45 + leftTransition, posY); + for (int j = 0; j < Constants::MTG_NB_COLORS - 1; j++) + { + sprintf(buffer, ((*countPerCostAndColor)[i][j] > 0) ? _("%i").c_str() : ".", (*countPerCostAndColor)[i][j]); + font->DrawString(buffer, 64 + leftTransition + j * 15, posY); + } + r->FillRect(77.f + leftTransition + (Constants::MTG_NB_COLORS - 2) * 15.0f, posY + 2.0f, (*countPerCost)[i] * 5.0f, + 8.0f, graphColor); + posY += 10; + } + + posY += 10; + sprintf(buffer, _("Average converted mana cost: %2.2f").c_str(), avgCost); + font->DrawString(buffer, 20 + leftTransition, posY); + posY += 15; + sprintf(buffer, _("C - Converted mana cost. Cards with cost>%i are included in the last row.").c_str(), + Constants::STATS_MAX_MANA_COST); + font->DrawString(buffer, 20 + leftTransition, posY); + posY += 10; + font->DrawString(_("# - Total number of cards with given cost"), 20 + leftTransition, posY); + + break; + + case 8: + // Title + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Probabilities").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + + // No lands detail + float graphScale, graphWidth; + graphWidth = 100; + graphScale = (stw->noLandsProbInTurn[0] == 0) ? 0 : (graphWidth / stw->noLandsProbInTurn[0]); + font->DrawString(_("No lands in first n cards:"), 20 + leftTransition, 30); + + posY = 50; + for (int i = 0; i < Constants::STATS_FOR_TURNS; i++) + { + sprintf(buffer, _("%i:").c_str(), i + 7); + font->DrawString(buffer, 30 + leftTransition, posY); + sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[i]); + font->DrawString(buffer, 45 + leftTransition, posY); + r->FillRect(84 + leftTransition, posY + 2, graphScale * stw->noLandsProbInTurn[i], 8, graphColor); + posY += 10; + } + + // No creatures probability detail + posY += 10; + font->DrawString(_("No creatures in first n cards:"), 20 + leftTransition, posY); + posY += 20; + graphScale = (stw->noCreaturesProbInTurn[0] == 0) ? 0 : (graphWidth / stw->noCreaturesProbInTurn[0]); + + for (int i = 0; i < Constants::STATS_FOR_TURNS; i++) + { + sprintf(buffer, _("%i:").c_str(), i + 7); + font->DrawString(buffer, 30 + leftTransition, posY); + sprintf(buffer, _("%2.2f%%").c_str(), stw->noCreaturesProbInTurn[i]); + font->DrawString(buffer, 45 + leftTransition, posY); + r->FillRect(84 + leftTransition, posY + 2, graphScale * stw->noCreaturesProbInTurn[i], 8, graphColor); + posY += 10; + } + + break; + + case 7: // Total mana cost per color + // Title + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost per color").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + + font->DrawString(_("Total colored manasymbols in cards' casting costs:"), 20 + leftTransition, 30); + + posY = 50; + for (int i = 1; i < Constants::MTG_NB_COLORS - 1; i++) + { + if (stw->totalCostPerColor[i] > 0) + { + sprintf(buffer, _("%i").c_str(), stw->totalCostPerColor[i]); + font->DrawString(buffer, 20 + leftTransition, posY); + sprintf(buffer, _("(%i%%)").c_str(), (int) (100 * (float) stw->totalCostPerColor[i] / stw->totalColoredSymbols)); + font->DrawString(buffer, 33 + leftTransition, posY); + posX = 72; + for (int j = 0; j < stw->totalCostPerColor[i]; j++) + { + r->RenderQuad(mIcons[i], posX + leftTransition, posY + 6, 0, 0.5, 0.5); + posX += ((j + 1) % 10 == 0) ? 17 : 13; + if ((((j + 1) % 30) == 0) && (j < stw->totalCostPerColor[i] - 1)) + { + posX = 72; + posY += 15; + } + } + posY += 17; + } + } + break; + + case 9: // Victory statistics + // Title + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Victory statistics").c_str()); + font->DrawString(buffer, 10 + leftTransition, 10); + + font->DrawString(_("Victories against AI:"), 20 + leftTransition, 30); + + sprintf(buffer, _("Games played: %i").c_str(), stw->gamesPlayed); + font->DrawString(buffer, 20 + leftTransition, 45); + sprintf(buffer, _("Victory ratio: %i%%").c_str(), stw->percentVictories); + font->DrawString(buffer, 20 + leftTransition, 55); + + int AIsPerColumn = 19; + posY = 70; + posX = 20; + + // ToDo: Multiple pages when too many AI decks are present + for (int i = 0; i < (int) stw->aiDeckStats.size(); i++) + { + sprintf(buffer, _("%.14s").c_str(), stw->aiDeckNames.at(i).c_str()); + font->DrawString(buffer, posX + (i < 2 * AIsPerColumn ? leftTransition : rightTransition), posY); + sprintf(buffer, _("%i/%i").c_str(), stw->aiDeckStats.at(i)->victories, stw->aiDeckStats.at(i)->nbgames); + font->DrawString(buffer, posX + (i < AIsPerColumn ? leftTransition : rightTransition) + 80, posY); + sprintf(buffer, _("%i%%").c_str(), stw->aiDeckStats.at(i)->percentVictories()); + font->DrawString(buffer, posX + (i < AIsPerColumn ? leftTransition : rightTransition) + 110, posY); + posY += 10; + if (((i + 1) % AIsPerColumn) == 0) + { + posY = 70; + posX += 155; + } + } + break; } - break; } - } } -void GameStateDeckViewer::updateStats() { - if (!stw->needUpdate || !myDeck) - return; - stw->needUpdate = false; - stw->cardCount = myDeck->getCount(WSrcDeck::UNFILTERED_COPIES); - stw->countLands = myDeck->getCount(Constants::MTG_COLOR_LAND); - stw->totalPrice = myDeck->totalPrice(); +void GameStateDeckViewer::updateStats() +{ + if (!stw->needUpdate || !myDeck) + return; + stw->needUpdate = false; + stw->cardCount = myDeck->getCount(WSrcDeck::UNFILTERED_COPIES); + stw->countLands = myDeck->getCount(Constants::MTG_COLOR_LAND); + stw->totalPrice = myDeck->totalPrice(); - stw->countManaProducers = 0; - // Mana cost - int currentCount, convertedCost; - ManaCost * currentCost; - stw->totalManaCost = 0; - stw->totalCreatureCost = 0; - stw->totalSpellCost = 0; - MTGCard * current = myDeck->getCard(); + stw->countManaProducers = 0; + // Mana cost + int currentCount, convertedCost; + ManaCost * currentCost; + stw->totalManaCost = 0; + stw->totalCreatureCost = 0; + stw->totalSpellCost = 0; + MTGCard * current = myDeck->getCard(); - // Clearing arrays - for (int i=0; i<=Constants::STATS_MAX_MANA_COST; i++) { - stw->countCardsPerCost[i] = 0; - stw->countCreaturesPerCost[i] = 0; - stw->countSpellsPerCost[i] = 0; - } - - for (int i=0; i<=Constants::MTG_NB_COLORS; i++) { - stw->totalCostPerColor[i] = 0; - stw->countLandsPerColor[i] = 0; - stw->countBasicLandsPerColor[i] = 0; - stw->countNonLandProducersPerColor[i] = 0; - } - - for (int i=0; i<=Constants::STATS_MAX_MANA_COST; i++) { - for (int k=0; k<=Constants::MTG_NB_COLORS; k++) { - stw->countCardsPerCostAndColor[i][k] = 0; - stw->countCreaturesPerCostAndColor[i][k] = 0; - stw->countSpellsPerCostAndColor[i][k] = 0; + // Clearing arrays + for (int i = 0; i <= Constants::STATS_MAX_MANA_COST; i++) + { + stw->countCardsPerCost[i] = 0; + stw->countCreaturesPerCost[i] = 0; + stw->countSpellsPerCost[i] = 0; } - } - for(int ic=0;icSize(true);ic++){ - current = myDeck->getCard(ic,true); - currentCost = current->data->getManaCost(); - convertedCost = currentCost->getConvertedCost(); - currentCount = myDeck->count(current); - - // Add to the cards per cost counters - stw->totalManaCost += convertedCost * currentCount; - if (convertedCost > Constants::STATS_MAX_MANA_COST) { - convertedCost = Constants::STATS_MAX_MANA_COST; + for (int i = 0; i <= Constants::MTG_NB_COLORS; i++) + { + stw->totalCostPerColor[i] = 0; + stw->countLandsPerColor[i] = 0; + stw->countBasicLandsPerColor[i] = 0; + stw->countNonLandProducersPerColor[i] = 0; } - stw->countCardsPerCost[convertedCost] += currentCount; - if (current->data->isCreature()) { - stw->countCreaturesPerCost[convertedCost] += currentCount; - stw->totalCreatureCost += convertedCost * currentCount; - } else if (current->data->isSpell()) { - stw->countSpellsPerCost[convertedCost] += currentCount; - stw->totalSpellCost += convertedCost * currentCount; - } - // Lets look for mana producing abilities + for (int i = 0; i <= Constants::STATS_MAX_MANA_COST; i++) + { + for (int k = 0; k <= Constants::MTG_NB_COLORS; k++) + { + stw->countCardsPerCostAndColor[i][k] = 0; + stw->countCreaturesPerCostAndColor[i][k] = 0; + stw->countSpellsPerCostAndColor[i][k] = 0; + } + } - vector abilityStrings; - string thisstring = current->data->magicText; - StringExplode(thisstring, "\n", &abilityStrings); + for (int ic = 0; ic < myDeck->Size(true); ic++) + { + current = myDeck->getCard(ic, true); + currentCost = current->data->getManaCost(); + convertedCost = currentCost->getConvertedCost(); + currentCount = myDeck->count(current); - for(int v=0;v<(int)abilityStrings.size();v++){ - string s = abilityStrings[v]; - size_t t = s.find("add"); - if(t != string::npos){ - s = s.substr(t+3); - ManaCost * mc = ManaCost::parseManaCost(s); - for (int j=0; jhasColor(j)){ - if (current->data->isLand()) { - if (current->data->hasType("Basic")) { - stw->countBasicLandsPerColor[j] += currentCount; - } else { - stw->countLandsPerColor[j] += currentCount; - } - } else { - stw->countNonLandProducersPerColor[j] += currentCount; + // Add to the cards per cost counters + stw->totalManaCost += convertedCost * currentCount; + if (convertedCost > Constants::STATS_MAX_MANA_COST) + { + convertedCost = Constants::STATS_MAX_MANA_COST; + } + stw->countCardsPerCost[convertedCost] += currentCount; + if (current->data->isCreature()) + { + stw->countCreaturesPerCost[convertedCost] += currentCount; + stw->totalCreatureCost += convertedCost * currentCount; + } + else if (current->data->isSpell()) + { + stw->countSpellsPerCost[convertedCost] += currentCount; + stw->totalSpellCost += convertedCost * currentCount; + } + + // Lets look for mana producing abilities + + vector abilityStrings; + string thisstring = current->data->magicText; + StringExplode(thisstring, "\n", &abilityStrings); + + for (int v = 0; v < (int) abilityStrings.size(); v++) + { + string s = abilityStrings[v]; + size_t t = s.find("add"); + if (t != string::npos) + { + s = s.substr(t + 3); + ManaCost * mc = ManaCost::parseManaCost(s); + for (int j = 0; j < Constants::MTG_NB_COLORS; j++) + { + if (mc->hasColor(j)) + { + if (current->data->isLand()) + { + if (current->data->hasType("Basic")) + { + stw->countBasicLandsPerColor[j] += currentCount; + } + else + { + stw->countLandsPerColor[j] += currentCount; + } + } + else + { + stw->countNonLandProducersPerColor[j] += currentCount; + } + } + } + SAFE_DELETE(mc); } - } } - SAFE_DELETE(mc); - } - } - // Add to the per color counters - // a. regular costs - for (int j=0; jtotalCostPerColor[j] += currentCost->getCost(j)*currentCount; - if (current->data->hasColor(j)) { - // Add to the per cost and color counter - stw->countCardsPerCostAndColor[convertedCost][j] += currentCount; - if (current->data->isCreature()) { - stw->countCreaturesPerCostAndColor[convertedCost][j] += currentCount; - } else if (current->data->isSpell()) { - stw->countSpellsPerCostAndColor[convertedCost][j] += currentCount; + // Add to the per color counters + // a. regular costs + for (int j = 0; j < Constants::MTG_NB_COLORS; j++) + { + stw->totalCostPerColor[j] += currentCost->getCost(j) * currentCount; + if (current->data->hasColor(j)) + { + // Add to the per cost and color counter + stw->countCardsPerCostAndColor[convertedCost][j] += currentCount; + if (current->data->isCreature()) + { + stw->countCreaturesPerCostAndColor[convertedCost][j] += currentCount; + } + else if (current->data->isSpell()) + { + stw->countSpellsPerCostAndColor[convertedCost][j] += currentCount; + } + } + } + + // b. Hybrid costs + ManaCostHybrid * hybridCost; + int i; + i = 0; + + while ((hybridCost = currentCost->getHybridCost(i++)) != NULL) + { + stw->totalCostPerColor[hybridCost->color1] += hybridCost->value1 * currentCount; + stw->totalCostPerColor[hybridCost->color2] += hybridCost->value2 * currentCount; } - } } - // b. Hybrid costs - ManaCostHybrid * hybridCost; - int i; - i = 0; - - while ((hybridCost = currentCost->getHybridCost(i++)) != NULL) { - stw->totalCostPerColor[hybridCost->color1] += hybridCost->value1*currentCount; - stw->totalCostPerColor[hybridCost->color2] += hybridCost->value2*currentCount; + stw->totalColoredSymbols = 0; + for (int j = 1; j < Constants::MTG_NB_COLORS; j++) + { + stw->totalColoredSymbols += stw->totalCostPerColor[j]; } - } - stw->totalColoredSymbols = 0; - for (int j=1; jtotalColoredSymbols += stw->totalCostPerColor[j]; - } + stw->countCardsPerCost[0] -= stw->countLands; - stw->countCardsPerCost[0] -= stw->countLands; + // Counts by type + stw->countCreatures = countCardsByType("Creature"); + stw->countInstants = countCardsByType("Instant"); + stw->countEnchantments = countCardsByType("Enchantment"); + stw->countSorceries = countCardsByType("Sorcery"); + stw->countSpells = stw->countInstants + stw->countEnchantments + stw->countSorceries; + //stw->countArtifacts = countCardsByType("Artifact"); - // Counts by type - stw->countCreatures = countCardsByType("Creature"); - stw->countInstants = countCardsByType("Instant"); - stw->countEnchantments = countCardsByType("Enchantment"); - stw->countSorceries = countCardsByType("Sorcery"); - stw->countSpells = stw->countInstants + stw->countEnchantments + stw->countSorceries; - //stw->countArtifacts = countCardsByType("Artifact"); + // Average mana costs + stw->avgManaCost = ((stw->cardCount - stw->countLands) <= 0) ? 0 : (float) stw->totalManaCost / (stw->cardCount + - stw->countLands); + stw->avgCreatureCost = (stw->countCreatures <= 0) ? 0 : (float) stw->totalCreatureCost / stw->countCreatures; + stw->avgSpellCost = (stw->countSpells <= 0) ? 0 : (float) stw->totalSpellCost / stw->countSpells; - // Average mana costs - stw->avgManaCost = ((stw->cardCount - stw->countLands) <= 0)?0:(float)stw->totalManaCost / (stw->cardCount - stw->countLands); - stw->avgCreatureCost = (stw->countCreatures <= 0)?0:(float)stw->totalCreatureCost / stw->countCreatures; - stw->avgSpellCost = (stw->countSpells <= 0)?0:(float)stw->totalSpellCost / stw->countSpells; - - // Probabilities - // TODO: this could be optimized by reusing results - for (int i=0; inoLandsProbInTurn[i] = noLuck(stw->cardCount, stw->countLands, 7+i)*100; - stw->noCreaturesProbInTurn[i] = noLuck(stw->cardCount, stw->countCreatures, 7+i)*100; - } + // Probabilities + // TODO: this could be optimized by reusing results + for (int i = 0; i < Constants::STATS_FOR_TURNS; i++) + { + stw->noLandsProbInTurn[i] = noLuck(stw->cardCount, stw->countLands, 7 + i) * 100; + stw->noCreaturesProbInTurn[i] = noLuck(stw->cardCount, stw->countCreatures, 7 + i) * 100; + } } // This should probably be cached in DeckDataWrapper // or at least be calculated for all common types in one go -int GameStateDeckViewer::countCardsByType(const char * _type) { - int result = 0; - for(int i=0;iSize(true);i++){ - MTGCard * current = myDeck->getCard(i,true); - if(current->data->hasType(_type)){ - result += myDeck->count(current); +int GameStateDeckViewer::countCardsByType(const char * _type) +{ + int result = 0; + for (int i = 0; i < myDeck->Size(true); i++) + { + MTGCard * current = myDeck->getCard(i, true); + if (current->data->hasType(_type)) + { + result += myDeck->count(current); + } } - } - return result; + return result; } -void GameStateDeckViewer::renderCard(int id, float rotation){ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - MTGCard * card = cardIndex[id]; +void GameStateDeckViewer::renderCard(int id, float rotation) +{ + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + MTGCard * card = cardIndex[id]; - float max_scale = 0.96f; - float x_center_0 = 180; - float right_border = SCREEN_WIDTH - 20 ; + float max_scale = 0.96f; + float x_center_0 = 180; + float right_border = SCREEN_WIDTH - 20; - float x_center = x_center_0 + cos((rotation + 8 - id)*M_PI/12)*(right_border-x_center_0); - float scale = max_scale/ 1.12f * cos((x_center-x_center_0)*1.5f/(right_border - x_center_0) ) + 0.2f * max_scale * cos (cos((x_center-x_center_0)*0.15f/(right_border - x_center_0) )); - float x = x_center; // ; + float x_center = x_center_0 + cos((rotation + 8 - id) * M_PI / 12) * (right_border - x_center_0); + float scale = max_scale / 1.12f * cos((x_center - x_center_0) * 1.5f / (right_border - x_center_0)) + 0.2f * max_scale * cos( + cos((x_center - x_center_0) * 0.15f / (right_border - x_center_0))); + float x = x_center; // ; - float y = (SCREEN_HEIGHT_F)/2.0f + SCREEN_HEIGHT_F * mSlide * (scale + 0.2f); + float y = (SCREEN_HEIGHT_F) / 2.0f + SCREEN_HEIGHT_F * mSlide * (scale + 0.2f); - int alpha = (int) (255 * (scale + 1.0 - max_scale)); + int alpha = (int) (255 * (scale + 1.0 - max_scale)); - if (!card) return; - JQuad * quad = NULL; + if (!card) + return; + JQuad * quad = NULL; - int cacheError = CACHE_ERROR_NONE; + int cacheError = CACHE_ERROR_NONE; - if(!options[Options::DISABLECARDS].number) - { - quad = resources.RetrieveCard(card,RETRIEVE_EXISTING); - cacheError = resources.RetrieveError(); - if (!quad && cacheError != CACHE_ERROR_404) + if (!options[Options::DISABLECARDS].number) { - if(last_user_activity > (abs(2-id) + 1)* NO_USER_ACTIVITY_SHOWCARD_DELAY) - quad = resources.RetrieveCard(card); - else{ - quad = backQuad; - } + quad = resources.RetrieveCard(card, RETRIEVE_EXISTING); + cacheError = resources.RetrieveError(); + if (!quad && cacheError != CACHE_ERROR_404) + { + if (last_user_activity > (abs(2 - id) + 1) * NO_USER_ACTIVITY_SHOWCARD_DELAY) + quad = resources.RetrieveCard(card); + else + { + quad = backQuad; + } + } } - } - int quadAlpha = alpha; - if ( !displayed_deck->count(card)) quadAlpha /=2; - if (quad) - { - if (quad == backQuad) - { - quad->SetColor(ARGB(255,255,255,255)); - float _scale = scale *(285 / quad->mHeight); - JRenderer::GetInstance()->RenderQuad(quad, x, y, 0.0f, _scale, _scale); - } - else - { - Pos pos = Pos(x, y, scale* 285/250, 0.0, 255); - CardGui::DrawCard(card, pos); - } - } - else - { - Pos pos = Pos(x, y, scale* 285/250, 0.0, 255); - CardGui::DrawCard(card, pos, DrawMode::kText); - if(!options[Options::DISABLECARDS].number) - quad = resources.RetrieveCard(card,CACHE_THUMB); + int quadAlpha = alpha; + if (!displayed_deck->count(card)) + quadAlpha /= 2; if (quad) { - float _scale = 285 * scale / quad->mHeight; - quad->SetColor(ARGB(40,255,255,255)); - JRenderer::GetInstance()->RenderQuad(quad, x, y, 0, _scale, _scale); + if (quad == backQuad) + { + quad->SetColor(ARGB(255,255,255,255)); + float _scale = scale * (285 / quad->mHeight); + JRenderer::GetInstance()->RenderQuad(quad, x, y, 0.0f, _scale, _scale); + } + else + { + Pos pos = Pos(x, y, scale * 285 / 250, 0.0, 255); + CardGui::DrawCard(card, pos); + } + } + else + { + Pos pos = Pos(x, y, scale * 285 / 250, 0.0, 255); + CardGui::DrawCard(card, pos, DrawMode::kText); + if (!options[Options::DISABLECARDS].number) + quad = resources.RetrieveCard(card, CACHE_THUMB); + if (quad) + { + float _scale = 285 * scale / quad->mHeight; + quad->SetColor(ARGB(40,255,255,255)); + JRenderer::GetInstance()->RenderQuad(quad, x, y, 0, _scale, _scale); + } + } + quadAlpha = 255 - quadAlpha; + if (quadAlpha > 0) + { + JRenderer::GetInstance()->FillRect(x - scale * 100.0f, y - scale * 142.5f, scale * 200.0f, scale * 285.0f, + ARGB(quadAlpha,0,0,0)); + } + if (last_user_activity < 3) + { + int fontAlpha = alpha; + float qtY = y - 135 * scale; + float qtX = x + 40 * scale; + char buffer[4096]; + sprintf(buffer, "x%i", displayed_deck->count(card)); + WFont * font = mFont; + font->SetColor(ARGB(fontAlpha/2,0,0,0)); + JRenderer::GetInstance()->FillRect(qtX, qtY, font->GetStringWidth(buffer) + 6, 16, ARGB(fontAlpha/2,0,0,0)); + font->DrawString(buffer, qtX + 4, qtY + 4); + font->SetColor(ARGB(fontAlpha,255,255,255)); + font->DrawString(buffer, qtX + 2, qtY + 2); + font->SetColor(ARGB(255,255,255,255)); } - } - quadAlpha = 255 - quadAlpha; - if (quadAlpha > 0) - { - JRenderer::GetInstance()->FillRect(x - scale * 100.0f ,y - scale * 142.5f , scale * 200.0f, scale * 285.0f, ARGB(quadAlpha,0,0,0)); - } - if (last_user_activity < 3) - { - int fontAlpha = alpha; - float qtY = y -135*scale; - float qtX = x + 40*scale; - char buffer[4096]; - sprintf(buffer, "x%i", displayed_deck->count(card)); - WFont * font = mFont; - font->SetColor(ARGB(fontAlpha/2,0,0,0)); - JRenderer::GetInstance()->FillRect(qtX, qtY,font->GetStringWidth(buffer) + 6,16,ARGB(fontAlpha/2,0,0,0)); - font->DrawString(buffer, qtX + 4, qtY + 4); - font->SetColor(ARGB(fontAlpha,255,255,255)); - font->DrawString(buffer, qtX+2, qtY + 2); - font->SetColor(ARGB(255,255,255,255)); - } } - -void GameStateDeckViewer::renderCard (int id){ - renderCard(id, 0); +void GameStateDeckViewer::renderCard(int id) +{ + renderCard(id, 0); } -void GameStateDeckViewer::Render() { +void GameStateDeckViewer::Render() +{ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - JRenderer * r = JRenderer::GetInstance(); - r->ClearScreen(ARGB(0,0,0,0)); - if(displayed_deck == myDeck && mStage != STAGE_MENU) - renderDeckBackground(); - int order[3] = {1,2,3}; - if (mRotation < 0.5 && mRotation > -0.5){ - order[1]=3; - order[2]=2; - }else if (mRotation < -0.5){ - order[0] = 3; - order[2] = 1; - } - - renderCard(6,mRotation); - renderCard(5,mRotation); - renderCard(4,mRotation); - renderCard(0,mRotation); - - for (int i =0; i< 3; i++){ - renderCard(order[i],mRotation); - } - - if (displayed_deck->Size()>0){ - renderSlideBar(); - }else{ - mFont->DrawString(_("No Card"), SCREEN_WIDTH/2, SCREEN_HEIGHT/2,JGETEXT_CENTER); - } - if (mStage == STAGE_ONSCREEN_MENU){ - renderOnScreenMenu(); - }else if (mStage == STAGE_WELCOME){ - welcome_menu->Render(); - }else{ - renderOnScreenBasicInfo(); - - } - if (mStage == STAGE_MENU){ - menu->Render(); - } - if (subMenu) - subMenu->Render(); - - if(filterMenu && !filterMenu->isFinished()) - filterMenu->Render(); - - if(options.keypadActive()) - options.keypadRender(); - - -} - - -int GameStateDeckViewer::loadDeck(int deckid){ - - if (!stw) - stw = new StatsWrapper( deckid ); - - stw->currentPage = 0; - stw->pageCount = 9; - stw->needUpdate = true; - - if(!playerdata) - playerdata = NEW PlayerData(mParent->collection); - SAFE_DELETE(myCollection); - myCollection = NEW DeckDataWrapper(playerdata->collection); - myCollection->Sort(WSrcCards::SORT_ALPHA); - displayed_deck = myCollection; - - char deckname[256]; - sprintf(deckname,"deck%i.txt",deckid); - if(myDeck){ - SAFE_DELETE(myDeck->parent); - SAFE_DELETE(myDeck); - } - myDeck = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(deckname,"",false,false).c_str(), mParent->collection)); - - // Check whether the cards in the deck are actually available in the player's collection: - int cheatmode = options[Options::CHEATMODE].number; - bool bPure = true; - for(int i=0;iSize(true);i++){ - MTGCard * current = myDeck->getCard(i,true); - int howmanyinDeck = myDeck->count(current); - for (int i = myCollection->count(current); i < howmanyinDeck; i++){ - bPure = false; - if(cheatmode){ //Are we cheating? - playerdata->collection->add(current); //Yup, add it to collection permanently. - myCollection->Add(current); - } - else{ - myDeck->Remove(current); //Nope. Remove it from deck. - break; - } + JRenderer * r = JRenderer::GetInstance(); + r->ClearScreen(ARGB(0,0,0,0)); + if (displayed_deck == myDeck && mStage != STAGE_MENU) + renderDeckBackground(); + int order[3] = { 1, 2, 3 }; + if (mRotation < 0.5 && mRotation > -0.5) + { + order[1] = 3; + order[2] = 2; + } + else if (mRotation < -0.5) + { + order[0] = 3; + order[2] = 1; } - myCollection->Remove(current,myDeck->count(current)); - } - if(!bPure){ - myDeck->validate(); - myCollection->validate(); - } + renderCard(6, mRotation); + renderCard(5, mRotation); + renderCard(4, mRotation); + renderCard(0, mRotation); - myDeck->Sort(WSrcCards::SORT_ALPHA); - SAFE_DELETE(filterMenu); - rebuildFilters(); - loadIndexes(); - return 1; + for (int i = 0; i < 3; i++) + { + renderCard(order[i], mRotation); + } + + if (displayed_deck->Size() > 0) + { + renderSlideBar(); + } + else + { + mFont->DrawString(_("No Card"), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, JGETEXT_CENTER); + } + if (mStage == STAGE_ONSCREEN_MENU) + { + renderOnScreenMenu(); + } + else if (mStage == STAGE_WELCOME) + { + welcome_menu->Render(); + } + else + { + renderOnScreenBasicInfo(); + + } + if (mStage == STAGE_MENU) + { + menu->Render(); + } + if (subMenu) + subMenu->Render(); + + if (filterMenu && !filterMenu->isFinished()) + filterMenu->Render(); + + if (options.keypadActive()) + options.keypadRender(); + +} + +int GameStateDeckViewer::loadDeck(int deckid) +{ + + if (!stw) + stw = new StatsWrapper(deckid); + + stw->currentPage = 0; + stw->pageCount = 9; + stw->needUpdate = true; + + if (!playerdata) + playerdata = NEW PlayerData(mParent->collection); + SAFE_DELETE(myCollection); + myCollection = NEW DeckDataWrapper(playerdata->collection); + myCollection->Sort(WSrcCards::SORT_ALPHA); + displayed_deck = myCollection; + + char deckname[256]; + sprintf(deckname, "deck%i.txt", deckid); + if (myDeck) + { + SAFE_DELETE(myDeck->parent); + SAFE_DELETE(myDeck); + } + myDeck = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(deckname, "", false, false).c_str(), mParent->collection)); + + // Check whether the cards in the deck are actually available in the player's collection: + int cheatmode = options[Options::CHEATMODE].number; + bool bPure = true; + for (int i = 0; i < myDeck->Size(true); i++) + { + MTGCard * current = myDeck->getCard(i, true); + int howmanyinDeck = myDeck->count(current); + for (int i = myCollection->count(current); i < howmanyinDeck; i++) + { + bPure = false; + if (cheatmode) + { //Are we cheating? + playerdata->collection->add(current); //Yup, add it to collection permanently. + myCollection->Add(current); + } + else + { + myDeck->Remove(current); //Nope. Remove it from deck. + break; + } + } + + myCollection->Remove(current, myDeck->count(current)); + } + if (!bPure) + { + myDeck->validate(); + myCollection->validate(); + } + + myDeck->Sort(WSrcCards::SORT_ALPHA); + SAFE_DELETE(filterMenu); + rebuildFilters(); + loadIndexes(); + return 1; } void GameStateDeckViewer::ButtonPressed(int controllerId, int controlId) { - int deckIdNumber = controlId; - int deckListSize = 0; - string defaultAiName; - DeckManager *deckManager = DeckManager::GetInstance(); - vector * deckList; - switch(controllerId){ - case MENU_DECK_SELECTION: //Deck menu - if (controlId == MENU_ITEM_CANCEL){ - if(!mSwitching) - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - else - mStage = STAGE_WAITING; + int deckIdNumber = controlId; + int deckListSize = 0; + string defaultAiName; + DeckManager *deckManager = DeckManager::GetInstance(); + vector * deckList; + switch (controllerId) + { + case MENU_DECK_SELECTION: //Deck menu + if (controlId == MENU_ITEM_CANCEL) + { + if (!mSwitching) + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + else + mStage = STAGE_WAITING; - mSwitching = false; - break; - } else if(controlId == MENU_ITEM_CHEAT_MODE){ // (PSY) Cheatmode: Complete the collection - playerdata->collection->complete(); // Add the cards - playerdata->collection->save(); // Save the new collection - for(int i=0;i(&options[Options::optionSet(i)]); - if(goa) - goa->giveAward(); - } - options.save(); - SAFE_DELETE(myCollection); - myCollection = NEW DeckDataWrapper(playerdata->collection); - myCollection->Sort(WSrcCards::SORT_ALPHA); - displayed_deck = myCollection; - rebuildFilters(); - loadIndexes(); - mStage = STAGE_WELCOME; - break; + mSwitching = false; + break; + } + else if (controlId == MENU_ITEM_CHEAT_MODE) + { // (PSY) Cheatmode: Complete the collection + playerdata->collection->complete(); // Add the cards + playerdata->collection->save(); // Save the new collection + for (int i = 0; i < setlist.size(); i++) + { // Update unlocked sets + GameOptionAward * goa = dynamic_cast (&options[Options::optionSet(i)]); + if (goa) + goa->giveAward(); + } + options.save(); + SAFE_DELETE(myCollection); + myCollection = NEW DeckDataWrapper(playerdata->collection); + myCollection->Sort(WSrcCards::SORT_ALPHA); + displayed_deck = myCollection; + rebuildFilters(); + loadIndexes(); + mStage = STAGE_WELCOME; + break; } mStage = STAGE_WAITING; deckList = deckManager->getPlayerDeckOrderList(); deckListSize = deckList->size(); if (controlId == MENU_ITEM_NEW_DECK) // new deck option selected - deckIdNumber = deckList->size() + 1; + deckIdNumber = deckList->size() + 1; else if (deckListSize > 0 && controlId <= deckListSize) - deckIdNumber = deckList->at(controlId - 1)-> getDeckId(); + deckIdNumber = deckList->at(controlId - 1)-> getDeckId(); else - deckIdNumber = controlId; + deckIdNumber = controlId; loadDeck(deckIdNumber); mStage = STAGE_WAITING; deckNum = controlId; break; - case MENU_DECK_BUILDER: //Save / exit menu + case MENU_DECK_BUILDER: //Save / exit menu switch (controlId) { case MENU_ITEM_SAVE_RETURN_MAIN_MENU: - saveDeck(); - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - break; + saveDeck(); + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + break; case MENU_ITEM_SAVE_RENAME: - if(myDeck && myDeck->parent){ - options.keypadStart(myDeck->parent->meta_name, &newDeckname); - options.keypadTitle("Rename deck"); - } - break; + if (myDeck && myDeck->parent) + { + options.keypadStart(myDeck->parent->meta_name, &newDeckname); + options.keypadTitle("Rename deck"); + } + break; case MENU_ITEM_SAVE_AS_AI_DECK: - // find the next unused ai deck number - // warn user that once saved, no edits can be made - // save entire collection to ai as spelled out card with count - // bring user to main deck editor menu. - isAIDeckSave = true; - defaultAiName = myDeck && myDeck->parent ? myDeck->parent->meta_name : "Custom AI Deck"; - options.keypadStart( defaultAiName, &newDeckname); - options.keypadTitle("Name Custom AI Deck"); - updateDecks(); - mStage = STAGE_WELCOME; - mSwitching = true; - break; + // find the next unused ai deck number + // warn user that once saved, no edits can be made + // save entire collection to ai as spelled out card with count + // bring user to main deck editor menu. + isAIDeckSave = true; + defaultAiName = myDeck && myDeck->parent ? myDeck->parent->meta_name : "Custom AI Deck"; + options.keypadStart(defaultAiName, &newDeckname); + options.keypadTitle("Name Custom AI Deck"); + updateDecks(); + mStage = STAGE_WELCOME; + mSwitching = true; + break; case MENU_ITEM_SWITCH_DECKS_NO_SAVE: - updateDecks(); - mStage = STAGE_WELCOME; - mSwitching = true; - break; + updateDecks(); + mStage = STAGE_WELCOME; + mSwitching = true; + break; case MENU_ITEM_MAIN_MENU: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - break; + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + break; case MENU_ITEM_EDITOR_CANCEL: - mStage = STAGE_WAITING; - break; + mStage = STAGE_WAITING; + break; case MENU_ITEM_FILTER_BY: - mStage = STAGE_FILTERS; - if(!filterMenu) rebuildFilters(); - filterMenu->Entering(JGE_BTN_NONE); - break; + mStage = STAGE_FILTERS; + if (!filterMenu) + rebuildFilters(); + filterMenu->Entering(JGE_BTN_NONE); + break; } break; - case MENU_CARD_PURCHASE: // Yes/ No sub menu. - switch (controlId){ - case MENU_ITEM_YES: + case MENU_CARD_PURCHASE: // Yes/ No sub menu. + switch (controlId) { - MTGCard * card = cardIndex[2]; - if (card){ - int rnd = (rand() % 25); - playerdata->credits += price; - price = price - (rnd * price)/100; - pricelist->setPrice(card->getMTGId(),price); - playerdata->collection->remove(card->getMTGId()); - displayed_deck->Remove(card,1); - displayed_deck->validate(); - stw->needUpdate = true; - loadIndexes(); - } + case MENU_ITEM_YES: + { + MTGCard * card = cardIndex[2]; + if (card) + { + int rnd = (rand() % 25); + playerdata->credits += price; + price = price - (rnd * price) / 100; + pricelist->setPrice(card->getMTGId(), price); + playerdata->collection->remove(card->getMTGId()); + displayed_deck->Remove(card, 1); + displayed_deck->validate(); + stw->needUpdate = true; + loadIndexes(); + } } - case MENU_ITEM_NO: - subMenu->Close(); - break; + case MENU_ITEM_NO: + subMenu->Close(); + break; } - } + } } // n cards total, a of them are of desired type (A), x drawn // returns probability of no A's -float noLuck(int n, int a, int x) { - if ((a >= n) || (a == 0)) - return 1; - if ((n == 0) || (x == 0) || (x > n) || (n-a < x)) - return 0; +float noLuck(int n, int a, int x) +{ + if ((a >= n) || (a == 0)) + return 1; + if ((n == 0) || (x == 0) || (x > n) || (n - a < x)) + return 0; - a = n - a; - float result = 1; + a = n - a; + float result = 1; - for (int i=0; i #endif - + const float MENU_FONT_SCALE = 1.0f; enum ENUM_DUEL_STATE - { +{ DUEL_STATE_START, DUEL_STATE_END, DUEL_STATE_CHOOSE_DECK1, @@ -40,587 +40,666 @@ enum ENUM_DUEL_STATE DUEL_STATE_BACK_TO_MAIN_MENU, DUEL_STATE_MENU, DUEL_STATE_ERROR - }; +}; enum ENUM_DUEL_MENUS - { +{ DUEL_MENU_GAME_MENU, DUEL_MENU_CHOOSE_DECK, DUEL_MENU_CHOOSE_OPPONENT - }; +}; - -GameStateDuel::GameStateDuel(GameApp* parent): GameState(parent) { - for (int i = 0; i<2; i ++){ - deck[i]=NULL; - mPlayers[i]=NULL; - } - premadeDeck = false; - game = NULL; - deckmenu = NULL; - opponentMenu = NULL; - menu = NULL; +GameStateDuel::GameStateDuel(GameApp* parent) : + GameState(parent) +{ + for (int i = 0; i < 2; i++) + { + deck[i] = NULL; + mPlayers[i] = NULL; + } + premadeDeck = false; + game = NULL; + deckmenu = NULL; + opponentMenu = NULL; + menu = NULL; #ifdef TESTSUITE - testSuite = NULL; + testSuite = NULL; #endif - credits = NULL; - rules = NULL; + credits = NULL; + rules = NULL; } -GameStateDuel::~GameStateDuel() { - End(); +GameStateDuel::~GameStateDuel() +{ + End(); } void GameStateDuel::Start() { - JRenderer * renderer = JRenderer::GetInstance(); - renderer->EnableVSync(true); - OpponentsDeckid=0; - + JRenderer * renderer = JRenderer::GetInstance(); + renderer->EnableVSync(true); + OpponentsDeckid = 0; #ifdef TESTSUITE - SAFE_DELETE(testSuite); - testSuite = NEW TestSuite(JGE_GET_RES("test/_tests.txt").c_str(),mParent->collection); + SAFE_DELETE(testSuite); + testSuite = NEW TestSuite(JGE_GET_RES("test/_tests.txt").c_str(),mParent->collection); #endif - mGamePhase = DUEL_STATE_CHOOSE_DECK1; - credits = NEW Credits(); + mGamePhase = DUEL_STATE_CHOOSE_DECK1; + credits = NEW Credits(); - menu = NULL; + menu = NULL; - int decksneeded = 0; - for (int i = 0; i<2; i ++){ - if (mParent->players[i] == PLAYER_TYPE_HUMAN){ - decksneeded = 1; - - deckmenu = NEW DeckMenu(DUEL_MENU_CHOOSE_DECK, this, Fonts::OPTION_FONT, "Choose a Deck", MENU_FONT_SCALE); + int decksneeded = 0; + for (int i = 0; i < 2; i++) + { + if (mParent->players[i] == PLAYER_TYPE_HUMAN) + { + decksneeded = 1; - DeckManager *deckManager = DeckManager::GetInstance(); - vector playerDeckList = getValidDeckMetaData( options.profileFile() ); - int nbDecks = playerDeckList.size(); + deckmenu = NEW DeckMenu(DUEL_MENU_CHOOSE_DECK, this, Fonts::OPTION_FONT, "Choose a Deck", MENU_FONT_SCALE); - if (nbDecks) - { - decksneeded = 0; - if (nbDecks > 1 ) - deckmenu->Add( MENUITEM_RANDOM_PLAYER, "Random", "Play with a random deck." ); - } + DeckManager *deckManager = DeckManager::GetInstance(); + vector playerDeckList = getValidDeckMetaData(options.profileFile()); + int nbDecks = playerDeckList.size(); - renderDeckMenu( deckmenu, playerDeckList ); - // save the changes to the player deck list maintained in DeckManager - deckManager->updateMetaDataList( &playerDeckList, false); - playerDeckList.clear(); + if (nbDecks) + { + decksneeded = 0; + if (nbDecks > 1) + deckmenu->Add(MENUITEM_RANDOM_PLAYER, "Random", "Play with a random deck."); + } - break; + renderDeckMenu(deckmenu, playerDeckList); + // save the changes to the player deck list maintained in DeckManager + deckManager->updateMetaDataList(&playerDeckList, false); + playerDeckList.clear(); + + break; + } } - } - if(deckmenu){ - if (decksneeded){ - //translate deck creating desc - Translator * t = Translator::GetInstance(); - map::iterator it = t->deckValues.find("Create your Deck!"); - if (it != t->deckValues.end()) - deckmenu->Add( MENUITEM_NEW_DECK, "Create your Deck!", it->second); + if (deckmenu) + { + if (decksneeded) + { + //translate deck creating desc + Translator * t = Translator::GetInstance(); + map::iterator it = t->deckValues.find("Create your Deck!"); + if (it != t->deckValues.end()) + deckmenu->Add(MENUITEM_NEW_DECK, "Create your Deck!", it->second); + else + deckmenu->Add(MENUITEM_NEW_DECK, "Create your Deck!", "Highly recommended to get\nthe full Wagic experience!"); + premadeDeck = true; + fillDeckMenu(deckmenu, JGE_GET_RES("player/premade")); + } + deckmenu->Add(MENUITEM_NEW_DECK, "New Deck...", "Create a new deck to play with."); + deckmenu->Add(MENUITEM_CANCEL, "Main Menu", "Return to Main Menu"); + } + + for (int i = 0; i < 2; ++i) + { + mPlayers[i] = NULL; + } + +} + +void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI) +{ + if (decknb) + { + if (!isAI) + { //Human Player + char deckFile[255]; + if (premadeDeck) + sprintf(deckFile, JGE_GET_RES("player/premade/deck%i.txt").c_str(), decknb); + else + sprintf(deckFile, "%s/deck%i.txt", options.profileFile().c_str(), decknb); + char deckFileSmall[255]; + sprintf(deckFileSmall, "player_deck%i", decknb); + MTGDeck * tempDeck = NEW MTGDeck(deckFile, mParent->collection); + mPlayers[playerId] = NEW HumanPlayer(tempDeck, deckFile, deckFileSmall); + + deck[playerId] = mPlayers[playerId]->game; + delete tempDeck; + } else - deckmenu->Add( MENUITEM_NEW_DECK, "Create your Deck!", "Highly recommended to get\nthe full Wagic experience!"); - premadeDeck = true; - fillDeckMenu(deckmenu,JGE_GET_RES("player/premade")); + { //AI Player, chooses deck + AIPlayerFactory playerCreator; + Player * opponent = NULL; + if (playerId == 1) + opponent = mPlayers[0]; + mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection, opponent, decknb); + deck[playerId] = mPlayers[playerId]->game; + } + } + else + { //Random deck + AIPlayerFactory playerCreator; + Player * opponent = NULL; + if (playerId == 1) + opponent = mPlayers[0]; + mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection, opponent); + deck[playerId] = mPlayers[playerId]->game; } - deckmenu->Add( MENUITEM_NEW_DECK, "New Deck...", "Create a new deck to play with."); - deckmenu->Add( MENUITEM_CANCEL, "Main Menu", "Return to Main Menu"); - } - - for (int i = 0; i < 2; ++i){ - mPlayers[i] = NULL; - } - } -void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI){ - if (decknb) { - if (!isAI) { //Human Player - char deckFile[255]; - if(premadeDeck) - sprintf(deckFile, JGE_GET_RES("player/premade/deck%i.txt").c_str(),decknb); - else - sprintf(deckFile, "%s/deck%i.txt",options.profileFile().c_str(), decknb); - char deckFileSmall[255]; - sprintf(deckFileSmall, "player_deck%i",decknb); - MTGDeck * tempDeck = NEW MTGDeck(deckFile, mParent->collection); - mPlayers[playerId] = NEW HumanPlayer(tempDeck, deckFile, deckFileSmall); - - deck[playerId] = mPlayers[playerId]->game; - delete tempDeck; - } - else { //AI Player, chooses deck - AIPlayerFactory playerCreator; - Player * opponent = NULL; - if (playerId == 1) opponent = mPlayers[0]; - mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection,opponent,decknb); - deck[playerId] = mPlayers[playerId]->game; - } - } - else { //Random deck - AIPlayerFactory playerCreator; - Player * opponent = NULL; - if (playerId == 1) opponent = mPlayers[0]; - mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection,opponent); - deck[playerId] = mPlayers[playerId]->game; - } -} - -void GameStateDuel::initRand(unsigned int seed){ - if (!seed) seed = time(0); - srand(seed); +void GameStateDuel::initRand(unsigned int seed) +{ + if (!seed) + seed = time(0); + srand(seed); } #ifdef TESTSUITE -void GameStateDuel::loadTestSuitePlayers(){ - if (!testSuite) return; - initRand(testSuite->seed); - SAFE_DELETE(game); - for (int i = 0; i < 2; i++){ - mPlayers[i] = NEW TestSuiteAI(testSuite, i); - deck[i] = mPlayers[i]->game; - } - mParent->gameType = testSuite->gameType; +void GameStateDuel::loadTestSuitePlayers() +{ + if (!testSuite) return; + initRand(testSuite->seed); + SAFE_DELETE(game); + for (int i = 0; i < 2; i++) + { + mPlayers[i] = NEW TestSuiteAI(testSuite, i); + deck[i] = mPlayers[i]->game; + } + mParent->gameType = testSuite->gameType; - GameObserver::Init(mPlayers, 2); - game = GameObserver::GetInstance(); - game->startGame(rules); - if (mParent->gameType == GAME_TYPE_MOMIR){ - game->addObserver(NEW MTGMomirRule(-1, mParent->collection)); - } + GameObserver::Init(mPlayers, 2); + game = GameObserver::GetInstance(); + game->startGame(rules); + if (mParent->gameType == GAME_TYPE_MOMIR) + { + game->addObserver(NEW MTGMomirRule(-1, mParent->collection)); + } } #endif void GameStateDuel::End() { - DebugTrace("Ending GameStateDuel"); + DebugTrace("Ending GameStateDuel"); - JRenderer::GetInstance()->EnableVSync(false); - DeckManager::EndInstance(); + JRenderer::GetInstance()->EnableVSync(false); + DeckManager::EndInstance(); - if (mPlayers[0] && mPlayers[1]) // save the stats for the game - mPlayers[0]->End(); - else // clean up player object - SAFE_DELETE( mPlayers[0] ); + if (mPlayers[0] && mPlayers[1]) // save the stats for the game + mPlayers[0]->End(); + else + // clean up player object + SAFE_DELETE( mPlayers[0] ); - GameObserver::EndInstance(); - game = NULL; - premadeDeck = false; + GameObserver::EndInstance(); + game = NULL; + premadeDeck = false; - for (int i = 0; i < 2; i++){ - mPlayers[i] = NULL; - deck[i] = NULL; - } + for (int i = 0; i < 2; i++) + { + mPlayers[i] = NULL; + deck[i] = NULL; + } - SAFE_DELETE(credits); - SAFE_DELETE(rules); + SAFE_DELETE(credits); + SAFE_DELETE(rules); - SAFE_DELETE(menu); - SAFE_DELETE(opponentMenu); - SAFE_DELETE(deckmenu); + SAFE_DELETE(menu); + SAFE_DELETE(opponentMenu); + SAFE_DELETE(deckmenu); #ifdef TESTSUITE - SAFE_DELETE(testSuite); + SAFE_DELETE(testSuite); #endif } - //TODO Move This to utils or ResourceManager. Don't we have more generic functions that can do that? -bool GameStateDuel::MusicExist(string FileName){ - string filepath = JGE_GET_RES(resources.musicFile(FileName)); - std::ifstream file(filepath.c_str()); - if (file) { - file.close(); - return true; - } - else - return false; +bool GameStateDuel::MusicExist(string FileName) +{ + string filepath = JGE_GET_RES(resources.musicFile(FileName)); + std::ifstream file(filepath.c_str()); + if (file) + { + file.close(); + return true; + } + else + return false; } -void GameStateDuel::ensureOpponentMenu(){ - if (!opponentMenu){ - opponentMenu = NEW DeckMenu(DUEL_MENU_CHOOSE_OPPONENT, this, Fonts::OPTION_FONT, "Choose Your Opponent", MENU_FONT_SCALE); - opponentMenu->Add( MENUITEM_RANDOM_AI, "Random"); - if (options[Options::EVILTWIN_MODE_UNLOCKED].number) - opponentMenu->Add( MENUITEM_EVIL_TWIN, "Evil Twin", _("Can you play against yourself?").c_str()); - DeckManager * deckManager = DeckManager::GetInstance(); - vector opponentDeckList = fillDeckMenu( opponentMenu, JGE_GET_RES("ai/baka"), "ai_baka", mPlayers[0]); - deckManager->updateMetaDataList(&opponentDeckList, true); - opponentMenu->Add( MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str()); - opponentDeckList.clear(); - } +void GameStateDuel::ensureOpponentMenu() +{ + if (!opponentMenu) + { + opponentMenu = NEW DeckMenu(DUEL_MENU_CHOOSE_OPPONENT, this, Fonts::OPTION_FONT, "Choose Your Opponent", MENU_FONT_SCALE); + opponentMenu->Add(MENUITEM_RANDOM_AI, "Random"); + if (options[Options::EVILTWIN_MODE_UNLOCKED].number) + opponentMenu->Add(MENUITEM_EVIL_TWIN, "Evil Twin", _("Can you play against yourself?").c_str()); + DeckManager * deckManager = DeckManager::GetInstance(); + vector opponentDeckList = fillDeckMenu(opponentMenu, JGE_GET_RES("ai/baka"), "ai_baka", mPlayers[0]); + deckManager->updateMetaDataList(&opponentDeckList, true); + opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str()); + opponentDeckList.clear(); + } } void GameStateDuel::Update(float dt) { - switch (mGamePhase) + switch (mGamePhase) { case DUEL_STATE_ERROR_NO_DECK: - if (JGE_BTN_OK == mEngine->ReadButton()) - mParent->SetNextState(GAME_STATE_DECK_VIEWER); - break; + if (JGE_BTN_OK == mEngine->ReadButton()) + mParent->SetNextState(GAME_STATE_DECK_VIEWER); + break; case DUEL_STATE_CHOOSE_DECK1: - if (mParent->gameType == GAME_TYPE_MOMIR){ - rules = NEW Rules("momir.txt"); - mGamePhase = DUEL_STATE_PLAY; - } else if (mParent->gameType == GAME_TYPE_RANDOM1){ - rules = NEW Rules ("random1.txt"); - mGamePhase = DUEL_STATE_PLAY; - }else if (mParent->gameType == GAME_TYPE_RANDOM2) { - rules = NEW Rules ("random2.txt"); - mGamePhase = DUEL_STATE_PLAY; - } -#ifdef TESTSUITE - else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){ - if (testSuite && testSuite->loadNext()){ - rules = NEW Rules("testsuite.txt"); - loadTestSuitePlayers(); - mGamePhase = DUEL_STATE_PLAY; - testSuite->pregameTests(); - testSuite->initGame(); - }else{ - if (!game){ - mGamePhase = DUEL_STATE_ERROR; - }else{ - mGamePhase = DUEL_STATE_END; - } - } - } -#endif - else{ - if (!rules) rules = NEW Rules("mtg.txt"); - if (mParent->players[0] == PLAYER_TYPE_HUMAN) - deckmenu->Update(dt); - else{ - loadPlayer(0); - mGamePhase = DUEL_STATE_CHOOSE_DECK2; - } - } - break; - case DUEL_STATE_CHOOSE_DECK1_TO_2: - if (deckmenu->closed) mGamePhase = DUEL_STATE_CHOOSE_DECK2; - else deckmenu->Update(dt); - break; - case DUEL_STATE_CHOOSE_DECK2: - if (mParent->players[1] == PLAYER_TYPE_HUMAN) - deckmenu->Update(dt); - else{ - if (mParent->players[0] == PLAYER_TYPE_HUMAN){ - ensureOpponentMenu(); - opponentMenu->Update(dt); - } - else{ - loadPlayer(1); - mGamePhase = DUEL_STATE_PLAY; - } - } - break; - case DUEL_STATE_CHOOSE_DECK2_TO_PLAY: - if (mParent->players[1] == PLAYER_TYPE_HUMAN){ - if (deckmenu->closed) mGamePhase = DUEL_STATE_PLAY; - else deckmenu->Update(dt); - } - else{ - ensureOpponentMenu(); - if (opponentMenu->closed) mGamePhase = DUEL_STATE_PLAY; - else opponentMenu->Update(dt); - } - break; - case DUEL_STATE_PLAY: - if (!game){ - GameObserver::Init(mPlayers, 2); - game = GameObserver::GetInstance(); - game->startGame(rules); - if (mParent->gameType == GAME_TYPE_MOMIR){ - game->addObserver(NEW MTGMomirRule(-1, mParent->collection)); - } - - //start of in game music code - musictrack = ""; - //check opponent id and choose the music track based on it - if(OpponentsDeckid) { - char temp[4096]; - sprintf(temp,"ai_baka_music%i.mp3",OpponentsDeckid); - musictrack.assign(temp); - } - else if(mParent->gameType == GAME_TYPE_CLASSIC) - musictrack = "ai_baka_music.mp3"; - else if(mParent->gameType == GAME_TYPE_MOMIR) - musictrack = "ai_baka_music_momir.mp3"; - else if(mParent->gameType == GAME_TYPE_RANDOM1 || mParent->gameType == GAME_TYPE_RANDOM2) - musictrack = "ai_baka_music_random.mp3"; - - if(!MusicExist(musictrack)) - musictrack = "ai_baka_music.mp3"; - - GameApp::playMusic(musictrack); - } - game->Update(dt); - if (game->gameOver){ - if (game->players[1]->playMode != Player::MODE_TEST_SUITE) - credits->compute(game->players[0],game->players[1], mParent); - mGamePhase = DUEL_STATE_END; -#ifdef TESTSUITE - if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){ - if (testSuite->loadNext()){ - loadTestSuitePlayers(); + if (mParent->gameType == GAME_TYPE_MOMIR) + { + rules = NEW Rules("momir.txt"); mGamePhase = DUEL_STATE_PLAY; - testSuite->initGame(); - } - else - mGamePhase = DUEL_STATE_END; + } + else if (mParent->gameType == GAME_TYPE_RANDOM1) + { + rules = NEW Rules("random1.txt"); + mGamePhase = DUEL_STATE_PLAY; + } + else if (mParent->gameType == GAME_TYPE_RANDOM2) + { + rules = NEW Rules("random2.txt"); + mGamePhase = DUEL_STATE_PLAY; + } +#ifdef TESTSUITE + else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE) + { + if (testSuite && testSuite->loadNext()) + { + rules = NEW Rules("testsuite.txt"); + loadTestSuitePlayers(); + mGamePhase = DUEL_STATE_PLAY; + testSuite->pregameTests(); + testSuite->initGame(); + } + else + { + if (!game) + { + mGamePhase = DUEL_STATE_ERROR; + } + else + { + mGamePhase = DUEL_STATE_END; + } + } + } +#endif + else + { + if (!rules) + rules = NEW Rules("mtg.txt"); + if (mParent->players[0] == PLAYER_TYPE_HUMAN) + deckmenu->Update(dt); + else + { + loadPlayer(0); + mGamePhase = DUEL_STATE_CHOOSE_DECK2; + } + } + break; + case DUEL_STATE_CHOOSE_DECK1_TO_2: + if (deckmenu->closed) + mGamePhase = DUEL_STATE_CHOOSE_DECK2; + else + deckmenu->Update(dt); + break; + case DUEL_STATE_CHOOSE_DECK2: + if (mParent->players[1] == PLAYER_TYPE_HUMAN) + deckmenu->Update(dt); + else + { + if (mParent->players[0] == PLAYER_TYPE_HUMAN) + { + ensureOpponentMenu(); + opponentMenu->Update(dt); + } + else + { + loadPlayer(1); + mGamePhase = DUEL_STATE_PLAY; + } + } + break; + case DUEL_STATE_CHOOSE_DECK2_TO_PLAY: + if (mParent->players[1] == PLAYER_TYPE_HUMAN) + { + if (deckmenu->closed) + mGamePhase = DUEL_STATE_PLAY; + else + deckmenu->Update(dt); } else + { + ensureOpponentMenu(); + if (opponentMenu->closed) + mGamePhase = DUEL_STATE_PLAY; + else + opponentMenu->Update(dt); + } + break; + case DUEL_STATE_PLAY: + if (!game) + { + GameObserver::Init(mPlayers, 2); + game = GameObserver::GetInstance(); + game->startGame(rules); + if (mParent->gameType == GAME_TYPE_MOMIR) + { + game->addObserver(NEW MTGMomirRule(-1, mParent->collection)); + } + + //start of in game music code + musictrack = ""; + //check opponent id and choose the music track based on it + if (OpponentsDeckid) + { + char temp[4096]; + sprintf(temp, "ai_baka_music%i.mp3", OpponentsDeckid); + musictrack.assign(temp); + } + else if (mParent->gameType == GAME_TYPE_CLASSIC) + musictrack = "ai_baka_music.mp3"; + else if (mParent->gameType == GAME_TYPE_MOMIR) + musictrack = "ai_baka_music_momir.mp3"; + else if (mParent->gameType == GAME_TYPE_RANDOM1 || mParent->gameType == GAME_TYPE_RANDOM2) + musictrack = "ai_baka_music_random.mp3"; + + if (!MusicExist(musictrack)) + musictrack = "ai_baka_music.mp3"; + + GameApp::playMusic(musictrack); + } + game->Update(dt); + if (game->gameOver) + { + if (game->players[1]->playMode != Player::MODE_TEST_SUITE) + credits->compute(game->players[0], game->players[1], mParent); + mGamePhase = DUEL_STATE_END; +#ifdef TESTSUITE + if (mParent->players[1] == PLAYER_TYPE_TESTSUITE) + { + if (testSuite->loadNext()) + { + loadTestSuitePlayers(); + mGamePhase = DUEL_STATE_PLAY; + testSuite->initGame(); + } + else + mGamePhase = DUEL_STATE_END; + } + else #endif - if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU){ - End(); - Start(); - } - } - if (mEngine->GetButtonClick(JGE_BTN_MENU)) { - if (!menu) { - menu = NEW SimpleMenu(DUEL_MENU_GAME_MENU, this, Fonts::MENU_FONT, SCREEN_WIDTH/2-100, 25, game->players[1]->deckName.c_str()); - int cardsinhand = game->players[0]->game->hand->nb_cards; - - //almosthumane - mulligan - if ((game->turn < 1) && (cardsinhand != 0) - && game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN - && game->players[0]->game->inPlay->nb_cards == 0 - && game->players[0]->game->graveyard->nb_cards == 0 - && game->players[0]->game->exile->nb_cards == 0) //1st Play Check - //IF there was no play at the moment automatically mulligan - { - menu->Add( MENUITEM_MULLIGAN, "Mulligan"); - } - //END almosthumane - mulligan - menu->Add(MENUITEM_MAIN_MENU, "Back to main menu"); - menu->Add(MENUITEM_CANCEL, "Cancel"); + if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU) + { + End(); + Start(); + } } - mGamePhase = DUEL_STATE_MENU; - } - break; + if (mEngine->GetButtonClick(JGE_BTN_MENU)) + { + if (!menu) + { + menu = NEW SimpleMenu(DUEL_MENU_GAME_MENU, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 25, + game->players[1]->deckName.c_str()); + int cardsinhand = game->players[0]->game->hand->nb_cards; + + //almosthumane - mulligan + if ((game->turn < 1) && (cardsinhand != 0) && game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN + && game->players[0]->game->inPlay->nb_cards == 0 && game->players[0]->game->graveyard->nb_cards + == 0 && game->players[0]->game->exile->nb_cards == 0) //1st Play Check + //IF there was no play at the moment automatically mulligan + { + menu->Add(MENUITEM_MULLIGAN, "Mulligan"); + } + //END almosthumane - mulligan + menu->Add(MENUITEM_MAIN_MENU, "Back to main menu"); + menu->Add(MENUITEM_CANCEL, "Cancel"); + } + mGamePhase = DUEL_STATE_MENU; + } + break; case DUEL_STATE_MENU: - menu->Update(dt); - break; - case DUEL_STATE_CANCEL: - menu->Update(dt); - if (menu->closed) { - mGamePhase = DUEL_STATE_PLAY; - SAFE_DELETE(menu); - } - break; - case DUEL_STATE_BACK_TO_MAIN_MENU: - if(menu){ menu->Update(dt); - if (menu->closed) { - PlayerData * playerdata = NEW PlayerData(mParent->collection); - playerdata->taskList->passOneDay(); - playerdata->taskList->save(); - SAFE_DELETE(playerdata); - SAFE_DELETE(menu); + break; + case DUEL_STATE_CANCEL: + menu->Update(dt); + if (menu->closed) + { + mGamePhase = DUEL_STATE_PLAY; + SAFE_DELETE(menu); } - } - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - - break; + break; + case DUEL_STATE_BACK_TO_MAIN_MENU: + if (menu) + { + menu->Update(dt); + if (menu->closed) + { + PlayerData * playerdata = NEW PlayerData(mParent->collection); + playerdata->taskList->passOneDay(); + playerdata->taskList->save(); + SAFE_DELETE(playerdata); + SAFE_DELETE(menu); + } + } + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + + break; default: - if (JGE_BTN_OK == mEngine->ReadButton()) - mParent->SetNextState(GAME_STATE_MENU); + if (JGE_BTN_OK == mEngine->ReadButton()) + mParent->SetNextState(GAME_STATE_MENU); } } - void GameStateDuel::Render() { - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - JRenderer * r = JRenderer::GetInstance(); - r->ClearScreen(ARGB(0,0,0,0)); + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + JRenderer * r = JRenderer::GetInstance(); + r->ClearScreen(ARGB(0,0,0,0)); - if (game) - game->Render(); - - switch (mGamePhase) + if (game) + game->Render(); + + switch (mGamePhase) { case DUEL_STATE_END: - { + { JRenderer * r = JRenderer::GetInstance(); - r->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(200,0,0,0)); - credits->Render(); + r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); + credits->Render(); #ifdef TESTSUITE - if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){ - r->ClearScreen(ARGB(255,0,0,0)); - char buf[4096]; - int nbFailed = testSuite->nbFailed; - int nbTests = testSuite->nbTests; - if (!nbFailed){ - sprintf(buf, "All %i tests successful!", nbTests); - }else{ - sprintf(buf, "%i tests out of %i FAILED!", nbFailed, nbTests); - } - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(buf,0,SCREEN_HEIGHT/2); - nbFailed = testSuite->nbAIFailed; - nbTests = testSuite->nbAITests; - if (nbTests){ - if (!nbFailed){ - sprintf(buf, "AI Tests: All %i tests successful!", nbTests); - }else{ - sprintf(buf, "AI Tests: %i tests out of %i FAILED!", nbFailed, nbTests); + if (mParent->players[1] == PLAYER_TYPE_TESTSUITE) + { + r->ClearScreen(ARGB(255,0,0,0)); + char buf[4096]; + int nbFailed = testSuite->nbFailed; + int nbTests = testSuite->nbTests; + if (!nbFailed) + { + sprintf(buf, "All %i tests successful!", nbTests); + } + else + { + sprintf(buf, "%i tests out of %i FAILED!", nbFailed, nbTests); + } + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(buf,0,SCREEN_HEIGHT/2); + nbFailed = testSuite->nbAIFailed; + nbTests = testSuite->nbAITests; + if (nbTests) + { + if (!nbFailed) + { + sprintf(buf, "AI Tests: All %i tests successful!", nbTests); + } + else + { + sprintf(buf, "AI Tests: %i tests out of %i FAILED!", nbFailed, nbTests); + } + mFont->DrawString(buf,0,SCREEN_HEIGHT/2+20); } - mFont->DrawString(buf,0,SCREEN_HEIGHT/2+20); - } } #endif - break; - } + break; + } case DUEL_STATE_ERROR: - { - r->ClearScreen(ARGB(200,0,0,0)); - mFont->DrawString(_("AN ERROR OCCURRED, CHECK FILE NAMES").c_str(),0,SCREEN_HEIGHT/2); - break; - } + { + r->ClearScreen(ARGB(200,0,0,0)); + mFont->DrawString(_("AN ERROR OCCURRED, CHECK FILE NAMES").c_str(), 0, SCREEN_HEIGHT / 2); + break; + } case DUEL_STATE_CHOOSE_DECK1: case DUEL_STATE_CHOOSE_DECK1_TO_2: case DUEL_STATE_CHOOSE_DECK2: case DUEL_STATE_CHOOSE_DECK2_TO_PLAY: - if (mParent->gameType != GAME_TYPE_CLASSIC) - mFont->DrawString(_("LOADING DECKS").c_str(),0,SCREEN_HEIGHT/2); - else{ - if (opponentMenu) - opponentMenu->Render(); - else if (deckmenu) - deckmenu->Render(); + if (mParent->gameType != GAME_TYPE_CLASSIC) + mFont->DrawString(_("LOADING DECKS").c_str(), 0, SCREEN_HEIGHT / 2); + else + { + if (opponentMenu) + opponentMenu->Render(); + else if (deckmenu) + deckmenu->Render(); - } - break; + } + break; case DUEL_STATE_ERROR_NO_DECK: - mFont->DrawString(_("NO DECK AVAILABLE,").c_str(),0,SCREEN_HEIGHT/2); - mFont->DrawString(_("PRESS CIRCLE TO GO TO THE DECK EDITOR!").c_str(),0,SCREEN_HEIGHT/2 + 20); - break; + mFont->DrawString(_("NO DECK AVAILABLE,").c_str(), 0, SCREEN_HEIGHT / 2); + mFont->DrawString(_("PRESS CIRCLE TO GO TO THE DECK EDITOR!").c_str(), 0, SCREEN_HEIGHT / 2 + 20); + break; case DUEL_STATE_MENU: case DUEL_STATE_CANCEL: case DUEL_STATE_BACK_TO_MAIN_MENU: - if (game) { - r->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(100,0,0,0)); - char buffer[4096]; - sprintf(buffer,_("Turn:%i").c_str(),game->turn); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(buffer,SCREEN_WIDTH/2,0,JGETEXT_CENTER); - } - if(menu) - menu->Render(); - } + if (game) + { + r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(100,0,0,0)); + char buffer[4096]; + sprintf(buffer, _("Turn:%i").c_str(), game->turn); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(buffer, SCREEN_WIDTH / 2, 0, JGETEXT_CENTER); + } + if (menu) + menu->Render(); + } } -void GameStateDuel::ButtonPressed(int controllerId, int controlId) { - int deckNumber = controlId; - DeckManager * deckManager = DeckManager::GetInstance(); - int aiDeckSize = deckManager->getAIDeckOrderList()->size(); - switch (controllerId){ +void GameStateDuel::ButtonPressed(int controllerId, int controlId) +{ + int deckNumber = controlId; + DeckManager * deckManager = DeckManager::GetInstance(); + int aiDeckSize = deckManager->getAIDeckOrderList()->size(); + switch (controllerId) + { case DUEL_MENU_CHOOSE_OPPONENT: - { - switch(controlId){ - case MENUITEM_RANDOM_AI: - loadPlayer(1); - opponentMenu->Close(); - mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; + { + switch (controlId) + { + case MENUITEM_RANDOM_AI: + loadPlayer(1); + opponentMenu->Close(); + mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; break; - default: + default: // cancel option. return to player deck selection - if (controlId == MENUITEM_CANCEL) + if (controlId == MENUITEM_CANCEL) { opponentMenu->Close(); deckmenu->Close(); - mParent->SetNextState( DUEL_STATE_CHOOSE_DECK1 ); + mParent->SetNextState(DUEL_STATE_CHOOSE_DECK1); mGamePhase = DUEL_MENU_GAME_MENU; break; } - else if ( controlId != MENUITEM_EVIL_TWIN && aiDeckSize > 0) // evil twin - deckNumber = deckManager->getAIDeckOrderList()->at( controlId - 1 )->getDeckId(); + else if (controlId != MENUITEM_EVIL_TWIN && aiDeckSize > 0) // evil twin + deckNumber = deckManager->getAIDeckOrderList()->at(controlId - 1)->getDeckId(); - loadPlayer(1,deckNumber,1); - OpponentsDeckid=deckNumber; - opponentMenu->Close(); - mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; + loadPlayer(1, deckNumber, 1); + OpponentsDeckid = deckNumber; + opponentMenu->Close(); + mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; break; } break; - } + } case DUEL_MENU_CHOOSE_DECK: - { - if ( controlId == MENUITEM_RANDOM_PLAYER ) // Random Player Deck Selection + { + if (controlId == MENUITEM_RANDOM_PLAYER) // Random Player Deck Selection { - vector * playerDeckList = deckManager->getPlayerDeckOrderList(); - deckNumber = playerDeckList->at(WRand() * 1001 % (playerDeckList->size()) )->getDeckId(); - loadPlayer( 0, deckNumber ); - deckmenu->Close(); - mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; - break; + vector * playerDeckList = deckManager->getPlayerDeckOrderList(); + deckNumber = playerDeckList->at(WRand() * 1001 % (playerDeckList->size()))->getDeckId(); + loadPlayer(0, deckNumber); + deckmenu->Close(); + mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; + break; } - else if (controlId == MENUITEM_MAIN_MENU || controlId == MENUITEM_CANCEL ) // user clicked on "Cancel" - { - if (deckmenu) + else if (controlId == MENUITEM_MAIN_MENU || controlId == MENUITEM_CANCEL) // user clicked on "Cancel" + { + if (deckmenu) deckmenu->Close(); mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU; break; } - if (controlId < 0){ - mParent->SetNextState(GAME_STATE_DECK_VIEWER); - return; + if (controlId < 0) + { + mParent->SetNextState(GAME_STATE_DECK_VIEWER); + return; } - if (mGamePhase == DUEL_STATE_CHOOSE_DECK1){ - vector * playerDeck = deckManager->getPlayerDeckOrderList(); - if ( !premadeDeck && controlId > 0 ) - deckNumber = playerDeck->at( controlId - 1 )->getDeckId(); - loadPlayer(0,deckNumber); - deckmenu->Close(); - mGamePhase = DUEL_STATE_CHOOSE_DECK1_TO_2; - playerDeck = NULL; - }else{ - loadPlayer(1,controlId); - deckmenu->Close(); - mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; + if (mGamePhase == DUEL_STATE_CHOOSE_DECK1) + { + vector * playerDeck = deckManager->getPlayerDeckOrderList(); + if (!premadeDeck && controlId > 0) + deckNumber = playerDeck->at(controlId - 1)->getDeckId(); + loadPlayer(0, deckNumber); + deckmenu->Close(); + mGamePhase = DUEL_STATE_CHOOSE_DECK1_TO_2; + playerDeck = NULL; + } + else + { + loadPlayer(1, controlId); + deckmenu->Close(); + mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; } break; - } + } default: - { - switch (controlId) + { + switch (controlId) { - case MENUITEM_MAIN_MENU: - menu->Close(); - mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU; + case MENUITEM_MAIN_MENU: + menu->Close(); + mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU; break; - case MENUITEM_CANCEL: - menu->Close(); - mGamePhase = DUEL_STATE_CANCEL; - break; - case MENUITEM_MULLIGAN: - //almosthumane - mulligan - { - - int cardsinhand = game->players[0]->game->hand->nb_cards; - - for (int i = 0 ; i < cardsinhand; i ++) //Discard hand - game->currentPlayer->game->putInZone(game->currentPlayer->game->hand->cards[0],game->currentPlayer->game->hand ,game->currentPlayer->game->library); - - game->currentPlayer->game->library->shuffle(); //Shuffle - - for (int i = 0; i < (cardsinhand-1); i ++) game->draw(); //Draw hand with 1 less card penalty //almhum + case MENUITEM_CANCEL: menu->Close(); mGamePhase = DUEL_STATE_CANCEL; break; - } - //END almosthumane - mulligan - } + case MENUITEM_MULLIGAN: + //almosthumane - mulligan + { + + int cardsinhand = game->players[0]->game->hand->nb_cards; + + for (int i = 0; i < cardsinhand; i++) //Discard hand + game->currentPlayer->game->putInZone(game->currentPlayer->game->hand->cards[0], game->currentPlayer->game->hand, + game->currentPlayer->game->library); + + game->currentPlayer->game->library->shuffle(); //Shuffle + + for (int i = 0; i < (cardsinhand - 1); i++) + game->draw(); //Draw hand with 1 less card penalty //almhum + menu->Close(); + mGamePhase = DUEL_STATE_CANCEL; + break; + } + //END almosthumane - mulligan + } + } } - } } diff --git a/projects/mtg/src/GameStateMenu.cpp b/projects/mtg/src/GameStateMenu.cpp index a208ed921..d376a8353 100644 --- a/projects/mtg/src/GameStateMenu.cpp +++ b/projects/mtg/src/GameStateMenu.cpp @@ -25,9 +25,8 @@ static const char* GAME_VERSION = "WTH?! 0.13.1 - by wololo"; #define MIN_ANGLE_MULTIPLIER 0.4f static const float STEP_ANGLE_MULTIPLIER = 0.0002f; - enum ENUM_MENU_STATE_MAJOR - { +{ MENU_STATE_MAJOR_MAINMENU = 0x01, MENU_STATE_MAJOR_SUBMENU = 0x02, MENU_STATE_MAJOR_LOADING_MENU = 0x03, @@ -37,744 +36,837 @@ enum ENUM_MENU_STATE_MAJOR MENU_STATE_MAJOR_LANG = 0x07, MENU_STATE_MAJOR = 0xFF - }; +}; enum ENUM_MENU_STATE_MINOR - { +{ MENU_STATE_MINOR_NONE = 0, MENU_STATE_MINOR_SUBMENU_CLOSING = 0x100, MENU_STATE_MINOR_FADEIN = 0x200, MENU_STATE_MINOR = 0xF00 - }; - +}; enum { - SUBMENUITEM_CANCEL = kCancelMenuID, - MENUITEM_PLAY, - MENUITEM_DECKEDITOR, - MENUITEM_SHOP, - MENUITEM_OPTIONS, - MENUITEM_EXIT, - SUBMENUITEM_1PLAYER, - SUBMENUITEM_2PLAYER, - SUBMENUITEM_DEMO, - SUBMENUITEM_TESTSUITE, - SUBMENUITEM_MOMIR, - SUBMENUITEM_CLASSIC, - SUBMENUITEM_RANDOM1, - SUBMENUITEM_RANDOM2, - SUBMENUITEM_STORY, + SUBMENUITEM_CANCEL = kCancelMenuID, + MENUITEM_PLAY, + MENUITEM_DECKEDITOR, + MENUITEM_SHOP, + MENUITEM_OPTIONS, + MENUITEM_EXIT, + SUBMENUITEM_1PLAYER, + SUBMENUITEM_2PLAYER, + SUBMENUITEM_DEMO, + SUBMENUITEM_TESTSUITE, + SUBMENUITEM_MOMIR, + SUBMENUITEM_CLASSIC, + SUBMENUITEM_RANDOM1, + SUBMENUITEM_RANDOM2, + SUBMENUITEM_STORY, }; - -GameStateMenu::GameStateMenu(GameApp* parent): GameState(parent) +GameStateMenu::GameStateMenu(GameApp* parent) : + GameState(parent) { - mGuiController = NULL; - subMenuController = NULL; - gameTypeMenu = NULL; - mSplash = NULL; - mBg = NULL; - //bgMusic = NULL; - timeIndex = 0; - angleMultiplier = MIN_ANGLE_MULTIPLIER; - yW = 55; - mVolume = 0; - scroller = NULL; - langChoices = false; - primitivesLoadCounter = -1; + mGuiController = NULL; + subMenuController = NULL; + gameTypeMenu = NULL; + mSplash = NULL; + mBg = NULL; + //bgMusic = NULL; + timeIndex = 0; + angleMultiplier = MIN_ANGLE_MULTIPLIER; + yW = 55; + mVolume = 0; + scroller = NULL; + langChoices = false; + primitivesLoadCounter = -1; } -GameStateMenu::~GameStateMenu() {} - +GameStateMenu::~GameStateMenu() +{ +} void GameStateMenu::Create() { - mDip = NULL; - mGuiController = NULL; - mReadConf = 0; - mCurrentSetName[0] = 0; + mDip = NULL; + mGuiController = NULL; + mReadConf = 0; + mCurrentSetName[0] = 0; - //load all the icon images. Menu icons are managed, so we can do this here. - int n = 0; - char buf[512]; + //load all the icon images. Menu icons are managed, so we can do this here. + int n = 0; + char buf[512]; - for (int i=0;i<5;i++){ - for (int j=0;j<2;j++){ - sprintf(buf,"menuicons%d%d",i,j); - mIcons[n] = resources.RetrieveQuad("menuicons.png", 2 + i * 36.0f, 2.0f + j * 36.0f, 32.0f, 32.0f, buf); - if(mIcons[n]) mIcons[n]->SetHotSpot(16,16); - n++; - } - } + for (int i = 0; i < 5; i++) + { + for (int j = 0; j < 2; j++) + { + sprintf(buf, "menuicons%d%d", i, j); + mIcons[n] = resources.RetrieveQuad("menuicons.png", 2 + i * 36.0f, 2.0f + j * 36.0f, 32.0f, 32.0f, buf); + if (mIcons[n]) + mIcons[n]->SetHotSpot(16, 16); + n++; + } + } - currentState = MENU_STATE_MAJOR_LOADING_CARDS; - bool langChosen = false; - string lang = options[Options::LANG].str; - if (lang.size()){ - lang = JGE_GET_RES("lang/") + lang + ".txt"; - if (fileExists(lang.c_str())) langChosen = true; - } - if (!langChosen){ - currentState = MENU_STATE_MAJOR_LANG | MENU_STATE_MINOR_NONE; - } - scroller = NEW TextScroller(Fonts::MAIN_FONT, SCREEN_WIDTH/2 - 90 , SCREEN_HEIGHT-17,180); - scrollerSet = 0; + currentState = MENU_STATE_MAJOR_LOADING_CARDS; + bool langChosen = false; + string lang = options[Options::LANG].str; + if (lang.size()) + { + lang = JGE_GET_RES("lang/") + lang + ".txt"; + if (fileExists(lang.c_str())) + langChosen = true; + } + if (!langChosen) + { + currentState = MENU_STATE_MAJOR_LANG | MENU_STATE_MINOR_NONE; + } + scroller = NEW TextScroller(Fonts::MAIN_FONT, SCREEN_WIDTH / 2 - 90, SCREEN_HEIGHT - 17, 180); + scrollerSet = 0; - splashTex = NULL; - mSplash = NULL; + splashTex = NULL; + mSplash = NULL; } - - void GameStateMenu::Destroy() { - SAFE_DELETE(mGuiController); - SAFE_DELETE(subMenuController); - SAFE_DELETE(gameTypeMenu); - resources.Release(bgTexture); - SAFE_DELETE(scroller); + SAFE_DELETE(mGuiController); + SAFE_DELETE(subMenuController); + SAFE_DELETE(gameTypeMenu); + resources.Release(bgTexture); + SAFE_DELETE(scroller); } -void GameStateMenu::Start(){ - LOG("GameStateMenu::Start"); - JRenderer::GetInstance()->EnableVSync(true); - subMenuController = NULL; - SAFE_DELETE(mGuiController); - - GameApp::playMusic("Track0.mp3"); +void GameStateMenu::Start() +{ + LOG("GameStateMenu::Start"); + JRenderer::GetInstance()->EnableVSync(true); + subMenuController = NULL; + SAFE_DELETE(mGuiController); - hasChosenGameType = 0; - mParent->gameType = GAME_TYPE_CLASSIC; + GameApp::playMusic("Track0.mp3"); - /* - if (options[Options::MOMIR_MODE_UNLOCKED].number) hasChosenGameType = 0; - if (options[Options::RANDOMDECK_MODE_UNLOCKED].number) hasChosenGameType = 0; - */ - bgTexture = resources.RetrieveTexture("menutitle.png", RETRIEVE_LOCK); - mBg = resources.RetrieveQuad("menutitle.png", 0, 0, 256, 166); // Create background quad for rendering. + hasChosenGameType = 0; + mParent->gameType = GAME_TYPE_CLASSIC; - if (mBg) mBg->SetHotSpot(128,50); + /* + if (options[Options::MOMIR_MODE_UNLOCKED].number) hasChosenGameType = 0; + if (options[Options::RANDOMDECK_MODE_UNLOCKED].number) hasChosenGameType = 0; + */ + bgTexture = resources.RetrieveTexture("menutitle.png", RETRIEVE_LOCK); + mBg = resources.RetrieveQuad("menutitle.png", 0, 0, 256, 166); // Create background quad for rendering. - if (MENU_STATE_MAJOR_MAINMENU == currentState) - currentState = currentState | MENU_STATE_MINOR_FADEIN; + if (mBg) + mBg->SetHotSpot(128, 50); - wallpaper = ""; + if (MENU_STATE_MAJOR_MAINMENU == currentState) + currentState = currentState | MENU_STATE_MINOR_FADEIN; + + wallpaper = ""; } -void GameStateMenu::genNbCardsStr(){ - //How many cards total ? - PlayerData * playerdata = NEW PlayerData(mParent->collection); - if(playerdata && !options[Options::ACTIVE_PROFILE].isDefault()) - sprintf(nbcardsStr, _("%s: %i cards (%i) (%i unique)").c_str(), options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards(), mParent->collection->primitives.size()); - else - sprintf(nbcardsStr, _("%i cards (%i unique)").c_str(), mParent->collection->totalCards(), mParent->collection->primitives.size()); +void GameStateMenu::genNbCardsStr() +{ + //How many cards total ? + PlayerData * playerdata = NEW PlayerData(mParent->collection); + if (playerdata && !options[Options::ACTIVE_PROFILE].isDefault()) + sprintf(nbcardsStr, _("%s: %i cards (%i) (%i unique)").c_str(), options[Options::ACTIVE_PROFILE].str.c_str(), + playerdata->collection->totalCards(), mParent->collection->totalCards(), + mParent->collection->primitives.size()); + else + sprintf(nbcardsStr, _("%i cards (%i unique)").c_str(), mParent->collection->totalCards(), + mParent->collection->primitives.size()); - SAFE_DELETE(playerdata); + SAFE_DELETE(playerdata); } -void GameStateMenu::fillScroller(){ - scroller->Reset(); - char buffer[4096]; - char buff2[512]; +void GameStateMenu::fillScroller() +{ + scroller->Reset(); + char buffer[4096]; + char buff2[512]; - DeckStats * stats = DeckStats::GetInstance(); - int totalGames = 0; + DeckStats * stats = DeckStats::GetInstance(); + int totalGames = 0; - for (int j=1; j<6; j++){ - sprintf(buffer, "stats/player_deck%i.txt",j); - string deckstats = options.profileFile(buffer); - if(fileExists(deckstats.c_str())){ - stats->load(deckstats.c_str()); - int percentVictories = stats->percentVictories(); + for (int j = 1; j < 6; j++) + { + sprintf(buffer, "stats/player_deck%i.txt", j); + string deckstats = options.profileFile(buffer); + if (fileExists(deckstats.c_str())) + { + stats->load(deckstats.c_str()); + int percentVictories = stats->percentVictories(); - sprintf(buff2, _("You have a %i%% victory ratio with Deck%i").c_str(),percentVictories,j); - scroller->Add(buff2); - int nbGames = stats->nbGames(); - totalGames+= nbGames; - sprintf(buff2, _("You have played %i games with Deck%i").c_str(),nbGames,j); - scroller->Add(buff2); + sprintf(buff2, _("You have a %i%% victory ratio with Deck%i").c_str(), percentVictories, j); + scroller->Add(buff2); + int nbGames = stats->nbGames(); + totalGames += nbGames; + sprintf(buff2, _("You have played %i games with Deck%i").c_str(), nbGames, j); + scroller->Add(buff2); + } } - } - if (totalGames){ - sprintf(buff2, _("You have played a total of %i games").c_str(),totalGames); - scroller->Add(buff2); - } - - if (!options[Options::DIFFICULTY_MODE_UNLOCKED].number) - scroller->Add(_("Unlock the difficult mode for more challenging duels!")); - if (!options[Options::MOMIR_MODE_UNLOCKED].number) - scroller->Add(_("Interested in playing Momir Basic? You'll have to unlock it first :)")); - if (!options[Options::RANDOMDECK_MODE_UNLOCKED].number) - scroller->Add(_("You haven't unlocked the random deck mode yet")); - if (!options[Options::EVILTWIN_MODE_UNLOCKED].number) - scroller->Add(_("You haven't unlocked the evil twin mode yet")); - if (!options[Options::RANDOMDECK_MODE_UNLOCKED].number) - scroller->Add(_("You haven't unlocked the random deck mode yet")); - if (!options[Options::EVILTWIN_MODE_UNLOCKED].number) - scroller->Add(_("You haven't unlocked the evil twin mode yet")); - - //Unlocked sets - int nbunlocked = 0; - for (int i = 0; i < setlist.size(); i++){ - if (1 == options[Options::optionSet(i)].number) nbunlocked++; - } - sprintf(buff2, _("You have unlocked %i expansions out of %i").c_str(),nbunlocked, setlist.size()); - scroller->Add(buff2); - - PlayerData * playerdata = NEW PlayerData(mParent->collection); - int totalCards = playerdata->collection->totalCards(); - if (totalCards){ - sprintf(buff2, _("You have a total of %i cards in your collection").c_str(),totalCards); - scroller->Add(buff2); - - int estimatedValue = playerdata->collection->totalPrice(); - sprintf(buff2, _("The shopkeeper would buy your entire collection for around %i credits").c_str(),estimatedValue/2); - scroller->Add(buff2); - - sprintf(buff2, _("The cards in your collection have an average value of %i credits").c_str(),estimatedValue/totalCards); - scroller->Add(buff2); - } - - sprintf(buff2, _("You currently have %i credits").c_str(),playerdata->credits); - SAFE_DELETE(playerdata); - scroller->Add(buff2); - - scroller->Add(_("More cards and mods at http://wololo.net/wagic")); - - scroller->Add(_("These stats will be updated next time you run Wagic")); - - scrollerSet = 1; - scroller->setRandom(); -} -void GameStateMenu::resetDirectory(){ - if(mDip != NULL) { - closedir(mDip); - mDip = NULL; - } -} -int GameStateMenu::nextDirectory(const char * root, const char * file){ - int found = 0; - if (!mDip){ - mDip = opendir(root); - } - - while (!found && (mDit = readdir(mDip))){ - sprintf(mCurrentSetFileName, "%s/%s/%s", root, mDit->d_name, file); - std::ifstream file(mCurrentSetFileName); - if(file){ - sprintf(mCurrentSetName, "%s", mDit->d_name); - file.close(); - found = 1; + if (totalGames) + { + sprintf(buff2, _("You have played a total of %i games").c_str(), totalGames); + scroller->Add(buff2); } - } - if (!found) resetDirectory(); - return found; + + if (!options[Options::DIFFICULTY_MODE_UNLOCKED].number) + scroller->Add(_("Unlock the difficult mode for more challenging duels!")); + if (!options[Options::MOMIR_MODE_UNLOCKED].number) + scroller->Add(_("Interested in playing Momir Basic? You'll have to unlock it first :)")); + if (!options[Options::RANDOMDECK_MODE_UNLOCKED].number) + scroller->Add(_("You haven't unlocked the random deck mode yet")); + if (!options[Options::EVILTWIN_MODE_UNLOCKED].number) + scroller->Add(_("You haven't unlocked the evil twin mode yet")); + if (!options[Options::RANDOMDECK_MODE_UNLOCKED].number) + scroller->Add(_("You haven't unlocked the random deck mode yet")); + if (!options[Options::EVILTWIN_MODE_UNLOCKED].number) + scroller->Add(_("You haven't unlocked the evil twin mode yet")); + + //Unlocked sets + int nbunlocked = 0; + for (int i = 0; i < setlist.size(); i++) + { + if (1 == options[Options::optionSet(i)].number) + nbunlocked++; + } + sprintf(buff2, _("You have unlocked %i expansions out of %i").c_str(), nbunlocked, setlist.size()); + scroller->Add(buff2); + + PlayerData * playerdata = NEW PlayerData(mParent->collection); + int totalCards = playerdata->collection->totalCards(); + if (totalCards) + { + sprintf(buff2, _("You have a total of %i cards in your collection").c_str(), totalCards); + scroller->Add(buff2); + + int estimatedValue = playerdata->collection->totalPrice(); + sprintf(buff2, _("The shopkeeper would buy your entire collection for around %i credits").c_str(), estimatedValue / 2); + scroller->Add(buff2); + + sprintf(buff2, _("The cards in your collection have an average value of %i credits").c_str(), estimatedValue / totalCards); + scroller->Add(buff2); + } + + sprintf(buff2, _("You currently have %i credits").c_str(), playerdata->credits); + SAFE_DELETE(playerdata); + scroller->Add(buff2); + + scroller->Add(_("More cards and mods at http://wololo.net/wagic")); + + scroller->Add(_("These stats will be updated next time you run Wagic")); + + scrollerSet = 1; + scroller->setRandom(); +} +void GameStateMenu::resetDirectory() +{ + if (mDip != NULL) + { + closedir(mDip); + mDip = NULL; + } +} +int GameStateMenu::nextDirectory(const char * root, const char * file) +{ + int found = 0; + if (!mDip) + { + mDip = opendir(root); + } + + while (!found && (mDit = readdir(mDip))) + { + sprintf(mCurrentSetFileName, "%s/%s/%s", root, mDit->d_name, file); + std::ifstream file(mCurrentSetFileName); + if (file) + { + sprintf(mCurrentSetName, "%s", mDit->d_name); + file.close(); + found = 1; + } + } + if (!found) + resetDirectory(); + return found; } void GameStateMenu::End() { - JRenderer::GetInstance()->EnableVSync(false); - - resources.Release(bgTexture); - SAFE_DELETE(mGuiController); + JRenderer::GetInstance()->EnableVSync(false); + + resources.Release(bgTexture); + SAFE_DELETE(mGuiController); } -string GameStateMenu::loadRandomWallpaper() { - if (wallpaper.size()) +string GameStateMenu::loadRandomWallpaper() +{ + if (wallpaper.size()) + return wallpaper; + + vector wallpapers; + std::ifstream file(JGE_GET_RES("graphics/wallpapers.txt").c_str()); + + if (!file) + return wallpaper; + + string s; + while (std::getline(file, s)) + { + if (!s.size()) + continue; + if (s[s.size() - 1] == '\r') + s.erase(s.size() - 1); //Handle DOS files + wallpapers.push_back(s); + } + + int rnd = rand() % (wallpapers.size()); + wallpaper = wallpapers[rnd]; return wallpaper; - vector wallpapers; - std::ifstream file(JGE_GET_RES("graphics/wallpapers.txt").c_str()); - - if (!file) return wallpaper; - - string s; - while (std::getline(file,s)) { - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - wallpapers.push_back(s); - } - - int rnd = rand() % (wallpapers.size()); - wallpaper = wallpapers[rnd]; - return wallpaper; - } -string GameStateMenu::getLang(string s){ - if (!s.size()) return ""; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files +string GameStateMenu::getLang(string s) +{ + if (!s.size()) + return ""; + if (s[s.size() - 1] == '\r') + s.erase(s.size() - 1); //Handle DOS files size_t found = s.find("#LANG:"); - if (found != 0) return ""; + if (found != 0) + return ""; return s.substr(6); } -void GameStateMenu::setLang(int id){ - options[Options::LANG].str = langs[id-1]; - options.save(); +void GameStateMenu::setLang(int id) +{ + options[Options::LANG].str = langs[id - 1]; + options.save(); } -void GameStateMenu::loadLangMenu(){ - LOG("GameStateMenu::loadLangMenu"); - subMenuController = NEW SimpleMenu( MENU_LANGUAGE_SELECTION, this, Fonts::MENU_FONT, 150,60); - if (!subMenuController) return; - resetDirectory(); - if (!mDip){ - mDip = opendir(JGE_GET_RES("lang").c_str()); - } +void GameStateMenu::loadLangMenu() +{ + LOG("GameStateMenu::loadLangMenu"); + subMenuController = NEW SimpleMenu(MENU_LANGUAGE_SELECTION, this, Fonts::MENU_FONT, 150, 60); + if (!subMenuController) + return; + resetDirectory(); + if (!mDip) + { + mDip = opendir(JGE_GET_RES("lang").c_str()); + } - while ((mDit = readdir(mDip))){ - string filename = JGE_GET_RES("lang/"); - filename += mDit->d_name; - std::ifstream file(filename.c_str()); - string s; - string lang; - if(file){ - if(std::getline(file,s)){ - lang = getLang(s); - } - file.close(); + while ((mDit = readdir(mDip))) + { + string filename = JGE_GET_RES("lang/"); + filename += mDit->d_name; + std::ifstream file(filename.c_str()); + string s; + string lang; + if (file) + { + if (std::getline(file, s)) + { + lang = getLang(s); + } + file.close(); + } + if (lang.size()) + { + langChoices = true; + string filen = mDit->d_name; + langs.push_back(filen.substr(0, filen.size() - 4)); + subMenuController->Add(langs.size(), lang.c_str()); + } } - if (lang.size()){ - langChoices = true; - string filen = mDit->d_name; - langs.push_back(filen.substr(0,filen.size()-4)); - subMenuController->Add(langs.size(),lang.c_str()); - } - } - resetDirectory(); - LOG("GameStateMenu::loadLangMenu - Done"); + resetDirectory(); + LOG("GameStateMenu::loadLangMenu - Done"); } -void GameStateMenu::listPrimitives(){ - LOG("GameStateMenu::listPrimitives"); - resetDirectory(); - if (!mDip){ - mDip = opendir(JGE_GET_RES("sets/primitives/").c_str()); - } +void GameStateMenu::listPrimitives() +{ + LOG("GameStateMenu::listPrimitives"); + resetDirectory(); + if (!mDip) + { + mDip = opendir(JGE_GET_RES("sets/primitives/").c_str()); + } - while ((mDit = readdir(mDip))){ - string filename = JGE_GET_RES("sets/primitives/"); - filename += mDit->d_name; - std::ifstream file(filename.c_str()); - if(!file) continue; - file.close(); - primitives.push_back(filename); - } - resetDirectory(); - primitivesLoadCounter = 0; - LOG("GameStateMenu::listPrimitives - Done"); + while ((mDit = readdir(mDip))) + { + string filename = JGE_GET_RES("sets/primitives/"); + filename += mDit->d_name; + std::ifstream file(filename.c_str()); + if (!file) + continue; + file.close(); + primitives.push_back(filename); + } + resetDirectory(); + primitivesLoadCounter = 0; + LOG("GameStateMenu::listPrimitives - Done"); } -void GameStateMenu::ensureMGuiController(){ - if (!mGuiController) { - mGuiController = NEW JGuiController(100, this); - if (mGuiController) { - WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); - mFont->SetColor(ARGB(255,255,255,255)); - mGuiController->Add(NEW MenuItem(MENUITEM_PLAY, mFont, "Play", 80, 50 + SCREEN_HEIGHT/2, mIcons[8], mIcons[9],"particle1.psi",resources.GetQuad("particles"), true)); - mGuiController->Add(NEW MenuItem(MENUITEM_DECKEDITOR, mFont, "Deck Editor", 160, 50 + SCREEN_HEIGHT/2, mIcons[2], mIcons[3],"particle2.psi",resources.GetQuad("particles"))); - mGuiController->Add(NEW MenuItem(MENUITEM_SHOP, mFont, "Shop", 240, 50 + SCREEN_HEIGHT/2, mIcons[0], mIcons[1],"particle3.psi",resources.GetQuad("particles"))); - mGuiController->Add(NEW MenuItem(MENUITEM_OPTIONS, mFont, "Options", 320, 50 + SCREEN_HEIGHT/2, mIcons[6], mIcons[7],"particle4.psi",resources.GetQuad("particles"))); - mGuiController->Add(NEW MenuItem(MENUITEM_EXIT, mFont, "Exit", 400, 50 + SCREEN_HEIGHT/2, mIcons[4], mIcons[5],"particle5.psi",resources.GetQuad("particles"))); +void GameStateMenu::ensureMGuiController() +{ + if (!mGuiController) + { + mGuiController = NEW JGuiController(100, this); + if (mGuiController) + { + WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); + mFont->SetColor(ARGB(255,255,255,255)); + mGuiController->Add(NEW MenuItem(MENUITEM_PLAY, mFont, "Play", 80, 50 + SCREEN_HEIGHT / 2, mIcons[8], mIcons[9], + "particle1.psi", resources.GetQuad("particles"), true)); + mGuiController->Add(NEW MenuItem(MENUITEM_DECKEDITOR, mFont, "Deck Editor", 160, 50 + SCREEN_HEIGHT / 2, mIcons[2], + mIcons[3], "particle2.psi", resources.GetQuad("particles"))); + mGuiController->Add(NEW MenuItem(MENUITEM_SHOP, mFont, "Shop", 240, 50 + SCREEN_HEIGHT / 2, mIcons[0], mIcons[1], + "particle3.psi", resources.GetQuad("particles"))); + mGuiController->Add(NEW MenuItem(MENUITEM_OPTIONS, mFont, "Options", 320, 50 + SCREEN_HEIGHT / 2, mIcons[6], mIcons[7], + "particle4.psi", resources.GetQuad("particles"))); + mGuiController->Add(NEW MenuItem(MENUITEM_EXIT, mFont, "Exit", 400, 50 + SCREEN_HEIGHT / 2, mIcons[4], mIcons[5], + "particle5.psi", resources.GetQuad("particles"))); + } } - } } void GameStateMenu::Update(float dt) { - timeIndex += dt * 2; - switch (MENU_STATE_MAJOR & currentState) { - case MENU_STATE_MAJOR_LANG : - if (MENU_STATE_MINOR_NONE == (currentState & MENU_STATE_MINOR)) { - if (!subMenuController) loadLangMenu(); + timeIndex += dt * 2; + switch (MENU_STATE_MAJOR & currentState) + { + case MENU_STATE_MAJOR_LANG: + if (MENU_STATE_MINOR_NONE == (currentState & MENU_STATE_MINOR)) + { + if (!subMenuController) + loadLangMenu(); } - if(!langChoices){ - currentState = MENU_STATE_MAJOR_LOADING_CARDS; - SAFE_DELETE(subMenuController); + if (!langChoices) + { + currentState = MENU_STATE_MAJOR_LOADING_CARDS; + SAFE_DELETE(subMenuController); } else - subMenuController->Update(dt); - break; - case MENU_STATE_MAJOR_LOADING_CARDS : - if (primitivesLoadCounter == -1){ - listPrimitives(); - Translator::GetInstance()->init(); - } - if (primitivesLoadCounter < (int)(primitives.size())){ - mParent->collection->load(primitives[primitivesLoadCounter].c_str() ); - primitivesLoadCounter++; + subMenuController->Update(dt); break; - } - primitivesLoadCounter = primitives.size() + 1; - if (mReadConf){ - mParent->collection->load(mCurrentSetFileName, mCurrentSetName); - }else{ - mReadConf = 1; - } - if (!nextDirectory(JGE_GET_RES("sets/").c_str(),"_cards.dat")){ - //Remove temporary translations - Translator::GetInstance()->tempValues.clear(); - - DebugTrace(std::endl << "==" << std::endl << - "Total MTGCards: " << mParent->collection->collection.size() << std::endl << - "Total CardPrimitives: " << mParent->collection->primitives.size() << std::endl << "=="); - - //Force default, if necessary. - if(options[Options::ACTIVE_PROFILE].str == "") - options[Options::ACTIVE_PROFILE].str = "Default"; - - //Release splash texture - resources.Release(splashTex); - splashTex = NULL; - mSplash = NULL; - - //check for deleted collection / first-timer - std::ifstream file(options.profileFile(PLAYER_COLLECTION).c_str()); - if(file){ - file.close(); - currentState = MENU_STATE_MAJOR_MAINMENU; - }else{ - currentState = MENU_STATE_MAJOR_FIRST_TIME; + case MENU_STATE_MAJOR_LOADING_CARDS: + if (primitivesLoadCounter == -1) + { + listPrimitives(); + Translator::GetInstance()->init(); } + if (primitivesLoadCounter < (int) (primitives.size())) + { + mParent->collection->load(primitives[primitivesLoadCounter].c_str()); + primitivesLoadCounter++; + break; + } + primitivesLoadCounter = primitives.size() + 1; + if (mReadConf) + { + mParent->collection->load(mCurrentSetFileName, mCurrentSetName); + } + else + { + mReadConf = 1; + } + if (!nextDirectory(JGE_GET_RES("sets/").c_str(), "_cards.dat")) + { + //Remove temporary translations + Translator::GetInstance()->tempValues.clear(); - //Reload list of unlocked sets, now that we know about the sets. - options.reloadProfile(false); - genNbCardsStr(); - resetDirectory(); - //All major things have been loaded, resize the cache to use it as efficiently as possible - resources.ResetCacheLimits(); - } - break; - case MENU_STATE_MAJOR_FIRST_TIME : - currentState &= MENU_STATE_MAJOR_MAINMENU; - options.reloadProfile(); //Handles building a new deck, if needed. - break; - case MENU_STATE_MAJOR_MAINMENU : - if (!scrollerSet) fillScroller(); - ensureMGuiController(); - if (mGuiController) - mGuiController->Update(dt); - if(mEngine->GetButtonState(JGE_BTN_NEXT)) //Hook for GameStateAward state - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_AWARDS); //TODO: A slide transition would be nice. - break; - case MENU_STATE_MAJOR_SUBMENU : - if (subMenuController) - subMenuController->Update(dt); - ensureMGuiController(); - mGuiController->Update(dt); - break; - case MENU_STATE_MAJOR_DUEL : - if (MENU_STATE_MINOR_NONE == (currentState & MENU_STATE_MINOR)) { - if (!hasChosenGameType){ - currentState = MENU_STATE_MAJOR_SUBMENU; - subMenuController = NEW SimpleMenu( MENU_FIRST_DUEL_SUBMENU, this, Fonts::MENU_FONT, 150,60); - if (subMenuController){ - subMenuController->Add(SUBMENUITEM_CLASSIC,"Classic"); - if (options[Options::MOMIR_MODE_UNLOCKED].number) - subMenuController->Add(SUBMENUITEM_MOMIR, "Momir Basic"); - if (options[Options::RANDOMDECK_MODE_UNLOCKED].number){ - subMenuController->Add(SUBMENUITEM_RANDOM1, "Random 1 Color"); - subMenuController->Add(SUBMENUITEM_RANDOM2, "Random 2 Colors"); - } - subMenuController->Add(SUBMENUITEM_STORY,"Story"); - subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel"); - } - }else{ - if (mParent->gameType == GAME_TYPE_STORY ) - mParent->DoTransition(TRANSITION_FADE, GAME_STATE_STORY); - else - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_DUEL); - currentState = MENU_STATE_MAJOR_MAINMENU; - } - } - } + DebugTrace(std::endl << "==" << std::endl << + "Total MTGCards: " << mParent->collection->collection.size() << std::endl << + "Total CardPrimitives: " << mParent->collection->primitives.size() << std::endl << "=="); - switch (MENU_STATE_MINOR & currentState){ - case MENU_STATE_MINOR_SUBMENU_CLOSING : - if (!subMenuController){ //http://code.google.com/p/wagic/issues/detail?id=379 - currentState &= ~MENU_STATE_MINOR_SUBMENU_CLOSING; + //Force default, if necessary. + if (options[Options::ACTIVE_PROFILE].str == "") + options[Options::ACTIVE_PROFILE].str = "Default"; + + //Release splash texture + resources.Release(splashTex); + splashTex = NULL; + mSplash = NULL; + + //check for deleted collection / first-timer + std::ifstream file(options.profileFile(PLAYER_COLLECTION).c_str()); + if (file) + { + file.close(); + currentState = MENU_STATE_MAJOR_MAINMENU; + } + else + { + currentState = MENU_STATE_MAJOR_FIRST_TIME; + } + + //Reload list of unlocked sets, now that we know about the sets. + options.reloadProfile(false); + genNbCardsStr(); + resetDirectory(); + //All major things have been loaded, resize the cache to use it as efficiently as possible + resources.ResetCacheLimits(); + } break; - } - if (subMenuController->closed) { - SAFE_DELETE(subMenuController); - currentState &= ~MENU_STATE_MINOR_SUBMENU_CLOSING; - } else - subMenuController->Update(dt); - break; - case MENU_STATE_MINOR_NONE : - ;// Nothing to do. + case MENU_STATE_MAJOR_FIRST_TIME: + currentState &= MENU_STATE_MAJOR_MAINMENU; + options.reloadProfile(); //Handles building a new deck, if needed. + break; + case MENU_STATE_MAJOR_MAINMENU: + if (!scrollerSet) + fillScroller(); + ensureMGuiController(); + if (mGuiController) + mGuiController->Update(dt); + if (mEngine->GetButtonState(JGE_BTN_NEXT)) //Hook for GameStateAward state + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_AWARDS); //TODO: A slide transition would be nice. + break; + case MENU_STATE_MAJOR_SUBMENU: + if (subMenuController) + subMenuController->Update(dt); + ensureMGuiController(); + mGuiController->Update(dt); + break; + case MENU_STATE_MAJOR_DUEL: + if (MENU_STATE_MINOR_NONE == (currentState & MENU_STATE_MINOR)) + { + if (!hasChosenGameType) + { + currentState = MENU_STATE_MAJOR_SUBMENU; + subMenuController = NEW SimpleMenu(MENU_FIRST_DUEL_SUBMENU, this, Fonts::MENU_FONT, 150, 60); + if (subMenuController) + { + subMenuController->Add(SUBMENUITEM_CLASSIC, "Classic"); + if (options[Options::MOMIR_MODE_UNLOCKED].number) + subMenuController->Add(SUBMENUITEM_MOMIR, "Momir Basic"); + if (options[Options::RANDOMDECK_MODE_UNLOCKED].number) + { + subMenuController->Add(SUBMENUITEM_RANDOM1, "Random 1 Color"); + subMenuController->Add(SUBMENUITEM_RANDOM2, "Random 2 Colors"); + } + subMenuController->Add(SUBMENUITEM_STORY, "Story"); + subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel"); + } + } + else + { + if (mParent->gameType == GAME_TYPE_STORY) + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_STORY); + else + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_DUEL); + currentState = MENU_STATE_MAJOR_MAINMENU; + } + } } - if(mEngine->GetButtonState(JGE_BTN_PREV)) { - //Reset deck of cards - angleMultiplier = MIN_ANGLE_MULTIPLIER; - yW = 55; - } - - if (yW <= 55) + switch (MENU_STATE_MINOR & currentState) { - if (mEngine->GetButtonState(JGE_BTN_PRI)) angleMultiplier += STEP_ANGLE_MULTIPLIER; - else angleMultiplier *= 0.9999f; - if (angleMultiplier > MAX_ANGLE_MULTIPLIER) angleMultiplier = MAX_ANGLE_MULTIPLIER; - else if (angleMultiplier < MIN_ANGLE_MULTIPLIER) angleMultiplier = MIN_ANGLE_MULTIPLIER; - - if (mEngine->GetButtonState(JGE_BTN_CANCEL) && (dt != 0)) - { - angleMultiplier = (cos(timeIndex)*angleMultiplier - M_PI/3.0f - 0.1f - angleW) / dt; - yW = yW + 5*dt + (yW - 45) *5* dt; - } - else - angleW = cos(timeIndex)*angleMultiplier - M_PI/3.0f - 0.1f; + case MENU_STATE_MINOR_SUBMENU_CLOSING: + if (!subMenuController) + { //http://code.google.com/p/wagic/issues/detail?id=379 + currentState &= ~MENU_STATE_MINOR_SUBMENU_CLOSING; + break; + } + if (subMenuController->closed) + { + SAFE_DELETE(subMenuController); + currentState &= ~MENU_STATE_MINOR_SUBMENU_CLOSING; + } + else + subMenuController->Update(dt); + break; + case MENU_STATE_MINOR_NONE: + ;// Nothing to do. } - else + + if (mEngine->GetButtonState(JGE_BTN_PREV)) { - angleW += angleMultiplier * dt; - yW = yW + 5*dt + (yW - 55) *5*dt; + //Reset deck of cards + angleMultiplier = MIN_ANGLE_MULTIPLIER; + yW = 55; } - scroller->Update(dt); - if((currentState & MENU_STATE_MINOR) == MENU_STATE_MINOR_FADEIN){ - currentState = currentState ^ MENU_STATE_MINOR_FADEIN; - mParent->DoAnimation( TRANSITION_FADE_IN, 0.15f ); - } + if (yW <= 55) + { + if (mEngine->GetButtonState(JGE_BTN_PRI)) + angleMultiplier += STEP_ANGLE_MULTIPLIER; + else + angleMultiplier *= 0.9999f; + if (angleMultiplier > MAX_ANGLE_MULTIPLIER) + angleMultiplier = MAX_ANGLE_MULTIPLIER; + else if (angleMultiplier < MIN_ANGLE_MULTIPLIER) + angleMultiplier = MIN_ANGLE_MULTIPLIER; + + if (mEngine->GetButtonState(JGE_BTN_CANCEL) && (dt != 0)) + { + angleMultiplier = (cos(timeIndex) * angleMultiplier - M_PI / 3.0f - 0.1f - angleW) / dt; + yW = yW + 5 * dt + (yW - 45) * 5 * dt; + } + else + angleW = cos(timeIndex) * angleMultiplier - M_PI / 3.0f - 0.1f; + } + else + { + angleW += angleMultiplier * dt; + yW = yW + 5 * dt + (yW - 55) * 5 * dt; + } + + scroller->Update(dt); + if ((currentState & MENU_STATE_MINOR) == MENU_STATE_MINOR_FADEIN) + { + currentState = currentState ^ MENU_STATE_MINOR_FADEIN; + mParent->DoAnimation(TRANSITION_FADE_IN, 0.15f); + } } void GameStateMenu::Render() { - if((currentState & MENU_STATE_MINOR) == MENU_STATE_MINOR_FADEIN) - return; + if ((currentState & MENU_STATE_MINOR) == MENU_STATE_MINOR_FADEIN) + return; - JRenderer * renderer = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); - if ((currentState & MENU_STATE_MAJOR) == MENU_STATE_MAJOR_LANG){ - }else if ((currentState & MENU_STATE_MAJOR) == MENU_STATE_MAJOR_LOADING_CARDS){ - if(!splashTex){ - splashTex = resources.RetrieveTexture("splash.jpg",RETRIEVE_LOCK); - mSplash = resources.RetrieveTempQuad("splash.jpg"); - } - if (mSplash) - renderer->RenderQuad(mSplash,0,0); - else { - string wp = loadRandomWallpaper(); - if (wp.size()) { - JTexture * wpTex = resources.RetrieveTexture(wp); - if (wpTex) { - JQuad * wpQuad = resources.RetrieveTempQuad(wp); - renderer->RenderQuad(wpQuad,0,0,0,SCREEN_WIDTH_F / wpQuad->mWidth, SCREEN_HEIGHT_F / wpQuad->mHeight); - } - } - } - char text[512]; - if (mCurrentSetName[0]) { - sprintf(text, _("LOADING SET: %s").c_str(), mCurrentSetName); - }else{ - if (primitivesLoadCounter <= (int)(primitives.size())) - sprintf(text,"LOADING PRIMITIVES"); - else - sprintf(text,"LOADING..."); - } - mFont->SetColor(ARGB(170,0,0,0)); - mFont->DrawString(text,SCREEN_WIDTH/2 + 2 ,SCREEN_HEIGHT - 50 + 2,JGETEXT_CENTER); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(text,SCREEN_WIDTH/2,SCREEN_HEIGHT - 50,JGETEXT_CENTER); - }else{ - mFont = resources.GetWFont(Fonts::MAIN_FONT); - PIXEL_TYPE colors[] = + JRenderer * renderer = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); + if ((currentState & MENU_STATE_MAJOR) == MENU_STATE_MAJOR_LANG) { - - ARGB(255,3,3,0), - ARGB(255,8,8,0), - ARGB(255,21,21,10), - ARGB(255,50,50,30), - }; - renderer->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,colors); - - if (mGuiController) - mGuiController->Render(); - - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->SetColor(ARGB(128,255,255,255)); - mFont->DrawString(GAME_VERSION, SCREEN_WIDTH-74,5,JGETEXT_RIGHT); - mFont->DrawString(nbcardsStr,10, 5); - mFont->SetScale(1.f); - mFont->SetColor(ARGB(255,255,255,255)); - - renderer->FillRoundRect(SCREEN_WIDTH/2 - 100,SCREEN_HEIGHT, 191,6,5,ARGB(100,10,5,0)); - scroller->Render(); - - - if(mBg) - renderer->RenderQuad(mBg,SCREEN_WIDTH/2,50); - - JQuad * jq = resources.RetrieveTempQuad("button_shoulder.png"); - if(jq){ - int alp = 255; - if(options.newAward()) - alp = (int)(sin(timeIndex) * 255); - float olds = mFont->GetScale(); - mFont = resources.GetWFont(Fonts::OPTION_FONT); - jq->SetColor(ARGB(abs(alp),255,255,255)); - mFont->SetColor(ARGB(abs(alp),0,0,0)); - string s = _("Trophy Room");; - mFont->SetScale(1.0f); - mFont->SetScale(50.0f/mFont->GetStringWidth(s.c_str())); - renderer->RenderQuad(jq, SCREEN_WIDTH-64, 2); - mFont->DrawString(s,SCREEN_WIDTH-10,9,JGETEXT_RIGHT); - mFont = resources.GetWFont(Fonts::MENU_FONT); - mFont->SetScale(olds); } - } - if (subMenuController){ - subMenuController->Render(); - } -} + else if ((currentState & MENU_STATE_MAJOR) == MENU_STATE_MAJOR_LOADING_CARDS) + { + if (!splashTex) + { + splashTex = resources.RetrieveTexture("splash.jpg", RETRIEVE_LOCK); + mSplash = resources.RetrieveTempQuad("splash.jpg"); + } + if (mSplash) + renderer->RenderQuad(mSplash, 0, 0); + else + { + string wp = loadRandomWallpaper(); + if (wp.size()) + { + JTexture * wpTex = resources.RetrieveTexture(wp); + if (wpTex) + { + JQuad * wpQuad = resources.RetrieveTempQuad(wp); + renderer->RenderQuad(wpQuad, 0, 0, 0, SCREEN_WIDTH_F / wpQuad->mWidth, SCREEN_HEIGHT_F / wpQuad->mHeight); + } + } + } + char text[512]; + if (mCurrentSetName[0]) + { + sprintf(text, _("LOADING SET: %s").c_str(), mCurrentSetName); + } + else + { + if (primitivesLoadCounter <= (int) (primitives.size())) + sprintf(text, "LOADING PRIMITIVES"); + else + sprintf(text, "LOADING..."); + } + mFont->SetColor(ARGB(170,0,0,0)); + mFont->DrawString(text, SCREEN_WIDTH / 2 + 2, SCREEN_HEIGHT - 50 + 2, JGETEXT_CENTER); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(text, SCREEN_WIDTH / 2, SCREEN_HEIGHT - 50, JGETEXT_CENTER); + } + else + { + mFont = resources.GetWFont(Fonts::MAIN_FONT); + PIXEL_TYPE colors[] = { + ARGB(255,3,3,0), ARGB(255,8,8,0), ARGB(255,21,21,10), ARGB(255,50,50,30), }; + renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, colors); + + if (mGuiController) + mGuiController->Render(); + + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + mFont->SetColor(ARGB(128,255,255,255)); + mFont->DrawString(GAME_VERSION, SCREEN_WIDTH - 74, 5, JGETEXT_RIGHT); + mFont->DrawString(nbcardsStr, 10, 5); + mFont->SetScale(1.f); + mFont->SetColor(ARGB(255,255,255,255)); + + renderer->FillRoundRect(SCREEN_WIDTH / 2 - 100, SCREEN_HEIGHT, 191, 6, 5, ARGB(100,10,5,0)); + scroller->Render(); + + if (mBg) + renderer->RenderQuad(mBg, SCREEN_WIDTH / 2, 50); + + JQuad * jq = resources.RetrieveTempQuad("button_shoulder.png"); + if (jq) + { + int alp = 255; + if (options.newAward()) + alp = (int) (sin(timeIndex) * 255); + float olds = mFont->GetScale(); + mFont = resources.GetWFont(Fonts::OPTION_FONT); + jq->SetColor(ARGB(abs(alp),255,255,255)); + mFont->SetColor(ARGB(abs(alp),0,0,0)); + string s = _("Trophy Room"); + ; + mFont->SetScale(1.0f); + mFont->SetScale(50.0f / mFont->GetStringWidth(s.c_str())); + renderer->RenderQuad(jq, SCREEN_WIDTH - 64, 2); + mFont->DrawString(s, SCREEN_WIDTH - 10, 9, JGETEXT_RIGHT); + mFont = resources.GetWFont(Fonts::MENU_FONT); + mFont->SetScale(olds); + } + } + if (subMenuController) + { + subMenuController->Render(); + } +} void GameStateMenu::ButtonPressed(int controllerId, int controlId) { - WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); + WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); - DebugTrace("GameStateMenu: controllerId " << controllerId << " selected"); - switch (controllerId){ - case MENU_LANGUAGE_SELECTION: - setLang(controlId); - resources.ReloadWFonts(); // Fix for choosing Chinese language at first time. - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_LOADING_CARDS | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; - case 101: - options.createUsersFirstDeck(controlId); - currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE; - break; - default: - switch (controlId) + DebugTrace("GameStateMenu: controllerId " << controllerId << " selected"); + switch (controllerId) { - case MENUITEM_PLAY: - subMenuController = NEW SimpleMenu( MENU_FIRST_DUEL_SUBMENU, this, Fonts::MENU_FONT, 150,60); - if (subMenuController){ - subMenuController->Add(SUBMENUITEM_1PLAYER,"1 Player"); - // TODO Put 2 players mode back - // This requires to fix the hand (to accept 2 players) OR to implement network game - //subMenuController->Add(SUBMENUITEM_2PLAYER, "2 Players"); - subMenuController->Add(SUBMENUITEM_DEMO,"Demo"); - subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel"); -#ifdef TESTSUITE - subMenuController->Add(SUBMENUITEM_TESTSUITE, "Test Suite"); -#endif - currentState = MENU_STATE_MAJOR_SUBMENU | MENU_STATE_MINOR_NONE; - } - break; - case MENUITEM_DECKEDITOR: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_DECK_VIEWER); - break; - case MENUITEM_SHOP: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_SHOP); - break; - case MENUITEM_OPTIONS: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_OPTIONS); - break; - case MENUITEM_EXIT: - mEngine->End(); - break; - case SUBMENUITEM_1PLAYER: - mParent->players[0] = PLAYER_TYPE_HUMAN; - mParent->players[1] = PLAYER_TYPE_CPU; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; - case SUBMENUITEM_2PLAYER: - mParent->players[0] = PLAYER_TYPE_HUMAN; - mParent->players[1] = PLAYER_TYPE_HUMAN; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; - case SUBMENUITEM_DEMO: - mParent->players[0] = PLAYER_TYPE_CPU; - mParent->players[1] = PLAYER_TYPE_CPU; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; - case SUBMENUITEM_CANCEL: - if (subMenuController != NULL) - { + case MENU_LANGUAGE_SELECTION: + setLang(controlId); + resources.ReloadWFonts(); // Fix for choosing Chinese language at first time. subMenuController->Close(); - } - currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; + currentState = MENU_STATE_MAJOR_LOADING_CARDS | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; + case 101: + options.createUsersFirstDeck(controlId); + currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE; + break; + default: + switch (controlId) + { + case MENUITEM_PLAY: + subMenuController = NEW SimpleMenu(MENU_FIRST_DUEL_SUBMENU, this, Fonts::MENU_FONT, 150, 60); + if (subMenuController) + { + subMenuController->Add(SUBMENUITEM_1PLAYER, "1 Player"); + // TODO Put 2 players mode back + // This requires to fix the hand (to accept 2 players) OR to implement network game + //subMenuController->Add(SUBMENUITEM_2PLAYER, "2 Players"); + subMenuController->Add(SUBMENUITEM_DEMO, "Demo"); + subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel"); +#ifdef TESTSUITE + subMenuController->Add(SUBMENUITEM_TESTSUITE, "Test Suite"); +#endif + currentState = MENU_STATE_MAJOR_SUBMENU | MENU_STATE_MINOR_NONE; + } + break; + case MENUITEM_DECKEDITOR: + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_DECK_VIEWER); + break; + case MENUITEM_SHOP: + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_SHOP); + break; + case MENUITEM_OPTIONS: + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_OPTIONS); + break; + case MENUITEM_EXIT: + mEngine->End(); + break; + case SUBMENUITEM_1PLAYER: + mParent->players[0] = PLAYER_TYPE_HUMAN; + mParent->players[1] = PLAYER_TYPE_CPU; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; + case SUBMENUITEM_2PLAYER: + mParent->players[0] = PLAYER_TYPE_HUMAN; + mParent->players[1] = PLAYER_TYPE_HUMAN; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; + case SUBMENUITEM_DEMO: + mParent->players[0] = PLAYER_TYPE_CPU; + mParent->players[1] = PLAYER_TYPE_CPU; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; + case SUBMENUITEM_CANCEL: + if (subMenuController != NULL) + { + subMenuController->Close(); + } + currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; - case SUBMENUITEM_CLASSIC: - this->hasChosenGameType = 1; - mParent->gameType = GAME_TYPE_CLASSIC; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; + case SUBMENUITEM_CLASSIC: + this->hasChosenGameType = 1; + mParent->gameType = GAME_TYPE_CLASSIC; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; - case SUBMENUITEM_MOMIR: - this->hasChosenGameType = 1; - mParent->gameType = GAME_TYPE_MOMIR; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; + case SUBMENUITEM_MOMIR: + this->hasChosenGameType = 1; + mParent->gameType = GAME_TYPE_MOMIR; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; - case SUBMENUITEM_RANDOM1: - this->hasChosenGameType = 1; - mParent->gameType = GAME_TYPE_RANDOM1; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; + case SUBMENUITEM_RANDOM1: + this->hasChosenGameType = 1; + mParent->gameType = GAME_TYPE_RANDOM1; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; - case SUBMENUITEM_RANDOM2: - this->hasChosenGameType = 1; - mParent->gameType = GAME_TYPE_RANDOM2; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; + case SUBMENUITEM_RANDOM2: + this->hasChosenGameType = 1; + mParent->gameType = GAME_TYPE_RANDOM2; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; - case SUBMENUITEM_STORY: - this->hasChosenGameType = 1; - mParent->gameType = GAME_TYPE_STORY; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; + case SUBMENUITEM_STORY: + this->hasChosenGameType = 1; + mParent->gameType = GAME_TYPE_STORY; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; #ifdef TESTSUITE - case SUBMENUITEM_TESTSUITE: - mParent->players[0] = PLAYER_TYPE_TESTSUITE; - mParent->players[1] = PLAYER_TYPE_TESTSUITE; - subMenuController->Close(); - currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; - break; + case SUBMENUITEM_TESTSUITE: + mParent->players[0] = PLAYER_TYPE_TESTSUITE; + mParent->players[1] = PLAYER_TYPE_TESTSUITE; + subMenuController->Close(); + currentState = MENU_STATE_MAJOR_DUEL | MENU_STATE_MINOR_SUBMENU_CLOSING; + break; #endif + } + break; } - break; - } } ostream& GameStateMenu::toString(ostream& out) const { - return out << "GameStateMenu ::: scroller : " << scroller - << " ; scrollerSet : " << scrollerSet - << " ; mGuiController : " << mGuiController - << " ; subMenuController : " << subMenuController - << " ; gameTypeMenu : " << gameTypeMenu - << " ; hasChosenGameType : " << hasChosenGameType - << " ; mIcons : " << mIcons - << " ; bgTexture : " << bgTexture - << " ; mBg : " << mBg - << " ; mCreditsYPos : " << mCreditsYPos - << " ; currentState : " << currentState - << " ; mVolume : " << mVolume - << " ; nbcardsStr : " << nbcardsStr - << " ; mDip : " << mDip - << " ; mDit : " << mDit - << " ; mCurrentSetName : " << mCurrentSetName - << " ; mCurrentSetFileName : " << mCurrentSetFileName - << " ; mReadConf : " << mReadConf - << " ; timeIndex : " << timeIndex - << " ; angleMultiplier : " << angleMultiplier - << " ; angleW : " << angleW - << " ; yW : " << yW; + return out << "GameStateMenu ::: scroller : " << scroller + << " ; scrollerSet : " << scrollerSet + << " ; mGuiController : " << mGuiController + << " ; subMenuController : " << subMenuController + << " ; gameTypeMenu : " << gameTypeMenu + << " ; hasChosenGameType : " << hasChosenGameType + << " ; mIcons : " << mIcons + << " ; bgTexture : " << bgTexture + << " ; mBg : " << mBg + << " ; mCreditsYPos : " << mCreditsYPos + << " ; currentState : " << currentState + << " ; mVolume : " << mVolume + << " ; nbcardsStr : " << nbcardsStr + << " ; mDip : " << mDip + << " ; mDit : " << mDit + << " ; mCurrentSetName : " << mCurrentSetName + << " ; mCurrentSetFileName : " << mCurrentSetFileName + << " ; mReadConf : " << mReadConf + << " ; timeIndex : " << timeIndex + << " ; angleMultiplier : " << angleMultiplier + << " ; angleW : " << angleW + << " ; yW : " << yW; } diff --git a/projects/mtg/src/GameStateOptions.cpp b/projects/mtg/src/GameStateOptions.cpp index ec916b1fc..1b3ea1dea 100644 --- a/projects/mtg/src/GameStateOptions.cpp +++ b/projects/mtg/src/GameStateOptions.cpp @@ -10,275 +10,299 @@ namespace { - const int kSaveAndBackToMainMenuID = 1; - const int kBackToMainMenuID = 2; - const int kNewProfileID = 4; - const int kReloadID = 5; + const int kSaveAndBackToMainMenuID = 1; + const int kBackToMainMenuID = 2; + const int kNewProfileID = 4; + const int kReloadID = 5; } -GameStateOptions::GameStateOptions(GameApp* parent): GameState(parent), mReload(false), grabber(NULL), optionsMenu(NULL), optionsTabs(NULL) {} -GameStateOptions::~GameStateOptions() {} +GameStateOptions::GameStateOptions(GameApp* parent) : + GameState(parent), mReload(false), grabber(NULL), optionsMenu(NULL), optionsTabs(NULL) +{ +} +GameStateOptions::~GameStateOptions() +{ +} void GameStateOptions::Start() { - newProfile = ""; - timer = 0; - mState = SHOW_OPTIONS; - JRenderer::GetInstance()->EnableVSync(true); + newProfile = ""; + timer = 0; + mState = SHOW_OPTIONS; + JRenderer::GetInstance()->EnableVSync(true); - WGuiList * optionsList; + WGuiList * optionsList; - optionsList = NEW WGuiList("Settings"); + optionsList = NEW WGuiList("Settings"); - optionsList->Add(NEW WGuiHeader("General Options")); - if (GameApp::HasMusic) - optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::MUSICVOLUME,"Music volume",100,10,100),OptionVolume::getInstance())); - optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::SFXVOLUME,"SFX volume",100,10,100),OptionVolume::getInstance())); - if (options[Options::DIFFICULTY_MODE_UNLOCKED].number){ - optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::DIFFICULTY,"Difficulty",3,1,0),OptionDifficulty::getInstance())); - optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::ECON_DIFFICULTY,"Economic Difficuly",Constants::ECON_EASY))); - } - optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1)); - optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells")); - optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities")); - optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDMAIN, "Interrupt opponent's end of turn")); - optionsTabs = NEW WGuiTabMenu(); - optionsTabs->Add(optionsList); + optionsList->Add(NEW WGuiHeader("General Options")); + if (GameApp::HasMusic) + optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::MUSICVOLUME, "Music volume", 100, 10, 100), + OptionVolume::getInstance())); + optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::SFXVOLUME, "SFX volume", 100, 10, 100), OptionVolume::getInstance())); + if (options[Options::DIFFICULTY_MODE_UNLOCKED].number) + { + optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::DIFFICULTY, "Difficulty", 3, 1, 0), + OptionDifficulty::getInstance())); + optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::ECON_DIFFICULTY, "Economic Difficuly", Constants::ECON_EASY))); + } + optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1)); + optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells")); + optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities")); + optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDMAIN, "Interrupt opponent's end of turn")); + optionsTabs = NEW WGuiTabMenu(); + optionsTabs->Add(optionsList); - optionsList = NEW WGuiList("Game"); - optionsList->Add(NEW WGuiHeader("Interface Options")); - optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::CLOSEDHAND,"Closed hand",1,1,0))); - optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::HANDDIRECTION,"Hand direction",1,1,0))); - optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::MANADISPLAY,"Mana display",2,1,0))); - optionsList->Add(NEW OptionInteger(Options::REVERSETRIGGERS, "Reverse left and right triggers")); - optionsList->Add(NEW OptionInteger(Options::DISABLECARDS,"Disable card images")); - optionsList->Add(NEW OptionInteger(Options::TRANSITIONS,"Disable screen transitions")); - optionsList->Add(NEW OptionInteger(Options::OSD, "Display InGame extra information")); - optionsTabs->Add(optionsList); + optionsList = NEW WGuiList("Game"); + optionsList->Add(NEW WGuiHeader("Interface Options")); + optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::CLOSEDHAND, "Closed hand", 1, 1, 0))); + optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::HANDDIRECTION, "Hand direction", 1, 1, 0))); + optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::MANADISPLAY, "Mana display", 2, 1, 0))); + optionsList->Add(NEW OptionInteger(Options::REVERSETRIGGERS, "Reverse left and right triggers")); + optionsList->Add(NEW OptionInteger(Options::DISABLECARDS, "Disable card images")); + optionsList->Add(NEW OptionInteger(Options::TRANSITIONS, "Disable screen transitions")); + optionsList->Add(NEW OptionInteger(Options::OSD, "Display InGame extra information")); + optionsTabs->Add(optionsList); - optionsList = NEW WGuiList("User"); - optionsList->Add(NEW WGuiHeader("User Options")); - WDecoConfirm * cPrf = NEW WDecoConfirm(this,NEW OptionProfile(mParent,this)); - cPrf->confirm = "Use this Profile"; - OptionThemeStyle * ots = NEW OptionThemeStyle("Theme Style"); - OptionDirectory * od = NEW OptionTheme(ots); - WDecoConfirm * cThm = NEW WDecoConfirm(this,od); - cThm->confirm = "Use this Theme"; + optionsList = NEW WGuiList("User"); + optionsList->Add(NEW WGuiHeader("User Options")); + WDecoConfirm * cPrf = NEW WDecoConfirm(this, NEW OptionProfile(mParent, this)); + cPrf->confirm = "Use this Profile"; + OptionThemeStyle * ots = NEW OptionThemeStyle("Theme Style"); + OptionDirectory * od = NEW OptionTheme(ots); + WDecoConfirm * cThm = NEW WDecoConfirm(this, od); + cThm->confirm = "Use this Theme"; - WDecoConfirm * cStyle = NEW WDecoConfirm(this,ots); - cStyle->confirm = "Use this Style"; + WDecoConfirm * cStyle = NEW WDecoConfirm(this, ots); + cStyle->confirm = "Use this Style"; - optionsList->Add(NEW WGuiSplit(cPrf,cThm)); - optionsList->Add(cStyle); - optionsList->Add(NEW WGuiButton(NEW WGuiHeader("New Profile"),-102, kNewProfileID, this)); + optionsList->Add(NEW WGuiSplit(cPrf, cThm)); + optionsList->Add(cStyle); + optionsList->Add(NEW WGuiButton(NEW WGuiHeader("New Profile"), -102, kNewProfileID, this)); - optionsList->Add(NEW WDecoCheat(NEW OptionInteger(Options::CHEATMODE, "Enable cheat mode"))); - optionsTabs->Add(optionsList); + optionsList->Add(NEW WDecoCheat(NEW OptionInteger(Options::CHEATMODE, "Enable cheat mode"))); + optionsTabs->Add(optionsList); - optionsList = NEW WGuiList("Advanced"); - optionsList->Add(NEW WGuiHeader("Advanced Options")); - WDecoStyled * wAdv = NEW WDecoStyled(NEW WGuiHeader("The following options require a restart.")); - wAdv->mStyle = WDecoStyled::DS_STYLE_ALERT; - optionsList->Add(wAdv); - WDecoConfirm * cLang = NEW WDecoConfirm(this,NEW OptionLanguage("Language")); - cLang->confirm = "Use this Language"; - optionsList->Add(cLang); - WDecoEnum * oGra = NEW WDecoEnum(NEW OptionInteger(Options::MAX_GRADE,"Minimum Card Grade",Constants::GRADE_DANGEROUS,1,Constants::GRADE_BORDERLINE,"",Constants::GRADE_SUPPORTED)); - optionsList->Add(oGra); - WDecoEnum * oASPhases = NEW WDecoEnum(NEW OptionInteger(Options::ASPHASES,"Phase Skip Automation",Constants::ASKIP_FULL,1,Constants::ASKIP_NONE,"",Constants::ASKIP_NONE)); - optionsList->Add(oASPhases); - optionsTabs->Add(optionsList); + optionsList = NEW WGuiList("Advanced"); + optionsList->Add(NEW WGuiHeader("Advanced Options")); + WDecoStyled * wAdv = NEW WDecoStyled(NEW WGuiHeader("The following options require a restart.")); + wAdv->mStyle = WDecoStyled::DS_STYLE_ALERT; + optionsList->Add(wAdv); + WDecoConfirm * cLang = NEW WDecoConfirm(this, NEW OptionLanguage("Language")); + cLang->confirm = "Use this Language"; + optionsList->Add(cLang); + WDecoEnum * oGra = NEW WDecoEnum(NEW OptionInteger(Options::MAX_GRADE, "Minimum Card Grade", Constants::GRADE_DANGEROUS, 1, + Constants::GRADE_BORDERLINE, "", Constants::GRADE_SUPPORTED)); + optionsList->Add(oGra); + WDecoEnum * oASPhases = NEW WDecoEnum(NEW OptionInteger(Options::ASPHASES, "Phase Skip Automation", Constants::ASKIP_FULL, 1, + Constants::ASKIP_NONE, "", Constants::ASKIP_NONE)); + optionsList->Add(oASPhases); + optionsTabs->Add(optionsList); - optionsList = NEW WGuiKeyBinder("Key Bindings", this); - optionsTabs->Add(optionsList); + optionsList = NEW WGuiKeyBinder("Key Bindings", this); + optionsTabs->Add(optionsList); - optionsList = NEW WGuiList("Credits"); - optionsList->failMsg = ""; - optionsTabs->Add(optionsList); + optionsList = NEW WGuiList("Credits"); + optionsList->failMsg = ""; + optionsTabs->Add(optionsList); - optionsMenu = NEW SimpleMenu(-102, this,Fonts::MENU_FONT, 50,170); - optionsMenu->Add(kBackToMainMenuID, "Back to Main Menu"); - optionsMenu->Add(kSaveAndBackToMainMenuID, "Save & Back to Main Menu"); - optionsMenu->Add(kCancelMenuID, "Cancel"); + optionsMenu = NEW SimpleMenu(-102, this, Fonts::MENU_FONT, 50, 170); + optionsMenu->Add(kBackToMainMenuID, "Back to Main Menu"); + optionsMenu->Add(kSaveAndBackToMainMenuID, "Save & Back to Main Menu"); + optionsMenu->Add(kCancelMenuID, "Cancel"); - optionsTabs->Entering(JGE_BTN_NONE); + optionsTabs->Entering(JGE_BTN_NONE); } - void GameStateOptions::End() { - JRenderer::GetInstance()->EnableVSync(false); - SAFE_DELETE(optionsTabs); - SAFE_DELETE(optionsMenu); + JRenderer::GetInstance()->EnableVSync(false); + SAFE_DELETE(optionsTabs); + SAFE_DELETE(optionsMenu); } - void GameStateOptions::Update(float dt) { - timer += dt * 10; + timer += dt * 10; - if(options.keypadActive()){ - options.keypadUpdate(dt); + if (options.keypadActive()) + { + options.keypadUpdate(dt); - if(newProfile != ""){ - newProfile = options.keypadFinish(); - if(newProfile != ""){ - options[Options::ACTIVE_PROFILE] = newProfile; - options.reloadProfile(false); - optionsTabs->Reload(); - } - newProfile = ""; - } - } - else switch(mState){ - default: - case SAVE: - switch (optionsTabs->needsConfirm()) + if (newProfile != "") { - case WGuiBase::CONFIRM_CANCEL: - mState = SHOW_OPTIONS; - break; - case WGuiBase::CONFIRM_OK: - optionsTabs->save(); - JSoundSystem::GetInstance()->SetSfxVolume(options[Options::SFXVOLUME].number); - JSoundSystem::GetInstance()->SetMusicVolume(options[Options::MUSICVOLUME].number); - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - mState = SHOW_OPTIONS; - break; - case WGuiBase::CONFIRM_NEED: - optionsTabs->yieldFocus(); - break; + newProfile = options.keypadFinish(); + if (newProfile != "") + { + options[Options::ACTIVE_PROFILE] = newProfile; + options.reloadProfile(false); + optionsTabs->Reload(); + } + newProfile = ""; } - // Note : No break here : must continue to continue updating the menu elements. - case SHOW_OPTIONS: { - JGE* j = JGE::GetInstance(); - JButton key; - if (grabber) { - LocalKeySym sym; - if (LOCAL_KEY_NONE != (sym = j->ReadLocalKey())) - grabber->KeyPressed(sym); - } - else while ((key = JGE::GetInstance()->ReadButton())){ - if(!optionsTabs->CheckUserInput(key) && key == JGE_BTN_MENU) - mState = SHOW_OPTIONS_MENU; - } - optionsTabs->Update(dt); - break; - } - case SHOW_OPTIONS_MENU: - optionsMenu->Update(dt); - break; } - if(mReload){ - options.reloadProfile(true); - Translator::EndInstance(); - Translator::GetInstance()->init(); - optionsTabs->Reload(); - mReload = false; - } + else + switch (mState) + { + default: + case SAVE: + switch (optionsTabs->needsConfirm()) + { + case WGuiBase::CONFIRM_CANCEL: + mState = SHOW_OPTIONS; + break; + case WGuiBase::CONFIRM_OK: + optionsTabs->save(); + JSoundSystem::GetInstance()->SetSfxVolume(options[Options::SFXVOLUME].number); + JSoundSystem::GetInstance()->SetMusicVolume(options[Options::MUSICVOLUME].number); + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + mState = SHOW_OPTIONS; + break; + case WGuiBase::CONFIRM_NEED: + optionsTabs->yieldFocus(); + break; + } + // Note : No break here : must continue to continue updating the menu elements. + case SHOW_OPTIONS: + { + JGE* j = JGE::GetInstance(); + JButton key; + if (grabber) + { + LocalKeySym sym; + if (LOCAL_KEY_NONE != (sym = j->ReadLocalKey())) + grabber->KeyPressed(sym); + } + else + while ((key = JGE::GetInstance()->ReadButton())) + { + if (!optionsTabs->CheckUserInput(key) && key == JGE_BTN_MENU) + mState = SHOW_OPTIONS_MENU; + } + optionsTabs->Update(dt); + break; + } + case SHOW_OPTIONS_MENU: + optionsMenu->Update(dt); + break; + } + if (mReload) + { + options.reloadProfile(true); + Translator::EndInstance(); + Translator::GetInstance()->init(); + optionsTabs->Reload(); + mReload = false; + } } void GameStateOptions::Render() { - //Erase - JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0)); + //Erase + JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0)); - const char * const CreditsText[] = { - "Wagic, The Homebrew?! by Wololo", - "", - "updates, new cards, and more on http://wololo.net/wagic", - "Many thanks to the people who help this project", - "", - "", - "Art: Ilya B, Julio, Jeck, J, Kaioshin, Lakeesha", - "Check themeinfo.txt for the full credits of each theme!", - "", - "Dev Team:", - "Abrasax, almosthumane, Daddy32, DJardin, Dr.Solomat,", - "J, Jeck, Leungclj, linshier, Mnguyen, Psyringe,", - "Salmelo, Superhiro, Wololo, Yeshua, Zethfox", - "", - "Music by Celestial Aeon Project, http://www.jamendo.com", - "", - "Deck Builders: Abrasax, AzureKnight, colarchon", - "Hehotfarv, Jeremy, Jog1118, JonyAS, Kaioshin", - "Lachaux, Link17, Muddobbers, Nakano, Niegen", - "Psyringe, r1c47, Superhiro, Szei, Thanatos02", - "Whismer, Wololo", - "", - "Thanks also go to Dr.Watson, Orine, Raphael, Sakya, Tyranid", - "for their help.", - "", - "Thanks to everyone who contributes code/content on the forums!", - "", - "Developed with the JGE++ Library (http://code.google.com/p/wagic)", - "SFX From www.soundsnap.com", + const char * const CreditsText[] = { + "Wagic, The Homebrew?! by Wololo", + "", + "updates, new cards, and more on http://wololo.net/wagic", + "Many thanks to the people who help this project", + "", + "", + "Art: Ilya B, Julio, Jeck, J, Kaioshin, Lakeesha", + "Check themeinfo.txt for the full credits of each theme!", + "", + "Dev Team:", + "Abrasax, almosthumane, Daddy32, DJardin, Dr.Solomat,", + "J, Jeck, Leungclj, linshier, Mnguyen, Psyringe,", + "Salmelo, Superhiro, Wololo, Yeshua, Zethfox", + "", + "Music by Celestial Aeon Project, http://www.jamendo.com", + "", + "Deck Builders: Abrasax, AzureKnight, colarchon", + "Hehotfarv, Jeremy, Jog1118, JonyAS, Kaioshin", + "Lachaux, Link17, Muddobbers, Nakano, Niegen", + "Psyringe, r1c47, Superhiro, Szei, Thanatos02", + "Whismer, Wololo", + "", + "Thanks also go to Dr.Watson, Orine, Raphael, Sakya, Tyranid", + "for their help.", + "", + "Thanks to everyone who contributes code/content on the forums!", + "", + "Developed with the JGE++ Library (http://code.google.com/p/wagic)", + "SFX From www.soundsnap.com", - "", - "", - "This work is not related to or endorsed by Wizards of the Coast, Inc", - "", - "Please support this project with donations at http://wololo.net/wagic", + "", + "", + "This work is not related to or endorsed by Wizards of the Coast, Inc", + "", + "Please support this project with donations at http://wololo.net/wagic", }; - WFont * mFont = resources.GetWFont(Fonts::MAGIC_FONT); - mFont->SetColor(ARGB(255,200,200,200)); - mFont->SetScale(1.0); - float startpos = 272 - timer; - float pos = startpos; - int size = sizeof(CreditsText) / sizeof(CreditsText[0]); + WFont * mFont = resources.GetWFont(Fonts::MAGIC_FONT); + mFont->SetColor(ARGB(255,200,200,200)); + mFont->SetScale(1.0); + float startpos = 272 - timer; + float pos = startpos; + int size = sizeof(CreditsText) / sizeof(CreditsText[0]); - for (int i = 0; i < size; i++){ - pos = startpos + 20 * i; - if (pos > -20 && pos < SCREEN_HEIGHT + 20){ - mFont->DrawString(CreditsText[i],SCREEN_WIDTH/2,pos ,JGETEXT_CENTER); + for (int i = 0; i < size; i++) + { + pos = startpos + 20 * i; + if (pos > -20 && pos < SCREEN_HEIGHT + 20) + { + mFont->DrawString(CreditsText[i], SCREEN_WIDTH / 2, pos, JGETEXT_CENTER); + } } - } - if (pos < -20) - timer = 0; + if (pos < -20) + timer = 0; + optionsTabs->Render(); - optionsTabs->Render(); + if (mState == SHOW_OPTIONS_MENU) + optionsMenu->Render(); - if(mState == SHOW_OPTIONS_MENU) - optionsMenu->Render(); - - if(options.keypadActive()) - options.keypadRender(); + if (options.keypadActive()) + options.keypadRender(); } void GameStateOptions::ButtonPressed(int controllerId, int controlId) { - //Exit menu? - if(controllerId == -102) - switch (controlId){ - case kSaveAndBackToMainMenuID: - mState = SAVE; - break; - //Set Audio volume - case kBackToMainMenuID: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - break; - case kCancelMenuID: - mState = SHOW_OPTIONS; - break; - case kNewProfileID: - options.keypadStart("",&newProfile); - options.keypadTitle("New Profile"); - break; - case kReloadID: - mReload = true; - break; - } - else - optionsTabs->ButtonPressed(controllerId, controlId); -}; + //Exit menu? + if (controllerId == -102) + switch (controlId) + { + case kSaveAndBackToMainMenuID: + mState = SAVE; + break; + //Set Audio volume + case kBackToMainMenuID: + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + break; + case kCancelMenuID: + mState = SHOW_OPTIONS; + break; + case kNewProfileID: + options.keypadStart("", &newProfile); + options.keypadTitle("New Profile"); + break; + case kReloadID: + mReload = true; + break; + } + else + optionsTabs->ButtonPressed(controllerId, controlId); +} +; -void GameStateOptions::GrabKeyboard(KeybGrabber* g) { - grabber = g; +void GameStateOptions::GrabKeyboard(KeybGrabber* g) +{ + grabber = g; } -void GameStateOptions::UngrabKeyboard(const KeybGrabber* g) { - if (g == grabber) grabber = NULL; +void GameStateOptions::UngrabKeyboard(const KeybGrabber* g) +{ + if (g == grabber) + grabber = NULL; } diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index 51075c1a9..b083b20ab 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -1,6 +1,6 @@ /* - The shop is where the player can buy cards, decks... -*/ + The shop is where the player can buy cards, decks... + */ #include "PrecompiledHeader.h" #include @@ -14,792 +14,920 @@ #include -float GameStateShop::_x1[] = { 79, 19, 27,103,154,187,102,144,198,133,183}; -float GameStateShop::_y1[] = {150,194,222,167,164,156,195,190,175,220,220}; +float GameStateShop::_x1[] = { 79, 19, 27, 103, 154, 187, 102, 144, 198, 133, 183 }; +float GameStateShop::_y1[] = { 150, 194, 222, 167, 164, 156, 195, 190, 175, 220, 220 }; -float GameStateShop::_x2[] = {103, 48, 74,135,183,215,138,181,231,171,225}; -float GameStateShop::_y2[] = {155,179,218,165,166,155,195,186,177,225,216}; +float GameStateShop::_x2[] = { 103, 48, 74, 135, 183, 215, 138, 181, 231, 171, 225 }; +float GameStateShop::_y2[] = { 155, 179, 218, 165, 166, 155, 195, 186, 177, 225, 216 }; -float GameStateShop::_x3[] = { 48, 61, 9, 96,139,190, 81,146,187, 97,191}; -float GameStateShop::_y3[] = {164,205,257,184,180,170,219,212,195,251,252}; +float GameStateShop::_x3[] = { 48, 61, 9, 96, 139, 190, 81, 146, 187, 97, 191 }; +float GameStateShop::_y3[] = { 164, 205, 257, 184, 180, 170, 219, 212, 195, 251, 252 }; -float GameStateShop::_x4[] = { 76, 90, 65,131,171,221,123,187,225,141,237}; -float GameStateShop::_y4[] = {169,188,250,182,182,168,220,208,198,259,245}; +float GameStateShop::_x4[] = { 76, 90, 65, 131, 171, 221, 123, 187, 225, 141, 237 }; +float GameStateShop::_y4[] = { 169, 188, 250, 182, 182, 168, 220, 208, 198, 259, 245 }; +BoosterDisplay::BoosterDisplay(int id, GameObserver* game, int x, int y, JGuiListener * listener, TargetChooser * tc, + int nb_displayed_items) : + CardDisplay(id, game, x, y, listener, tc, nb_displayed_items) +{ +} -BoosterDisplay::BoosterDisplay(int id, GameObserver* game, int x, int y, JGuiListener * listener, TargetChooser * tc, int nb_displayed_items): -CardDisplay(id, game,x,y,listener,tc,nb_displayed_items){} +bool BoosterDisplay::CheckUserInput(JButton key) +{ + if (JGE_BTN_UP == key || JGE_BTN_DOWN == key) + return false; -bool BoosterDisplay::CheckUserInput(JButton key){ - if (JGE_BTN_UP == key || JGE_BTN_DOWN == key) - return false; - - return CardDisplay::CheckUserInput(key); + return CardDisplay::CheckUserInput(key); } - -GameStateShop::GameStateShop(GameApp* parent): GameState(parent) { - menu = NULL; - for(int i=0;i<8;i++) - altThumb[i] = NULL; - mBack = NULL; - boosterDisplay = NULL; - taskList = NULL; - srcCards = NULL; - shopMenu = NULL; - bigDisplay = NULL; - myCollection = NULL; - packlist = NULL; - pricelist = NULL; - playerdata = NULL; - booster = NULL; - lightAlpha = 0; - filterMenu = NULL; - alphaChange = 0; - for(int i=0;isetElapsed(15); - srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); - srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); - - bigSync = 0; - shopMenu = NEW WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP, true, &bigSync); - MTGAllCards * ac = GameApp::collection; - playerdata = NEW PlayerData(ac); - myCollection = NEW DeckDataWrapper(playerdata->collection); - pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(),ac); - for(int i=0;imOffset.setOffset(i-BOOSTER_SLOTS); +GameStateShop::GameStateShop(GameApp* parent) : + GameState(parent) +{ + menu = NULL; + for (int i = 0; i < 8; i++) + altThumb[i] = NULL; + mBack = NULL; + boosterDisplay = NULL; + taskList = NULL; + srcCards = NULL; + shopMenu = NULL; + bigDisplay = NULL; + myCollection = NULL; + packlist = NULL; + pricelist = NULL; + playerdata = NULL; + booster = NULL; + lightAlpha = 0; + filterMenu = NULL; + alphaChange = 0; + for (int i = 0; i < SHOP_ITEMS; i++) + { + mPrices[i] = 0; + mCounts[i] = 0; } - dist->xy = WDistort(_x1[i],_y1[i],_x2[i],_y2[i],_x3[i],_y3[i],_x4[i],_y4[i]); - shopMenu->Add(NEW WGuiButton(dist,-102,i,this)); - } - shopMenu->Entering(JGE_BTN_NONE); - - if(!bigDisplay){ - bigDisplay = NEW WGuiCardImage(srcCards); - bigDisplay->mOffset.Hook(&bigSync); - bigDisplay->mOffset.setOffset(-BOOSTER_SLOTS); - bigDisplay->setX(385); - bigDisplay->setY(135); - } - - //alternateRender doesn't lock, so lock our thumbnails for hgeDistort. - altThumb[0] = resources.RetrieveTexture("artifact_thumb.jpg", RETRIEVE_LOCK); - altThumb[1] = resources.RetrieveTexture("green_thumb.jpg", RETRIEVE_LOCK); - altThumb[2] = resources.RetrieveTexture("blue_thumb.jpg", RETRIEVE_LOCK); - altThumb[3] = resources.RetrieveTexture("red_thumb.jpg", RETRIEVE_LOCK); - altThumb[4] = resources.RetrieveTexture("black_thumb.jpg", RETRIEVE_LOCK); - altThumb[5] = resources.RetrieveTexture("white_thumb.jpg", RETRIEVE_LOCK); - altThumb[6] = resources.RetrieveTexture("land_thumb.jpg", RETRIEVE_LOCK); - altThumb[7] = resources.RetrieveTexture("gold_thumb.jpg", RETRIEVE_LOCK); - - - mBack = resources.GetQuad("back"); - - JRenderer::GetInstance()->EnableVSync(true); - - taskList = NULL; - packlist = NEW MTGPacks(); - packlist->loadAll(); - load(); + mTouched = false; } -string GameStateShop::descPurchase(int controlId, bool tiny){ - char buffer[4096]; - string name; - if(controlId < BOOSTER_SLOTS){ - name = mBooster[controlId].getName(); - } - else{ - MTGCard * c = srcCards->getCard(controlId-BOOSTER_SLOTS); - if(!c) - return ""; - name = _(c->data->getName()); - } - if(mInventory[controlId] <= 0){ - if(tiny) - sprintf(buffer,_("SOLD OUT").c_str(),name.c_str()); - else - sprintf(buffer,_("%s : SOLD OUT").c_str(),name.c_str()); - return buffer; - } - - if(tiny){ - if(controlId < BOOSTER_SLOTS || mCounts[controlId] == 0) - return name; - - sprintf(buffer,_("%s (%i)").c_str(),name.c_str(),mCounts[controlId]); - return buffer; - } - switch(options[Options::ECON_DIFFICULTY].number){ - case Constants::ECON_HARD: - case Constants::ECON_NORMAL: - if(mCounts[controlId] < 1) - sprintf(buffer,_("%s").c_str(),name.c_str()); - else - sprintf(buffer,_("%s (%i)").c_str(),name.c_str(),mCounts[controlId]); - break; - default: - if(mCounts[controlId] < 1) - sprintf(buffer,_("%s : %i credits").c_str(),name.c_str(),mPrices[controlId]); - else - sprintf(buffer,_("%s (%i) : %i credits").c_str(),name.c_str(),mCounts[controlId],mPrices[controlId]); - break; - } - return buffer; +GameStateShop::~GameStateShop() +{ + End(); } -void GameStateShop::beginPurchase(int controlId){ - WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); - mFont->SetScale(DEFAULT_MENU_FONT_SCALE); - SAFE_DELETE(menu); - if(mInventory[controlId] <= 0){ - menu = NEW SimpleMenu(-145,this,Fonts::MENU_FONT,SCREEN_WIDTH-300,SCREEN_HEIGHT/2,_("Sold Out").c_str()); - menu->Add(-1,"Ok"); - } - else if(playerdata->credits - mPrices[controlId] < 0){ - menu = NEW SimpleMenu(-145,this,Fonts::MENU_FONT,SCREEN_WIDTH-300,SCREEN_HEIGHT/2,_("Not enough credits").c_str()); - menu->Add(-1,"Ok"); - if(options[Options::CHEATMODE].number) { - menu->Add(-2,"Steal it"); + +void GameStateShop::Create() +{ +} + +void GameStateShop::Start() +{ + menu = NULL; + bListCards = false; + mTouched = false; + mStage = STAGE_FADE_IN; + mElapsed = 0; + needLoad = true; + booster = NULL; + srcCards = NEW WSrcUnlockedCards(0); + srcCards->setElapsed(15); + srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); + srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); + + bigSync = 0; + shopMenu = NEW WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP, true, &bigSync); + MTGAllCards * ac = GameApp::collection; + playerdata = NEW PlayerData(ac); + myCollection = NEW DeckDataWrapper(playerdata->collection); + pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(), ac); + for (int i = 0; i < SHOP_SLOTS; i++) + { + WGuiCardDistort * dist; + if (i < BOOSTER_SLOTS) + dist = NEW WGuiCardDistort(NULL, true); + else + { + dist = NEW WGuiCardDistort(srcCards, true); + dist->mOffset.setOffset(i - BOOSTER_SLOTS); + } + dist->xy = WDistort(_x1[i], _y1[i], _x2[i], _y2[i], _x3[i], _y3[i], _x4[i], _y4[i]); + shopMenu->Add(NEW WGuiButton(dist, -102, i, this)); + } + shopMenu->Entering(JGE_BTN_NONE); + + if (!bigDisplay) + { + bigDisplay = NEW WGuiCardImage(srcCards); + bigDisplay->mOffset.Hook(&bigSync); + bigDisplay->mOffset.setOffset(-BOOSTER_SLOTS); + bigDisplay->setX(385); + bigDisplay->setY(135); + } + + //alternateRender doesn't lock, so lock our thumbnails for hgeDistort. + altThumb[0] = resources.RetrieveTexture("artifact_thumb.jpg", RETRIEVE_LOCK); + altThumb[1] = resources.RetrieveTexture("green_thumb.jpg", RETRIEVE_LOCK); + altThumb[2] = resources.RetrieveTexture("blue_thumb.jpg", RETRIEVE_LOCK); + altThumb[3] = resources.RetrieveTexture("red_thumb.jpg", RETRIEVE_LOCK); + altThumb[4] = resources.RetrieveTexture("black_thumb.jpg", RETRIEVE_LOCK); + altThumb[5] = resources.RetrieveTexture("white_thumb.jpg", RETRIEVE_LOCK); + altThumb[6] = resources.RetrieveTexture("land_thumb.jpg", RETRIEVE_LOCK); + altThumb[7] = resources.RetrieveTexture("gold_thumb.jpg", RETRIEVE_LOCK); + + mBack = resources.GetQuad("back"); + + JRenderer::GetInstance()->EnableVSync(true); + + taskList = NULL; + packlist = NEW MTGPacks(); + packlist->loadAll(); + load(); +} + +string GameStateShop::descPurchase(int controlId, bool tiny) +{ + char buffer[4096]; + string name; + if (controlId < BOOSTER_SLOTS) + { + name = mBooster[controlId].getName(); } - } - else{ - char buf[512]; - if(controlId < BOOSTER_SLOTS) - sprintf(buf,_("Purchase Booster: %i credits").c_str(),mPrices[controlId]); else - sprintf(buf,_("Purchase Card: %i credits").c_str(),mPrices[controlId]); - menu = NEW SimpleMenu(-145,this,Fonts::MENU_FONT,SCREEN_WIDTH-300,SCREEN_HEIGHT/2,buf); - - menu->Add(controlId,"Yes"); - menu->Add(-1,"No"); - } -} -void GameStateShop::cancelCard(int controlId){ - //Update prices - MTGCard * c = srcCards->getCard(controlId-BOOSTER_SLOTS); - if(!c || !c->data || playerdata->credits - mPrices[controlId] < 0) - return; //We only care about their opinion if they /can/ buy it. + { + MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS); + if (!c) + return ""; + name = _(c->data->getName()); + } + if (mInventory[controlId] <= 0) + { + if (tiny) + sprintf(buffer, _("SOLD OUT").c_str(), name.c_str()); + else + sprintf(buffer, _("%s : SOLD OUT").c_str(), name.c_str()); + return buffer; + } - int price = mPrices[controlId]; - int rnd; - switch(options[Options::ECON_DIFFICULTY].number){ + if (tiny) + { + if (controlId < BOOSTER_SLOTS || mCounts[controlId] == 0) + return name; + + sprintf(buffer, _("%s (%i)").c_str(), name.c_str(), mCounts[controlId]); + return buffer; + } + switch (options[Options::ECON_DIFFICULTY].number) + { case Constants::ECON_HARD: - rnd = rand() % 10; break; - case Constants::ECON_EASY: - rnd = rand() % 50; break; - default: - rnd = rand() % 25; break; - } - price = price - (rnd * price)/100; - if (price < pricelist->getPrice(c->getMTGId())) //filters have a tendancy to increase the price instead of lowering it! - pricelist->setPrice(c->getMTGId(),price); - //Prices do not immediately go down when you ignore something. - return; + case Constants::ECON_NORMAL: + if (mCounts[controlId] < 1) + sprintf(buffer, _("%s").c_str(), name.c_str()); + else + sprintf(buffer, _("%s (%i)").c_str(), name.c_str(), mCounts[controlId]); + break; + default: + if (mCounts[controlId] < 1) + sprintf(buffer, _("%s : %i credits").c_str(), name.c_str(), mPrices[controlId]); + else + sprintf(buffer, _("%s (%i) : %i credits").c_str(), name.c_str(), mCounts[controlId], mPrices[controlId]); + break; + } + return buffer; } -void GameStateShop::cancelBooster(int controlId){ - return; //TODO FIXME Tie boosters into pricelist. +void GameStateShop::beginPurchase(int controlId) +{ + WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); + mFont->SetScale(DEFAULT_MENU_FONT_SCALE); + SAFE_DELETE(menu); + if (mInventory[controlId] <= 0) + { + menu = NEW SimpleMenu(-145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, _("Sold Out").c_str()); + menu->Add(-1, "Ok"); + } + else if (playerdata->credits - mPrices[controlId] < 0) + { + menu = NEW SimpleMenu(-145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, _("Not enough credits").c_str()); + menu->Add(-1, "Ok"); + if (options[Options::CHEATMODE].number) + { + menu->Add(-2, "Steal it"); + } + } + else + { + char buf[512]; + if (controlId < BOOSTER_SLOTS) + sprintf(buf, _("Purchase Booster: %i credits").c_str(), mPrices[controlId]); + else + sprintf(buf, _("Purchase Card: %i credits").c_str(), mPrices[controlId]); + menu = NEW SimpleMenu(-145, this, Fonts::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, buf); + + menu->Add(controlId, "Yes"); + menu->Add(-1, "No"); + } } -void GameStateShop::purchaseCard(int controlId){ - MTGCard * c = srcCards->getCard(controlId-BOOSTER_SLOTS); - if(!c || !c->data || playerdata->credits - mPrices[controlId] < 0) - return; - myCollection->Add(c); - int price = mPrices[controlId]; - pricelist->setPrice(c->getMTGId(),price); // In case they changed their minds after cancelling. - playerdata->credits -= price; - //Update prices - int rnd; - switch(options[Options::ECON_DIFFICULTY].number){ +void GameStateShop::cancelCard(int controlId) +{ + //Update prices + MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS); + if (!c || !c->data || playerdata->credits - mPrices[controlId] < 0) + return; //We only care about their opinion if they /can/ buy it. + + int price = mPrices[controlId]; + int rnd; + switch (options[Options::ECON_DIFFICULTY].number) + { case Constants::ECON_HARD: - rnd = rand() % 50; break; + rnd = rand() % 10; + break; case Constants::ECON_EASY: - rnd = rand() % 10; break; - default: - rnd = rand() % 25; break; - } - price = price + (rnd * price)/100; - pricelist->setPrice(c->getMTGId(),price); - mPrices[controlId] = pricelist->getPurchasePrice(c->getMTGId()); //Prices go up immediately. - mInventory[controlId]--; - updateCounts(); - mTouched = true; - menu->Close(); -} -void GameStateShop::purchaseBooster(int controlId){ - if(playerdata->credits - mPrices[controlId] < 0) + rnd = rand() % 50; + break; + default: + rnd = rand() % 25; + break; + } + price = price - (rnd * price) / 100; + if (price < pricelist->getPrice(c->getMTGId())) //filters have a tendancy to increase the price instead of lowering it! + pricelist->setPrice(c->getMTGId(), price); + //Prices do not immediately go down when you ignore something. return; - playerdata->credits -= mPrices[controlId]; - mInventory[controlId]--; - SAFE_DELETE(booster); - deleteDisplay(); - booster = NEW MTGDeck(mParent->collection); - boosterDisplay = NEW BoosterDisplay(12,NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT/2,this,NULL,5); - mBooster[controlId].addToDeck(booster,srcCards); - - string sort = mBooster[controlId].getSort(); - DeckDataWrapper * ddw = NEW DeckDataWrapper(booster); - if(sort == "alpha") - ddw->Sort(WSrcCards::SORT_ALPHA); - else if(sort == "collector") - ddw->Sort(WSrcCards::SORT_COLLECTOR); - else - ddw->Sort(WSrcCards::SORT_RARITY); - for (int x=0;xSize();x++){ - MTGCard * c = ddw->getCard(x); - MTGCardInstance * ci = NEW MTGCardInstance(c, NULL); - boosterDisplay->AddCard(ci); - subBooster.push_back(ci); - } - SAFE_DELETE(ddw); +} +void GameStateShop::cancelBooster(int controlId) +{ + return; //TODO FIXME Tie boosters into pricelist. +} +void GameStateShop::purchaseCard(int controlId) +{ + MTGCard * c = srcCards->getCard(controlId - BOOSTER_SLOTS); + if (!c || !c->data || playerdata->credits - mPrices[controlId] < 0) + return; + myCollection->Add(c); + int price = mPrices[controlId]; + pricelist->setPrice(c->getMTGId(), price); // In case they changed their minds after cancelling. + playerdata->credits -= price; + //Update prices + int rnd; + switch (options[Options::ECON_DIFFICULTY].number) + { + case Constants::ECON_HARD: + rnd = rand() % 50; + break; + case Constants::ECON_EASY: + rnd = rand() % 10; + break; + default: + rnd = rand() % 25; + break; + } + price = price + (rnd * price) / 100; + pricelist->setPrice(c->getMTGId(), price); + mPrices[controlId] = pricelist->getPurchasePrice(c->getMTGId()); //Prices go up immediately. + mInventory[controlId]--; + updateCounts(); + mTouched = true; + menu->Close(); +} +void GameStateShop::purchaseBooster(int controlId) +{ + if (playerdata->credits - mPrices[controlId] < 0) + return; + playerdata->credits -= mPrices[controlId]; + mInventory[controlId]--; + SAFE_DELETE(booster); + deleteDisplay(); + booster = NEW MTGDeck(mParent->collection); + boosterDisplay = NEW BoosterDisplay(12, NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT / 2, this, NULL, 5); + mBooster[controlId].addToDeck(booster, srcCards); - myCollection->loadMatches(booster); - mTouched = true; - save(true); - menu->Close(); + string sort = mBooster[controlId].getSort(); + DeckDataWrapper * ddw = NEW DeckDataWrapper(booster); + if (sort == "alpha") + ddw->Sort(WSrcCards::SORT_ALPHA); + else if (sort == "collector") + ddw->Sort(WSrcCards::SORT_COLLECTOR); + else + ddw->Sort(WSrcCards::SORT_RARITY); + for (int x = 0; x < ddw->Size(); x++) + { + MTGCard * c = ddw->getCard(x); + MTGCardInstance * ci = NEW MTGCardInstance(c, NULL); + boosterDisplay->AddCard(ci); + subBooster.push_back(ci); + } + SAFE_DELETE(ddw); + + myCollection->loadMatches(booster); + mTouched = true; + save(true); + menu->Close(); } -int GameStateShop::purchasePrice(int offset){ - MTGCard * c = NULL; - if(!pricelist || !srcCards || (c = srcCards->getCard(offset)) == NULL) - return 0; - float price = (float) pricelist->getPurchasePrice(c->getMTGId()); - int filteradd = srcCards->Size(true); - filteradd = ((filteradd - srcCards->Size())/filteradd); - - switch(options[Options::ECON_DIFFICULTY].number){ - case Constants::ECON_EASY: filteradd /= 2; break; - case Constants::ECON_HARD: filteradd *= 2; break; - default: break; - } - return (int) (price + price * (filteradd * srcCards->filterFee() )); -} -void GameStateShop::updateCounts(){ - for(int i=BOOSTER_SLOTS;igetCard(i-BOOSTER_SLOTS); - if(!c) mCounts[i] = 0; - else mCounts[i] = myCollection->countByName(c); - } -} -void GameStateShop::load(){ - int nbsets = 0; - int nbboostersets = 0; - - for(int i=0;igetOtherPrice(mBooster[i].basePrice()); - } - for(int i=BOOSTER_SLOTS;igetCard(i-BOOSTER_SLOTS)) == NULL){ - mPrices[i] = 0; - mCounts[i] = 0; - mInventory[i] = 0; - continue; - } - mPrices[i] = purchasePrice(i-BOOSTER_SLOTS); - mCounts[i] = myCollection->countByName(c); - switch(c->getRarity()){ - case Constants::RARITY_C: - mInventory[i] = 2 + rand() % 8; - break; - case Constants::RARITY_L: - mInventory[i] = 100; - break; - default: //We're using some non-coded rarities (S) in cards.dat. - case Constants::RARITY_U: - mInventory[i] = 1 + rand() % 5; - break; - case Constants::RARITY_R: - mInventory[i] = 1 + rand() % 2; - break; - } + if (!pricelist || !srcCards || (c = srcCards->getCard(offset)) == NULL) + return 0; + float price = (float) pricelist->getPurchasePrice(c->getMTGId()); + int filteradd = srcCards->Size(true); + filteradd = ((filteradd - srcCards->Size()) / filteradd); - } + switch (options[Options::ECON_DIFFICULTY].number) + { + case Constants::ECON_EASY: + filteradd /= 2; + break; + case Constants::ECON_HARD: + filteradd *= 2; + break; + default: + break; + } + return (int) (price + price * (filteradd * srcCards->filterFee())); +} +void GameStateShop::updateCounts() +{ + for (int i = BOOSTER_SLOTS; i < SHOP_ITEMS; i++) + { + MTGCard * c = srcCards->getCard(i - BOOSTER_SLOTS); + if (!c) + mCounts[i] = 0; + else + mCounts[i] = myCollection->countByName(c); + } +} +void GameStateShop::load() +{ + int nbsets = 0; + int nbboostersets = 0; + + for (int i = 0; i < BOOSTER_SLOTS; i++) + { + mBooster[i].randomize(packlist); + mInventory[i] = 1 + rand() % mBooster[i].maxInventory(); + mPrices[i] = pricelist->getOtherPrice(mBooster[i].basePrice()); + } + for (int i = BOOSTER_SLOTS; i < SHOP_ITEMS; i++) + { + MTGCard * c = NULL; + if ((c = srcCards->getCard(i - BOOSTER_SLOTS)) == NULL) + { + mPrices[i] = 0; + mCounts[i] = 0; + mInventory[i] = 0; + continue; + } + mPrices[i] = purchasePrice(i - BOOSTER_SLOTS); + mCounts[i] = myCollection->countByName(c); + switch (c->getRarity()) + { + case Constants::RARITY_C: + mInventory[i] = 2 + rand() % 8; + break; + case Constants::RARITY_L: + mInventory[i] = 100; + break; + default: //We're using some non-coded rarities (S) in cards.dat. + case Constants::RARITY_U: + mInventory[i] = 1 + rand() % 5; + break; + case Constants::RARITY_R: + mInventory[i] = 1 + rand() % 2; + break; + } + + } } void GameStateShop::save(bool force) { - if(mTouched || force){ - if(myCollection) - myCollection->Rebuild(playerdata->collection); - if(playerdata) - playerdata->save(); - if(pricelist) - pricelist->save(); - } - mTouched = false; + if (mTouched || force) + { + if (myCollection) + myCollection->Rebuild(playerdata->collection); + if (playerdata) + playerdata->save(); + if (pricelist) + pricelist->save(); + } + mTouched = false; } void GameStateShop::End() { - save(); - JRenderer::GetInstance()->EnableVSync(false); - mElapsed = 0; - SAFE_DELETE(shopMenu); - SAFE_DELETE(bigDisplay); - SAFE_DELETE(srcCards); - SAFE_DELETE(playerdata); - SAFE_DELETE(pricelist); - SAFE_DELETE(myCollection); - SAFE_DELETE(booster); - SAFE_DELETE(filterMenu); - SAFE_DELETE(packlist); - deleteDisplay(); + save(); + JRenderer::GetInstance()->EnableVSync(false); + mElapsed = 0; + SAFE_DELETE(shopMenu); + SAFE_DELETE(bigDisplay); + SAFE_DELETE(srcCards); + SAFE_DELETE(playerdata); + SAFE_DELETE(pricelist); + SAFE_DELETE(myCollection); + SAFE_DELETE(booster); + SAFE_DELETE(filterMenu); + SAFE_DELETE(packlist); + deleteDisplay(); - //Release alternate thumbnails. - for(int i=0;i<8;i++){ - resources.Release(altThumb[i]); - altThumb[i] = NULL; - } + //Release alternate thumbnails. + for (int i = 0; i < 8; i++) + { + resources.Release(altThumb[i]); + altThumb[i] = NULL; + } - SAFE_DELETE(menu); - SAFE_DELETE(taskList); + SAFE_DELETE(menu); + SAFE_DELETE(taskList); } -void GameStateShop::Destroy(){ +void GameStateShop::Destroy() +{ } -void GameStateShop::beginFilters(){ - if(!filterMenu){ - filterMenu = NEW WGuiFilters("Ask about...",srcCards); - filterMenu->setY(2); - filterMenu->setHeight(SCREEN_HEIGHT-2); - } - mStage = STAGE_ASK_ABOUT; - filterMenu->Entering(JGE_BTN_NONE); +void GameStateShop::beginFilters() +{ + if (!filterMenu) + { + filterMenu = NEW WGuiFilters("Ask about...", srcCards); + filterMenu->setY(2); + filterMenu->setHeight(SCREEN_HEIGHT - 2); + } + mStage = STAGE_ASK_ABOUT; + filterMenu->Entering(JGE_BTN_NONE); } void GameStateShop::Update(float dt) { - if (menu && menu->closed) - SAFE_DELETE(menu); - srcCards->Update(dt); - alphaChange = static_cast(500 - (int)((rand() % 1000)) * dt); - lightAlpha+= alphaChange; - if (lightAlpha < 0) lightAlpha = 0; - if (lightAlpha > 50) lightAlpha = 50; - // mParent->effect->UpdateSmall(dt); - // mParent->effect->UpdateBig(dt); - if (mStage != STAGE_FADE_IN) - mElapsed += dt; + if (menu && menu->closed) + SAFE_DELETE(menu); + srcCards->Update(dt); + alphaChange = static_cast (500 - (int) ((rand() % 1000)) * dt); + lightAlpha += alphaChange; + if (lightAlpha < 0) + lightAlpha = 0; + if (lightAlpha > 50) + lightAlpha = 50; + // mParent->effect->UpdateSmall(dt); + // mParent->effect->UpdateBig(dt); + if (mStage != STAGE_FADE_IN) + mElapsed += dt; - JButton btn; - switch(mStage){ + JButton btn; + switch (mStage) + { case STAGE_SHOP_PURCHASE: - if (menu) - menu->Update(dt); - beginPurchase(mBuying); - mStage = STAGE_SHOP_SHOP; - break; + if (menu) + menu->Update(dt); + beginPurchase(mBuying); + mStage = STAGE_SHOP_SHOP; + break; case STAGE_SHOP_MENU: - if (menu) - menu->Update(dt); - else{ - menu = NEW SimpleMenu(11,this,Fonts::MENU_FONT,SCREEN_WIDTH/2-100,20); - menu->Add(22,"Ask about..."); - menu->Add(14,"Check task board"); - if (options[Options::CHEATMODE].number) - menu->Add(-2,"Steal 1,000 credits"); - menu->Add(12,"Save & Back to Main Menu"); - menu->Add(kCancelMenuID, "Cancel"); - } - break; - case STAGE_SHOP_TASKS: - if (menu){ - menu->Update(dt); - return; - } - if (taskList){ - btn = mEngine->ReadButton(); - taskList->Update(dt); - if ( taskList->getState() != TaskList::TASKS_INACTIVE){ - if ( btn == JGE_BTN_SEC || btn == JGE_BTN_CANCEL || btn == JGE_BTN_PREV ){ - taskList->End(); - return; - } else if (taskList->getState() == TaskList::TASKS_ACTIVE && btn == JGE_BTN_MENU){ - if (!menu) { - menu = NEW SimpleMenu(11,this,Fonts::MENU_FONT,SCREEN_WIDTH/2-100,20); - menu->Add(15,"Return to shop"); - menu->Add(12,"Save & Back to Main Menu"); - menu->Add(kCancelMenuID, "Cancel"); - } - } - } + if (menu) + menu->Update(dt); else - mStage = STAGE_SHOP_SHOP; - } + { + menu = NEW SimpleMenu(11, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 20); + menu->Add(22, "Ask about..."); + menu->Add(14, "Check task board"); + if (options[Options::CHEATMODE].number) + menu->Add(-2, "Steal 1,000 credits"); + menu->Add(12, "Save & Back to Main Menu"); + menu->Add(kCancelMenuID, "Cancel"); + } + break; + case STAGE_SHOP_TASKS: + if (menu) + { + menu->Update(dt); + return; + } + if (taskList) + { + btn = mEngine->ReadButton(); + taskList->Update(dt); + if (taskList->getState() != TaskList::TASKS_INACTIVE) + { + if (btn == JGE_BTN_SEC || btn == JGE_BTN_CANCEL || btn == JGE_BTN_PREV) + { + taskList->End(); + return; + } + else if (taskList->getState() == TaskList::TASKS_ACTIVE && btn == JGE_BTN_MENU) + { + if (!menu) + { + menu = NEW SimpleMenu(11, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 20); + menu->Add(15, "Return to shop"); + menu->Add(12, "Save & Back to Main Menu"); + menu->Add(kCancelMenuID, "Cancel"); + } + } + } + else + mStage = STAGE_SHOP_SHOP; + } #ifdef TESTSUITE - if ((mEngine->GetButtonClick(JGE_BTN_PRI)) && (taskList)) { - taskList->passOneDay(); - if (taskList->getTaskCount() < 6) { - taskList->addRandomTask(); - taskList->addRandomTask(); - } - taskList->save(); - } -#endif - break; - case STAGE_ASK_ABOUT: - btn = mEngine->ReadButton(); - if (menu && !menu->closed){ - menu->CheckUserInput(btn); - menu->Update(dt); - return; - } - if (filterMenu){ - if (btn == JGE_BTN_CTRL) { - needLoad = filterMenu->Finish(); - filterMenu->Update(dt); - return; - } - if (filterMenu->isFinished()){ - if (needLoad){ - srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); - srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); - if(!srcCards->Size()){ - srcCards->clearFilters(); //Repetition of check at end of filterMenu->Finish(), for the token removal - srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); - srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); + if ((mEngine->GetButtonClick(JGE_BTN_PRI)) && (taskList)) + { + taskList->passOneDay(); + if (taskList->getTaskCount() < 6) + { + taskList->addRandomTask(); + taskList->addRandomTask(); } - load(); - } - mStage = STAGE_SHOP_SHOP; - }else{ - filterMenu->CheckUserInput(btn); - filterMenu->Update(dt); + taskList->save(); } - return; - } - break; +#endif + break; + case STAGE_ASK_ABOUT: + btn = mEngine->ReadButton(); + if (menu && !menu->closed) + { + menu->CheckUserInput(btn); + menu->Update(dt); + return; + } + if (filterMenu) + { + if (btn == JGE_BTN_CTRL) + { + needLoad = filterMenu->Finish(); + filterMenu->Update(dt); + return; + } + if (filterMenu->isFinished()) + { + if (needLoad) + { + srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); + srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); + if (!srcCards->Size()) + { + srcCards->clearFilters(); //Repetition of check at end of filterMenu->Finish(), for the token removal + srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterRarity("T"))); + srcCards->addFilter(NEW WCFilterNOT(NEW WCFilterSet(MTGSets::INTERNAL_SET))); + } + load(); + } + mStage = STAGE_SHOP_SHOP; + } + else + { + filterMenu->CheckUserInput(btn); + filterMenu->Update(dt); + } + return; + } + break; case STAGE_SHOP_SHOP: - btn = mEngine->ReadButton(); - if (menu && !menu->closed){ - menu->CheckUserInput(btn); - menu->Update(dt); - return; - } - if (btn == JGE_BTN_MENU){ - if (boosterDisplay){ - deleteDisplay(); - return; + btn = mEngine->ReadButton(); + if (menu && !menu->closed) + { + menu->CheckUserInput(btn); + menu->Update(dt); + return; } - mStage = STAGE_SHOP_MENU; - return; - } else if (btn == JGE_BTN_CTRL) - beginFilters(); - else if(btn == JGE_BTN_NEXT){ - mStage = STAGE_SHOP_TASKS; - if (!taskList) - taskList = NEW TaskList(); - taskList->Start(); - } - else if (btn == JGE_BTN_PRI) { - srcCards->Shuffle(); - load(); - } else if (btn == JGE_BTN_CANCEL) - options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; - else if (boosterDisplay){ - if (btn == JGE_BTN_SEC) - deleteDisplay(); - else { - boosterDisplay->CheckUserInput(btn); - boosterDisplay->Update(dt);} - return; - }else if (btn == JGE_BTN_SEC) - bListCards = !bListCards; - else if (shopMenu){ - if (shopMenu->CheckUserInput(btn)) - srcCards->Touch(); - } - if (shopMenu) - shopMenu->Update(dt); + if (btn == JGE_BTN_MENU) + { + if (boosterDisplay) + { + deleteDisplay(); + return; + } + mStage = STAGE_SHOP_MENU; + return; + } + else if (btn == JGE_BTN_CTRL) + beginFilters(); + else if (btn == JGE_BTN_NEXT) + { + mStage = STAGE_SHOP_TASKS; + if (!taskList) + taskList = NEW TaskList(); + taskList->Start(); + } + else if (btn == JGE_BTN_PRI) + { + srcCards->Shuffle(); + load(); + } + else if (btn == JGE_BTN_CANCEL) + options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; + else if (boosterDisplay) + { + if (btn == JGE_BTN_SEC) + deleteDisplay(); + else + { + boosterDisplay->CheckUserInput(btn); + boosterDisplay->Update(dt); + } + return; + } + else if (btn == JGE_BTN_SEC) + bListCards = !bListCards; + else if (shopMenu) + { + if (shopMenu->CheckUserInput(btn)) + srcCards->Touch(); + } + if (shopMenu) + shopMenu->Update(dt); - break; + break; case STAGE_FADE_IN: - mParent->DoAnimation(TRANSITION_FADE_IN); - mStage = STAGE_SHOP_SHOP; - break; - } + mParent->DoAnimation(TRANSITION_FADE_IN); + mStage = STAGE_SHOP_SHOP; + break; + } } -void GameStateShop::deleteDisplay(){ - vector::iterator i; - for(i=subBooster.begin();i!=subBooster.end();i++){ - if (!*i) continue; - delete *i; - } - subBooster.clear(); - SAFE_DELETE(boosterDisplay); +void GameStateShop::deleteDisplay() +{ + vector::iterator i; + for (i = subBooster.begin(); i != subBooster.end(); i++) + { + if (!*i) + continue; + delete *i; + } + subBooster.clear(); + SAFE_DELETE(boosterDisplay); } void GameStateShop::Render() { - //Erase - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - JRenderer * r = JRenderer::GetInstance(); - r->ClearScreen(ARGB(0,0,0,0)); - if(mStage == STAGE_FADE_IN) - return; + //Erase + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + JRenderer * r = JRenderer::GetInstance(); + r->ClearScreen(ARGB(0,0,0,0)); + if (mStage == STAGE_FADE_IN) + return; - JQuad * mBg = resources.RetrieveTempQuad("shop.jpg",TEXTURE_SUB_5551); - if (mBg) - r->RenderQuad(mBg,0,0); + JQuad * mBg = resources.RetrieveTempQuad("shop.jpg", TEXTURE_SUB_5551); + if (mBg) + r->RenderQuad(mBg, 0, 0); - JQuad * quad = resources.RetrieveTempQuad("shop_light.jpg",TEXTURE_SUB_5551); - if (quad){ - r->EnableTextureFilter(false); - r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); - quad->SetColor(ARGB(lightAlpha,255,255,255)); - r->RenderQuad(quad,0,0); - r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - r->EnableTextureFilter(true); - } - - if(shopMenu) - shopMenu->Render(); - if(filterMenu && !filterMenu->isFinished()) - filterMenu->Render(); - else{ - if(boosterDisplay) - boosterDisplay->Render(); - else if(bigDisplay){ - if(bigDisplay->mOffset.getPos() >= 0) - bigDisplay->setSource(srcCards); - else - bigDisplay->setSource(NULL); - bigDisplay->Render(); - float elp = srcCards->getElapsed(); - //Render the card list overlay. - if( bListCards || elp > LIST_FADEIN){ - int alpha = 200; - if(!bListCards && elp < LIST_FADEIN+.25){ - alpha = static_cast(800 *(elp-LIST_FADEIN)); - } - r->FillRoundRect(300,10, 160, SHOP_SLOTS * 20 + 15,5,ARGB(alpha,0,0,0)); - alpha += 55; - for(int i = 0; i < SHOP_SLOTS; i++){ - if (i == shopMenu->getSelected()) - mFont->SetColor(ARGB(alpha,255,255,0)); - else - mFont->SetColor(ARGB(alpha,255,255,255)); - char buffer[512]; - string s = descPurchase(i,true); - sprintf(buffer, "%s", s.c_str()); - float x = 310; - float y = static_cast(25 + 20*i); - mFont->DrawString(buffer,x,y); - } - } + JQuad * quad = resources.RetrieveTempQuad("shop_light.jpg", TEXTURE_SUB_5551); + if (quad) + { + r->EnableTextureFilter(false); + r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); + quad->SetColor(ARGB(lightAlpha,255,255,255)); + r->RenderQuad(quad, 0, 0); + r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + r->EnableTextureFilter(true); } - } - //Render the info bar - r->FillRect(0,SCREEN_HEIGHT-17,SCREEN_WIDTH,17,ARGB(128,0,0,0)); - char c[512]; - sprintf(c,_("credits: %i").c_str(), playerdata->credits); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(c, 5, SCREEN_HEIGHT - 12); - sprintf(c, "%s", _("[]:other cards").c_str()); - float len = 4 + mFont->GetStringWidth(c); - mFont->DrawString(c,SCREEN_WIDTH-len,SCREEN_HEIGHT-14); + if (shopMenu) + shopMenu->Render(); + if (filterMenu && !filterMenu->isFinished()) + filterMenu->Render(); + else + { + if (boosterDisplay) + boosterDisplay->Render(); + else if (bigDisplay) + { + if (bigDisplay->mOffset.getPos() >= 0) + bigDisplay->setSource(srcCards); + else + bigDisplay->setSource(NULL); + bigDisplay->Render(); + float elp = srcCards->getElapsed(); + //Render the card list overlay. + if (bListCards || elp > LIST_FADEIN) + { + int alpha = 200; + if (!bListCards && elp < LIST_FADEIN + .25) + { + alpha = static_cast (800 * (elp - LIST_FADEIN)); + } + r->FillRoundRect(300, 10, 160, SHOP_SLOTS * 20 + 15, 5, ARGB(alpha,0,0,0)); + alpha += 55; + for (int i = 0; i < SHOP_SLOTS; i++) + { + if (i == shopMenu->getSelected()) + mFont->SetColor(ARGB(alpha,255,255,0)); + else + mFont->SetColor(ARGB(alpha,255,255,255)); + char buffer[512]; + string s = descPurchase(i, true); + sprintf(buffer, "%s", s.c_str()); + float x = 310; + float y = static_cast (25 + 20 * i); + mFont->DrawString(buffer, x, y); + } + } + } + } - mFont->SetColor(ARGB(255,255,255,0)); - mFont->DrawString(descPurchase(bigSync.getPos()).c_str(), SCREEN_WIDTH/2, SCREEN_HEIGHT - 14,JGETEXT_CENTER); - mFont->SetColor(ARGB(255,255,255,255)); + //Render the info bar + r->FillRect(0, SCREEN_HEIGHT - 17, SCREEN_WIDTH, 17, ARGB(128,0,0,0)); + char c[512]; + sprintf(c, _("credits: %i").c_str(), playerdata->credits); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(c, 5, SCREEN_HEIGHT - 12); + sprintf(c, "%s", _("[]:other cards").c_str()); + float len = 4 + mFont->GetStringWidth(c); + mFont->DrawString(c, SCREEN_WIDTH - len, SCREEN_HEIGHT - 14); - if (mStage == STAGE_SHOP_TASKS && taskList) { - taskList->Render(); - } - if (menu) - menu->Render(); + mFont->SetColor(ARGB(255,255,255,0)); + mFont->DrawString(descPurchase(bigSync.getPos()).c_str(), SCREEN_WIDTH / 2, SCREEN_HEIGHT - 14, JGETEXT_CENTER); + mFont->SetColor(ARGB(255,255,255,255)); + + if (mStage == STAGE_SHOP_TASKS && taskList) + { + taskList->Render(); + } + if (menu) + menu->Render(); } void GameStateShop::ButtonPressed(int controllerId, int controlId) { - int sel = bigSync.getOffset(); + int sel = bigSync.getOffset(); - switch(controllerId){ + switch (controllerId) + { case -102: //Buying something... - mStage = STAGE_SHOP_PURCHASE; - if(menu) - menu->Close(); - mBuying = controlId; - return; - case -145: - if(controlId == -1){ //Nope, don't buy. - if(sel < BOOSTER_SLOTS) - cancelBooster(sel); - else - cancelCard(sel); - menu->Close(); + mStage = STAGE_SHOP_PURCHASE; + if (menu) + menu->Close(); + mBuying = controlId; + return; + case -145: + if (controlId == -1) + { //Nope, don't buy. + if (sel < BOOSTER_SLOTS) + cancelBooster(sel); + else + cancelCard(sel); + menu->Close(); + mStage = STAGE_SHOP_SHOP; + return; + } + if (sel > -1 && sel < SHOP_ITEMS) + { + if (controlId == -2) + playerdata->credits += mPrices[sel]; //We stole it. + if (sel < BOOSTER_SLOTS) //Clicked a booster. + purchaseBooster(sel); + else + purchaseCard(sel); + } mStage = STAGE_SHOP_SHOP; return; - } - if(sel > -1 && sel < SHOP_ITEMS){ - if(controlId == -2) - playerdata->credits += mPrices[sel]; //We stole it. - if(sel < BOOSTER_SLOTS) //Clicked a booster. - purchaseBooster(sel); - else - purchaseCard(sel); - } - mStage = STAGE_SHOP_SHOP; - return; - } - //Basic Menu. - switch(controlId){ - case 12: - if (taskList) taskList->save(); - mStage = STAGE_SHOP_SHOP; - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - save(); - break; - case 14: - mStage = STAGE_SHOP_TASKS; - if (!taskList) - taskList = NEW TaskList(); - taskList->Start(); - break; - case 15: - if(taskList) - taskList->End(); - break; - case 22: - beginFilters(); - break; - case -2: - playerdata->credits += 1000; - default: - mStage = STAGE_SHOP_SHOP; - } - menu->Close(); + } + //Basic Menu. + switch (controlId) + { + case 12: + if (taskList) + taskList->save(); + mStage = STAGE_SHOP_SHOP; + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + save(); + break; + case 14: + mStage = STAGE_SHOP_TASKS; + if (!taskList) + taskList = NEW TaskList(); + taskList->Start(); + break; + case 15: + if (taskList) + taskList->End(); + break; + case 22: + beginFilters(); + break; + case -2: + playerdata->credits += 1000; + default: + mStage = STAGE_SHOP_SHOP; + } + menu->Close(); } //ShopBooster -ShopBooster::ShopBooster(){ - pack = NULL; - mainSet = NULL; - altSet = NULL; +ShopBooster::ShopBooster() +{ + pack = NULL; + mainSet = NULL; + altSet = NULL; } -string ShopBooster::getSort() { - if(pack) - return pack->getSort(); - return ""; -}; -string ShopBooster::getName(){ - char buffer[512]; - if(!mainSet && pack) return pack->getName(); - if(altSet == mainSet) altSet = NULL; - if(altSet) - sprintf(buffer,_("%s & %s (15 Cards)").c_str(),mainSet->id.c_str(),altSet->id.c_str()); - else if(mainSet) - sprintf(buffer,_("%s Booster (15 Cards)").c_str(),mainSet->id.c_str()); - return buffer; +string ShopBooster::getSort() +{ + if (pack) + return pack->getSort(); + return ""; +} +; +string ShopBooster::getName() +{ + char buffer[512]; + if (!mainSet && pack) + return pack->getName(); + if (altSet == mainSet) + altSet = NULL; + if (altSet) + sprintf(buffer, _("%s & %s (15 Cards)").c_str(), mainSet->id.c_str(), altSet->id.c_str()); + else if (mainSet) + sprintf(buffer, _("%s Booster (15 Cards)").c_str(), mainSet->id.c_str()); + return buffer; } -void ShopBooster::randomize(MTGPacks * packlist){ - mainSet = NULL; altSet = NULL; pack = NULL; - if(!setlist.size()) return; - if(packlist && setlist.size() > 10){ //FIXME make these an unlockable item. - int rnd = rand() % 100; - if(rnd <= Constants::CHANCE_CUSTOM_PACK){ - randomCustom(packlist); - return; - } - } - randomStandard(); -} -int ShopBooster::basePrice(){ - if(pack) - return pack->getPrice(); - else if(altSet) - return Constants::PRICE_MIXED_BOOSTER; - return Constants::PRICE_BOOSTER; -} -void ShopBooster::randomCustom(MTGPacks * packlist){ - pack = packlist->randomPack(); - if(pack && !pack->isUnlocked()) +void ShopBooster::randomize(MTGPacks * packlist) +{ + mainSet = NULL; + altSet = NULL; pack = NULL; - if(!pack) + if (!setlist.size()) + return; + if (packlist && setlist.size() > 10) + { //FIXME make these an unlockable item. + int rnd = rand() % 100; + if (rnd <= Constants::CHANCE_CUSTOM_PACK) + { + randomCustom(packlist); + return; + } + } randomStandard(); } -void ShopBooster::randomStandard(){ - int mSet = -1; - MTGSetInfo * si = setlist.randomSet(-1); - mainSet = si; - altSet = NULL; - - int mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS]; - if(mSetCount < 80){ - if(rand() % 100 < Constants::CHANCE_PURE_OVERRIDE){ //Chance of picking a pure pack instead. - si = setlist.randomSet(-1,80); - mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS]; - mainSet = si; - }else - altSet = setlist.randomSet(si->block,80-mSetCount); - } - else if(rand() % 100 < Constants::CHANCE_MIXED_OVERRIDE) //Chance of having a mixed booster anyways. - altSet = setlist.randomSet(si->block); - - for(int attempts=0;attempts<10;attempts++){ //Try to prevent altSet == mainSet. - if(altSet != mainSet) break; - altSet = setlist.randomSet(-1,80-mSetCount); - } - if(altSet == mainSet) altSet = NULL; //Prevent "10E & 10E Booster" - if(!altSet) pack = mainSet->mPack; - +int ShopBooster::basePrice() +{ + if (pack) + return pack->getPrice(); + else if (altSet) + return Constants::PRICE_MIXED_BOOSTER; + return Constants::PRICE_BOOSTER; } -int ShopBooster::maxInventory(){ - if(altSet || pack) - return 2; - return 5; -} -void ShopBooster::addToDeck(MTGDeck * d, WSrcCards * srcCards){ - if(!pack){ //A combination booster. - MTGPack * mP = MTGPacks::getDefault(); - if(!altSet && mainSet->mPack) mP = mainSet->mPack; - char buf[512]; - if(!altSet) sprintf(buf,"set:%s;",mainSet->id.c_str()); - else sprintf(buf,"set:%s;|set:%s;",mainSet->id.c_str(),altSet->id.c_str()); - mP->pool = buf; - mP->assemblePack(d); //Use the primary packfile. assemblePack deletes pool. - } - else - pack->assemblePack(d); +void ShopBooster::randomCustom(MTGPacks * packlist) +{ + pack = packlist->randomPack(); + if (pack && !pack->isUnlocked()) + pack = NULL; + if (!pack) + randomStandard(); } +void ShopBooster::randomStandard() +{ + int mSet = -1; + MTGSetInfo * si = setlist.randomSet(-1); + mainSet = si; + altSet = NULL; + int mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS]; + if (mSetCount < 80) + { + if (rand() % 100 < Constants::CHANCE_PURE_OVERRIDE) + { //Chance of picking a pure pack instead. + si = setlist.randomSet(-1, 80); + mSetCount = si->counts[MTGSetInfo::TOTAL_CARDS]; + mainSet = si; + } + else + altSet = setlist.randomSet(si->block, 80 - mSetCount); + } + else if (rand() % 100 < Constants::CHANCE_MIXED_OVERRIDE) //Chance of having a mixed booster anyways. + altSet = setlist.randomSet(si->block); + + for (int attempts = 0; attempts < 10; attempts++) + { //Try to prevent altSet == mainSet. + if (altSet != mainSet) + break; + altSet = setlist.randomSet(-1, 80 - mSetCount); + } + if (altSet == mainSet) + altSet = NULL; //Prevent "10E & 10E Booster" + if (!altSet) + pack = mainSet->mPack; + +} +int ShopBooster::maxInventory() +{ + if (altSet || pack) + return 2; + return 5; +} +void ShopBooster::addToDeck(MTGDeck * d, WSrcCards * srcCards) +{ + if (!pack) + { //A combination booster. + MTGPack * mP = MTGPacks::getDefault(); + if (!altSet && mainSet->mPack) + mP = mainSet->mPack; + char buf[512]; + if (!altSet) + sprintf(buf, "set:%s;", mainSet->id.c_str()); + else + sprintf(buf, "set:%s;|set:%s;", mainSet->id.c_str(), altSet->id.c_str()); + mP->pool = buf; + mP->assemblePack(d); //Use the primary packfile. assemblePack deletes pool. + } + else + pack->assemblePack(d); +} #ifdef TESTSUITE -bool ShopBooster::unitTest(){ +bool ShopBooster::unitTest() +{ //this tests the default random pack creation. MTGDeck * d = NEW MTGDeck(GameApp::collection); char result[1024]; @@ -817,24 +945,27 @@ bool ShopBooster::unitTest(){ int u = 0, r = 0; int card = 0; - for(int i=0;iSize(true);i++){ + for(int i=0;iSize(true);i++) + { MTGCard * c = ddw->getCard(i); if(!c) break; if(c->getRarity() == Constants::RARITY_R || c->getRarity() == Constants::RARITY_M) - r+=ddw->count(c); + r+=ddw->count(c); else if(c->getRarity() == Constants::RARITY_U) - u+=ddw->count(c); + u+=ddw->count(c); card++; } int count = ddw->getCount(); SAFE_DELETE(ddw); SAFE_DELETE(d); - if(r != 1 || u != 3 ){ + if(r != 1 || u != 3 ) + { sprintf(result, "==Unexpected rarity count==
"); TestSuite::Log(result); res = false; } - if(count < 14) { + if(count < 14) + { sprintf(result, "==Unexpected card count==
"); TestSuite::Log(result); res = false; @@ -845,4 +976,4 @@ bool ShopBooster::unitTest(){ SAFE_DELETE(d); return res; } - #endif \ No newline at end of file +#endif diff --git a/projects/mtg/src/GameStateStory.cpp b/projects/mtg/src/GameStateStory.cpp index d9a80e408..09d8175cb 100644 --- a/projects/mtg/src/GameStateStory.cpp +++ b/projects/mtg/src/GameStateStory.cpp @@ -6,106 +6,132 @@ #include "GameApp.h" #include -GameStateStory::GameStateStory(GameApp* parent): GameState(parent) { - flow = NULL; - menu = NULL; +GameStateStory::GameStateStory(GameApp* parent) : + GameState(parent) +{ + flow = NULL; + menu = NULL; } -GameStateStory::~GameStateStory() { - End(); +GameStateStory::~GameStateStory() +{ + End(); } - -void GameStateStory::loadStoriesMenu(const char * root){ - SAFE_DELETE(menu); - stories.clear(); - DIR *mDip; - struct dirent *mDit; +void GameStateStory::loadStoriesMenu(const char * root) +{ + SAFE_DELETE(menu); + stories.clear(); + DIR *mDip; + struct dirent *mDit; - mDip = opendir(root); + mDip = opendir(root); - while ((mDit = readdir(mDip))){ - char buffer[4096]; - sprintf(buffer, "%s%s/story.xml", root, mDit->d_name); - std::ifstream file(buffer); - if(file){ - string fname = mDit->d_name; - stories.push_back(fname); - file.close(); + while ((mDit = readdir(mDip))) + { + char buffer[4096]; + sprintf(buffer, "%s%s/story.xml", root, mDit->d_name); + std::ifstream file(buffer); + if (file) + { + string fname = mDit->d_name; + stories.push_back(fname); + file.close(); + } } - } - closedir(mDip); - - switch(stories.size()){ + closedir(mDip); + + switch (stories.size()) + { case 0: - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - break; + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + break; case 1: - flow = NEW StoryFlow(stories[0]); - break; + flow = NEW StoryFlow(stories[0]); + break; default: - menu = NEW SimpleMenu(103, this, Fonts::MENU_FONT, 150,60); - for (size_t i = 0; i < stories.size(); ++i){ - menu->Add(i, stories[i].c_str()); + menu = NEW SimpleMenu(103, this, Fonts::MENU_FONT, 150, 60); + for (size_t i = 0; i < stories.size(); ++i) + { + menu->Add(i, stories[i].c_str()); } menu->Add(kCancelMenuID, "Cancel"); - } -} - -void GameStateStory::Start() { - flow = NULL; - menu = NULL; - loadStoriesMenu(JGE_GET_RES("campaigns/").c_str()); -} - -void GameStateStory::Update(float dt) { - if (!menu && mEngine->GetButtonClick(JGE_BTN_MENU)){ - menu = NEW SimpleMenu(100, this, Fonts::MENU_FONT, SCREEN_WIDTH/2-100, 25); - menu->Add(0,"Back to main menu"); - menu->Add(kCancelMenuID, "Cancel"); - } - if (menu) { - menu->Update(dt); - if (menu->closed) - SAFE_DELETE(menu); - //return; - } - if (flow){ - if (flow->currentPageId == "End") { - if (mEngine->GetButtonClick(JGE_BTN_OK) || mEngine->GetButtonClick(JGE_BTN_SEC)){ - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - } } - flow->Update(dt); - } } -void GameStateStory::Render() { - if (flow) flow->Render(); - if (menu) menu->Render(); +void GameStateStory::Start() +{ + flow = NULL; + menu = NULL; + loadStoriesMenu(JGE_GET_RES("campaigns/").c_str()); } -void GameStateStory::End() { - SAFE_DELETE(flow); - SAFE_DELETE(menu); +void GameStateStory::Update(float dt) +{ + if (!menu && mEngine->GetButtonClick(JGE_BTN_MENU)) + { + menu = NEW SimpleMenu(100, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 25); + menu->Add(0, "Back to main menu"); + menu->Add(kCancelMenuID, "Cancel"); + } + if (menu) + { + menu->Update(dt); + if (menu->closed) + SAFE_DELETE(menu); + //return; + } + if (flow) + { + if (flow->currentPageId == "End") + { + if (mEngine->GetButtonClick(JGE_BTN_OK) || mEngine->GetButtonClick(JGE_BTN_SEC)) + { + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + } + } + flow->Update(dt); + } } -void GameStateStory::ButtonPressed(int controllerId, int controlId) { - menu->Close(); +void GameStateStory::Render() +{ + if (flow) + flow->Render(); + if (menu) + menu->Render(); +} - switch (controllerId){ +void GameStateStory::End() +{ + SAFE_DELETE(flow); + SAFE_DELETE(menu); +} + +void GameStateStory::ButtonPressed(int controllerId, int controlId) +{ + menu->Close(); + + switch (controllerId) + { case 100: - if (controlId == -1){ - }else { - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - } - break; + if (controlId == -1) + { + } + else + { + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + } + break; default: - if (controlId == -1){ - mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU); - }else { - flow = NEW StoryFlow(stories[controlId]); - } - } + if (controlId == -1) + { + mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU); + } + else + { + flow = NEW StoryFlow(stories[controlId]); + } + } -} \ No newline at end of file +} diff --git a/projects/mtg/src/GameStateTransitions.cpp b/projects/mtg/src/GameStateTransitions.cpp index 1df9fd9fd..f867629ff 100644 --- a/projects/mtg/src/GameStateTransitions.cpp +++ b/projects/mtg/src/GameStateTransitions.cpp @@ -9,49 +9,63 @@ #include "OptionItem.h" #include "GameOptions.h" -TransitionBase::TransitionBase(GameApp* parent, GameState* _from, GameState* _to, float duration): GameState(parent){ - from = _from; - to = _to; - mDuration = duration; - bAnimationOnly = false; +TransitionBase::TransitionBase(GameApp* parent, GameState* _from, GameState* _to, float duration) : + GameState(parent) +{ + from = _from; + to = _to; + mDuration = duration; + bAnimationOnly = false; } -TransitionBase::~TransitionBase(){ - if(!bAnimationOnly){ - if(from) - from->End(); - } +TransitionBase::~TransitionBase() +{ + if (!bAnimationOnly) + { + if (from) + from->End(); + } } -void TransitionBase::Update(float dt){ - if(from && !Finished()) - from->Update(dt); - mElapsed += dt; +void TransitionBase::Update(float dt) +{ + if (from && !Finished()) + from->Update(dt); + mElapsed += dt; } -void TransitionBase::ButtonPressed(int controllerId, int controlId){ - if(!from) return; - JGuiListener * jgl = dynamic_cast(from); - if(jgl) - jgl->ButtonPressed(controllerId,controlId); +void TransitionBase::ButtonPressed(int controllerId, int controlId) +{ + if (!from) + return; + JGuiListener * jgl = dynamic_cast (from); + if (jgl) + jgl->ButtonPressed(controllerId, controlId); } -void TransitionBase::Start() { - mElapsed = 0; -}; +void TransitionBase::Start() +{ + mElapsed = 0; +} +; -void TransitionBase::End() { - mElapsed = 0; -}; +void TransitionBase::End() +{ + mElapsed = 0; +} +; -void TransitionFade::Render(){ - if(from) - from->Render(); - float fade = 255*mElapsed/mDuration; - if(mReversed) - fade = 255 - fade; - JRenderer::GetInstance()->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB((int)fade,0,0,0)); +void TransitionFade::Render() +{ + if (from) + from->Render(); + float fade = 255 * mElapsed / mDuration; + if (mReversed) + fade = 255 - fade; + JRenderer::GetInstance()->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB((int)fade,0,0,0)); } -TransitionFade::TransitionFade(GameApp* p, GameState* f, GameState* t, float dur, bool reversed): -TransitionBase(p, f,t,dur) { - mReversed = reversed; -}; +TransitionFade::TransitionFade(GameApp* p, GameState* f, GameState* t, float dur, bool reversed) : + TransitionBase(p, f, t, dur) +{ + mReversed = reversed; +} +; diff --git a/projects/mtg/src/GuiAvatars.cpp b/projects/mtg/src/GuiAvatars.cpp index e95f00c31..c5ca8bfd6 100644 --- a/projects/mtg/src/GuiAvatars.cpp +++ b/projects/mtg/src/GuiAvatars.cpp @@ -7,35 +7,37 @@ #define LIB_GRAVE_OFFSET 230 -GuiAvatars::GuiAvatars() : active(NULL) +GuiAvatars::GuiAvatars() : + active(NULL) { - Add(self = NEW GuiAvatar (SCREEN_WIDTH, SCREEN_HEIGHT, false, - GameObserver::GetInstance()->players[0], GuiAvatar::BOTTOM_RIGHT, this)); - Add(selfGraveyard = NEW GuiGraveyard(SCREEN_WIDTH - GuiAvatar::Width - GuiGameZone::Width/2 - 5, SCREEN_HEIGHT - GuiAvatar::Height - 5, false, - GameObserver::GetInstance()->players[0], this)); - Add(selfLibrary = NEW GuiLibrary (SCREEN_WIDTH - GuiAvatar::Width - GuiGameZone::Width/2 - 5 , SCREEN_HEIGHT - GuiAvatar::Height - 5 + GuiGameZone::Height + 5, false, - GameObserver::GetInstance()->players[0], this)); + Add(self = NEW GuiAvatar(SCREEN_WIDTH, SCREEN_HEIGHT, false, GameObserver::GetInstance()->players[0], GuiAvatar::BOTTOM_RIGHT, this)); + Add(selfGraveyard = NEW GuiGraveyard(SCREEN_WIDTH - GuiAvatar::Width - GuiGameZone::Width / 2 - 5, SCREEN_HEIGHT - GuiAvatar::Height - 5, false, GameObserver::GetInstance()->players[0], this)); + Add(selfLibrary = NEW GuiLibrary(SCREEN_WIDTH - GuiAvatar::Width - GuiGameZone::Width / 2 - 5, SCREEN_HEIGHT - GuiAvatar::Height - 5 + GuiGameZone::Height + 5, false, GameObserver::GetInstance()->players[0], this)); - Add(opponent = NEW GuiAvatar (0, 0, false, GameObserver::GetInstance()->players[1], GuiAvatar::TOP_LEFT, this)); - opponent->zoom = 0.9f; - //opponenthandveiw button - Add(opponentHand = NEW GuiOpponentHand(-30 + GuiAvatar::Width * 1.2 - GuiGameZone::Width / 2, 35 + GuiGameZone::Height - 10, false, GameObserver::GetInstance()->players[1], this)); - //opponenthandveiwends - Add(opponentGraveyard = NEW GuiGraveyard(5 + GuiAvatar::Width * 1.2 - GuiGameZone::Width / 2, 5, false, GameObserver::GetInstance()->players[1], this)); - Add(opponentLibrary = NEW GuiLibrary (5 + GuiAvatar::Width *1.2 - GuiGameZone::Width / 2, 5 + GuiGameZone::Height + 5, false, GameObserver::GetInstance()->players[1], this)); + Add(opponent = NEW GuiAvatar(0, 0, false, GameObserver::GetInstance()->players[1], GuiAvatar::TOP_LEFT, this)); + opponent->zoom = 0.9f; + //opponenthandveiw button + Add(opponentHand = NEW GuiOpponentHand(-30 + GuiAvatar::Width * 1.2 - GuiGameZone::Width / 2, 35 + GuiGameZone::Height - 10, + false, GameObserver::GetInstance()->players[1], this)); + //opponenthandveiwends + Add(opponentGraveyard = NEW GuiGraveyard(5 + GuiAvatar::Width * 1.2 - GuiGameZone::Width / 2, 5, false, + GameObserver::GetInstance()->players[1], this)); + Add(opponentLibrary = NEW GuiLibrary(5 + GuiAvatar::Width * 1.2 - GuiGameZone::Width / 2, 5 + GuiGameZone::Height + 5, false, + GameObserver::GetInstance()->players[1], this)); - CardSelectorSingleton::Instance()->Add(self); - CardSelectorSingleton::Instance()->Add(selfGraveyard); - CardSelectorSingleton::Instance()->Add(selfLibrary); - CardSelectorSingleton::Instance()->Add(opponent); - CardSelectorSingleton::Instance()->Add(opponentGraveyard); - CardSelectorSingleton::Instance()->Add(opponentLibrary); - CardSelectorSingleton::Instance()->Add(opponentHand); - selfGraveyard->alpha = selfLibrary->alpha = opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 0; + CardSelectorSingleton::Instance()->Add(self); + CardSelectorSingleton::Instance()->Add(selfGraveyard); + CardSelectorSingleton::Instance()->Add(selfLibrary); + CardSelectorSingleton::Instance()->Add(opponent); + CardSelectorSingleton::Instance()->Add(opponentGraveyard); + CardSelectorSingleton::Instance()->Add(opponentLibrary); + CardSelectorSingleton::Instance()->Add(opponentHand); + selfGraveyard->alpha = selfLibrary->alpha = opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 0; } -float GuiAvatars::LeftBoundarySelf(){ - return SCREEN_WIDTH - 10; +float GuiAvatars::LeftBoundarySelf() +{ + return SCREEN_WIDTH - 10; } GuiAvatars::~GuiAvatars() @@ -44,105 +46,125 @@ GuiAvatars::~GuiAvatars() void GuiAvatars::Activate(PlayGuiObject* c) { - c->zoom = 1.2f; - c->mHasFocus = true; - - if ((opponentGraveyard == c) || (opponentLibrary == c) || (opponent == c)|| (opponentHand == c) ) - { - opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 128.0f; - active = opponent; - opponent->zoom = 1.2f; - } - else if ((selfGraveyard == c) || (selfLibrary == c) || (self == c)) - { - selfGraveyard->alpha = selfLibrary->alpha = 128.0f; - self->zoom = 1.0f; - active = self; - } - if (opponent != c && self != c) c->alpha = 255.0f; + c->zoom = 1.2f; + c->mHasFocus = true; + + if ((opponentGraveyard == c) || (opponentLibrary == c) || (opponent == c) || (opponentHand == c)) + { + opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 128.0f; + active = opponent; + opponent->zoom = 1.2f; + } + else if ((selfGraveyard == c) || (selfLibrary == c) || (self == c)) + { + selfGraveyard->alpha = selfLibrary->alpha = 128.0f; + self->zoom = 1.0f; + active = self; + } + if (opponent != c && self != c) + c->alpha = 255.0f; } void GuiAvatars::Deactivate(PlayGuiObject* c) { - c->zoom = 1.0; - c->mHasFocus = false; - if ((opponentGraveyard == c) || (opponentLibrary == c) || (opponentHand == c) || (opponent == c)) - { - opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 0; - opponent->zoom = 0.9f; - active = NULL;} - else if ((selfGraveyard == c) || (selfLibrary == c) ||(self == c)) - { selfGraveyard->alpha = selfLibrary->alpha = 0; - self->zoom = 0.3f; - active = NULL; - } + c->zoom = 1.0; + c->mHasFocus = false; + if ((opponentGraveyard == c) || (opponentLibrary == c) || (opponentHand == c) || (opponent == c)) + { + opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 0; + opponent->zoom = 0.9f; + active = NULL; + } + else if ((selfGraveyard == c) || (selfLibrary == c) || (self == c)) + { + selfGraveyard->alpha = selfLibrary->alpha = 0; + self->zoom = 0.3f; + active = NULL; + } } int GuiAvatars::receiveEventPlus(WEvent* e) { - return selfGraveyard->receiveEventPlus(e) | opponentGraveyard->receiveEventPlus(e) | opponentHand->receiveEventPlus(e); + return selfGraveyard->receiveEventPlus(e) | opponentGraveyard->receiveEventPlus(e) | opponentHand->receiveEventPlus(e); } int GuiAvatars::receiveEventMinus(WEvent* e) { - selfGraveyard->receiveEventMinus(e); - opponentGraveyard->receiveEventMinus(e); - opponentHand->receiveEventMinus(e); - return 1; + selfGraveyard->receiveEventMinus(e); + opponentGraveyard->receiveEventMinus(e); + opponentHand->receiveEventMinus(e); + return 1; } -bool GuiAvatars::CheckUserInput(JButton key){ - if (self->CheckUserInput(key)) return true; - if (opponent->CheckUserInput(key)) return true; - if (selfGraveyard->CheckUserInput(key)) return true; - if (opponentGraveyard->CheckUserInput(key)) return true; - if (opponentHand->CheckUserInput(key)) return true; - if (selfLibrary->CheckUserInput(key)) return true; - if (opponentLibrary->CheckUserInput(key)) return true; - return false; +bool GuiAvatars::CheckUserInput(JButton key) +{ + if (self->CheckUserInput(key)) + return true; + if (opponent->CheckUserInput(key)) + return true; + if (selfGraveyard->CheckUserInput(key)) + return true; + if (opponentGraveyard->CheckUserInput(key)) + return true; + if (opponentHand->CheckUserInput(key)) + return true; + if (selfLibrary->CheckUserInput(key)) + return true; + if (opponentLibrary->CheckUserInput(key)) + return true; + return false; } -bool GuiAvatars::CheckUserInput(int x, int y){ -// if (self->CheckUserInput(key)) return true; -// if (opponent->CheckUserInput(key)) return true; - if (selfGraveyard->CheckUserInput(x, y)) return true; - if (opponentGraveyard->CheckUserInput(x, y)) return true; - if (opponentHand->CheckUserInput(x, y)) return true; - if (selfLibrary->CheckUserInput(x, y)) return true; - if (opponentLibrary->CheckUserInput(x, y)) return true; - return false; +bool GuiAvatars::CheckUserInput(int x, int y) +{ + // if (self->CheckUserInput(key)) return true; + // if (opponent->CheckUserInput(key)) return true; + if (selfGraveyard->CheckUserInput(x, y)) + return true; + if (opponentGraveyard->CheckUserInput(x, y)) + return true; + if (opponentHand->CheckUserInput(x, y)) + return true; + if (selfLibrary->CheckUserInput(x, y)) + return true; + if (opponentLibrary->CheckUserInput(x, y)) + return true; + return false; } void GuiAvatars::Update(float dt) { - self->Update(dt); - opponent->Update(dt); - selfGraveyard->Update(dt); - opponentHand->Update(dt); - opponentGraveyard->Update(dt); - selfLibrary->Update(dt); - opponentLibrary->Update(dt); + self->Update(dt); + opponent->Update(dt); + selfGraveyard->Update(dt); + opponentHand->Update(dt); + opponentGraveyard->Update(dt); + selfLibrary->Update(dt); + opponentLibrary->Update(dt); } void GuiAvatars::Render() { - JRenderer * r = JRenderer::GetInstance(); - float w = 54; - float h = 54; - if (opponent == active){ - r->FillRect(opponent->actX, opponent->actY, w * opponent->actZ , h * opponent->actZ, ARGB(200,0,0,0)); - }else if (self == active){ - r->FillRect(self->actX - w * self->actZ, self->actY - h * self->actZ, w * self->actZ , h * self->actZ, ARGB(200,0,0,0)); - } - GuiLayer::Render(); + JRenderer * r = JRenderer::GetInstance(); + float w = 54; + float h = 54; + if (opponent == active) + { + r->FillRect(opponent->actX, opponent->actY, w * opponent->actZ, h * opponent->actZ, ARGB(200,0,0,0)); + } + else if (self == active) + { + r->FillRect(self->actX - w * self->actZ, self->actY - h * self->actZ, w * self->actZ, h * self->actZ, ARGB(200,0,0,0)); + } + GuiLayer::Render(); } GuiAvatar* GuiAvatars::GetSelf() { - return self; + return self; } GuiAvatar* GuiAvatars::GetOpponent() { - return opponent; + return opponent; } diff --git a/projects/mtg/src/GuiBackground.cpp b/projects/mtg/src/GuiBackground.cpp index aadac23f1..2dfe82080 100644 --- a/projects/mtg/src/GuiBackground.cpp +++ b/projects/mtg/src/GuiBackground.cpp @@ -15,15 +15,18 @@ GuiBackground::~GuiBackground() void GuiBackground::Render() { - JRenderer* renderer = JRenderer::GetInstance(); - JQuad * quad = NULL; - GameObserver * go = GameObserver::GetInstance(); - if (go && go->mRules && go->mRules->bg.size()) { - quad = resources.RetrieveTempQuad(go->mRules->bg); - } - if (!quad) { - quad = resources.RetrieveTempQuad("backdrop.jpg"); - } - if (!quad) return; - renderer->RenderQuad(quad, 0, 18); + JRenderer* renderer = JRenderer::GetInstance(); + JQuad * quad = NULL; + GameObserver * go = GameObserver::GetInstance(); + if (go && go->mRules && go->mRules->bg.size()) + { + quad = resources.RetrieveTempQuad(go->mRules->bg); + } + if (!quad) + { + quad = resources.RetrieveTempQuad("backdrop.jpg"); + } + if (!quad) + return; + renderer->RenderQuad(quad, 0, 18); } diff --git a/projects/mtg/src/GuiCombat.cpp b/projects/mtg/src/GuiCombat.cpp index 116229899..6816620e1 100644 --- a/projects/mtg/src/GuiCombat.cpp +++ b/projects/mtg/src/GuiCombat.cpp @@ -16,521 +16,645 @@ const float kZoom_level1 = 1.4f; const float kZoom_level2 = 2.2f; const float kZoom_level3 = 2.7f; -struct Left : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test) - { return ref->y == test->y && ref->x > test->x && test->show; } }; -struct Right : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test) - { return ref->y == test->y && ref->x < test->x && test->show; } }; +struct Left: public Exp +{ + static inline bool test(DamagerDamaged* ref, DamagerDamaged* test) + { + return ref->y == test->y && ref->x > test->x && test->show; + } +}; +struct Right: public Exp +{ + static inline bool test(DamagerDamaged* ref, DamagerDamaged* test) + { + return ref->y == test->y && ref->x < test->x && test->show; + } +}; JTexture* GuiCombat::ok_tex = NULL; -GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), activeAtk(NULL), - ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), - enemy_avatar(SCREEN_WIDTH - MARGIN, TOP_LINE, 2, 0, 255), - cursor_pos(NONE), step(DAMAGE) +GuiCombat::GuiCombat(GameObserver* go) : + GuiLayer(), go(go), active(false), activeAtk(NULL), ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), enemy_avatar(SCREEN_WIDTH + - MARGIN, TOP_LINE, 2, 0, 255), cursor_pos(NONE), step(DAMAGE) { - if(NULL == ok_tex) + if (NULL == ok_tex) { - ok_tex = resources.RetrieveTexture("Ok.png",RETRIEVE_LOCK); + ok_tex = resources.RetrieveTexture("Ok.png", RETRIEVE_LOCK); } } GuiCombat::~GuiCombat() { - if(ok_tex){ - resources.Release(ok_tex); - ok_tex = NULL; - } + if (ok_tex) + { + resources.Release(ok_tex); + ok_tex = NULL; + } - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - delete (*it); + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + delete (*it); } -template +template static inline void repos(typename vector::iterator begin, typename vector::iterator end, signed size = -1) { - for (typename vector::iterator it = begin; it != end; ++it) - if ((*it)->show) ++size; - float space = (SCREEN_WIDTH - 2*MARGIN) / size; - float pos = MARGIN; - for (typename vector::iterator it = begin; it != end; ++it) - if ((*it)->show) - { - (*it)->x = pos; - pos += space; - } + for (typename vector::iterator it = begin; it != end; ++it) + if ((*it)->show) + ++size; + float space = (SCREEN_WIDTH - 2 * MARGIN) / size; + float pos = MARGIN; + for (typename vector::iterator it = begin; it != end; ++it) + if ((*it)->show) + { + (*it)->x = pos; + pos += space; + } } void GuiCombat::Update(float dt) { - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - (*it)->Update(dt); - if (activeAtk) - for (vector::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q) - (*q)->Update(dt); - ok.Update(dt); - enemy_avatar.Update(dt); + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + (*it)->Update(dt); + if (activeAtk) + for (vector::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q) + (*q)->Update(dt); + ok.Update(dt); + enemy_avatar.Update(dt); } void GuiCombat::remaskBlkViews(AttackerDamaged* before, AttackerDamaged* after) { - if (after) + if (after) { - for (vector::iterator q = after->blockers.begin(); q != after->blockers.end(); ++q) + for (vector::iterator q = after->blockers.begin(); q != after->blockers.end(); ++q) { - (*q)->actX = MARGIN; (*q)->y = TOP_LINE; - (*q)->zoom = kZoom_level2; (*q)->t = 0; + (*q)->actX = MARGIN; + (*q)->y = TOP_LINE; + (*q)->zoom = kZoom_level2; + (*q)->t = 0; } - repos(after->blockers.begin(), after->blockers.end(), after->card->has(Constants::TRAMPLE) ? 0 : -1); - enemy_avatar.actX = MARGIN; enemy_avatar.x = SCREEN_WIDTH - MARGIN; + repos (after->blockers.begin(), after->blockers.end(), after->card->has(Constants::TRAMPLE) ? 0 : -1); + enemy_avatar.actX = MARGIN; + enemy_avatar.x = SCREEN_WIDTH - MARGIN; } } void GuiCombat::validateDamage() { - switch (step) + switch (step) { - case FIRST_STRIKE : go->nextCombatStep(); break; - case DAMAGE : go->nextGamePhase(); break; - default: cout << "COMBAT : Cannot validate damage in this phase" << endl; break; + case FIRST_STRIKE: + go->nextCombatStep(); + break; + case DAMAGE: + go->nextGamePhase(); + break; + default: + cout << "COMBAT : Cannot validate damage in this phase" << endl; + break; } } void GuiCombat::autoaffectDamage(AttackerDamaged* attacker, CombatStep step) { - attacker->clearDamage(); - unsigned damage = attacker->card->stepPower(step); - for (vector::iterator it = attacker->blockers.begin(); it != attacker->blockers.end(); ++it) + attacker->clearDamage(); + unsigned damage = attacker->card->stepPower(step); + for (vector::iterator it = attacker->blockers.begin(); it != attacker->blockers.end(); ++it) { - (*it)->clearDamage(); - unsigned actual_damage = MIN(damage, (unsigned)MAX((*it)->card->toughness, 0)); - if (attacker->card->has(Constants::DEATHTOUCH) && actual_damage > 1) actual_damage = 1; - (*it)->addDamage(actual_damage, attacker); - attacker->addDamage((*it)->card->stepPower(step), *it); - damage -= actual_damage; + (*it)->clearDamage(); + unsigned actual_damage = MIN(damage, (unsigned)MAX((*it)->card->toughness, 0)); + if (attacker->card->has(Constants::DEATHTOUCH) && actual_damage > 1) + actual_damage = 1; + (*it)->addDamage(actual_damage, attacker); + attacker->addDamage((*it)->card->stepPower(step), *it); + damage -= actual_damage; } - if (damage > 0 && attacker->blockers.size() > 0 && !attacker->card->has(Constants::TRAMPLE)) attacker->blockers[0]->addDamage(damage, attacker); + if (damage > 0 && attacker->blockers.size() > 0 && !attacker->card->has(Constants::TRAMPLE)) + attacker->blockers[0]->addDamage(damage, attacker); } void GuiCombat::addOne(DefenserDamaged* blocker, CombatStep step) { - blocker->addDamage(1, activeAtk); - signed damage = activeAtk->card->stepPower(step); - for (vector::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it) + blocker->addDamage(1, activeAtk); + signed damage = activeAtk->card->stepPower(step); + for (vector::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it) { - damage -= (*it)->sumDamages(); - if (0 > damage) { (*it)->addDamage(-1, activeAtk); break; } + damage -= (*it)->sumDamages(); + if (0 > damage) + { + (*it)->addDamage(-1, activeAtk); + break; + } } } void GuiCombat::removeOne(DefenserDamaged* blocker, CombatStep step) { - blocker->addDamage(-1, activeAtk); - for (vector::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it) - if (activeAtk->card->has(Constants::DEATHTOUCH) ? ((*it)->sumDamages() < 1) : (!(*it)->hasLethalDamage())) { (*it)->addDamage(1, activeAtk); return; } - if (!activeAtk->card->has(Constants::TRAMPLE) && activeAtk->blockers.size() > 0) activeAtk->blockers.back()->addDamage(1, activeAtk); + blocker->addDamage(-1, activeAtk); + for (vector::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it) + if (activeAtk->card->has(Constants::DEATHTOUCH) ? ((*it)->sumDamages() < 1) : (!(*it)->hasLethalDamage())) + { + (*it)->addDamage(1, activeAtk); + return; + } + if (!activeAtk->card->has(Constants::TRAMPLE) && activeAtk->blockers.size() > 0) + activeAtk->blockers.back()->addDamage(1, activeAtk); } -bool GuiCombat::clickOK(){ - active = activeAtk = NULL; - cursor_pos = NONE; - switch (step) +bool GuiCombat::clickOK() +{ + active = activeAtk = NULL; + cursor_pos = NONE; + switch (step) { - case BLOCKERS : - case TRIGGERS : - assert(false); return false; // that should not happen + case BLOCKERS: + case TRIGGERS: + assert(false); + return false; // that should not happen - case ORDER : go->nextGamePhase(); return true; - case FIRST_STRIKE : return false; - case DAMAGE : validateDamage(); return true; - case END_FIRST_STRIKE : return false; - case END_DAMAGE : return false; // nothing; + case ORDER: + go->nextGamePhase(); + return true; + case FIRST_STRIKE: + return false; + case DAMAGE: + validateDamage(); + return true; + case END_FIRST_STRIKE: + return false; + case END_DAMAGE: + return false; // nothing; } - return false; + return false; } bool GuiCombat::CheckUserInput(JButton key) { - if (NONE == cursor_pos) return false; - DamagerDamaged* oldActive = active; - switch (key) + if (NONE == cursor_pos) + return false; + DamagerDamaged* oldActive = active; + switch (key) { case JGE_BTN_OK: - if (BLK == cursor_pos) + if (BLK == cursor_pos) { - if (ORDER == step) go->cardClick(active->card); // { activeAtk->card->raiseBlockerRankOrder(active->card); } - else + if (ORDER == step) + go->cardClick(active->card); // { activeAtk->card->raiseBlockerRankOrder(active->card); } + else { - signed damage = activeAtk->card->stepPower(step); - for (vector::iterator it = activeAtk->blockers.begin(); *it != active; ++it) - damage -= (*it)->sumDamages(); - signed now = active->sumDamages(); - damage -= now; - if (damage > 0) addOne(active, step); - else - if (activeAtk->card->has(Constants::DEATHTOUCH)) - for (; now >= 1; --now) removeOne(active, step); + signed damage = activeAtk->card->stepPower(step); + for (vector::iterator it = activeAtk->blockers.begin(); *it != active; ++it) + damage -= (*it)->sumDamages(); + signed now = active->sumDamages(); + damage -= now; + if (damage > 0) + addOne(active, step); + else if (activeAtk->card->has(Constants::DEATHTOUCH)) + for (; now >= 1; --now) + removeOne(active, step); else - for (now -= active->card->toughness; now >= 0; --now) removeOne(active, step); + for (now -= active->card->toughness; now >= 0; --now) + removeOne(active, step); } } - else if (ATK == cursor_pos) + else if (ATK == cursor_pos) { - active = activeAtk->blockers.front(); - active->zoom = kZoom_level3; - cursor_pos = BLK; + active = activeAtk->blockers.front(); + active->zoom = kZoom_level3; + cursor_pos = BLK; } - else if (OK == cursor_pos) + else if (OK == cursor_pos) { - clickOK(); + clickOK(); } - break; + break; case JGE_BTN_CANCEL: - if (BLK == cursor_pos) + if (BLK == cursor_pos) { - oldActive->zoom = kZoom_level2; - active = activeAtk; - cursor_pos = ATK; + oldActive->zoom = kZoom_level2; + active = activeAtk; + cursor_pos = ATK; } - return true; + return true; case JGE_BTN_LEFT: - switch (cursor_pos) - { - case NONE : break; - case OK : - for (vector::reverse_iterator it = attackers.rbegin(); it != attackers.rend(); ++it) if ((*it)->show) { active = *it; break; } - activeAtk = static_cast(active); - cursor_pos = ATK; - break; - case ATK : - { - DamagerDamaged* old = active; - active = closest(attackers, NULL, static_cast(active)); - activeAtk = static_cast(active); - if (old != active) { if (old) old->zoom = kZoom_none; if (active) active->zoom = kZoom_level1; } - } - break; - case BLK : - { - DamagerDamaged* old = active; - active = closest(activeAtk->blockers, NULL, static_cast(active)); - if (old != active) { if (old) old->zoom = kZoom_none; if (active) active->zoom = kZoom_level1; } - } - break; - } - break; - case JGE_BTN_RIGHT: - switch (cursor_pos) - { - case NONE : - case OK : break; - case BLK : - { - DamagerDamaged* old = active; - active = closest(activeAtk->blockers, NULL, static_cast(active)); - if (old != active) { if (old) old->zoom = kZoom_none; if (active) active->zoom = kZoom_level1; } - } - break; - case ATK : - { - DamagerDamaged* old = active; - active = closest(attackers, NULL, static_cast(active)); - if (active == oldActive) { active = activeAtk = NULL; cursor_pos = OK; } - else - { - if (old != active) { - if (old) old->zoom = kZoom_none; - if (active) active->zoom = kZoom_level1; + switch (cursor_pos) + { + case NONE: + break; + case OK: + for (vector::reverse_iterator it = attackers.rbegin(); it != attackers.rend(); ++it) + if ((*it)->show) + { + active = *it; + break; } - activeAtk = static_cast(active); - } - } - break; - } - break; + activeAtk = static_cast (active); + cursor_pos = ATK; + break; + case ATK: + { + DamagerDamaged* old = active; + active = closest (attackers, NULL, static_cast (active)); + activeAtk = static_cast (active); + if (old != active) + { + if (old) + old->zoom = kZoom_none; + if (active) + active->zoom = kZoom_level1; + } + } + break; + case BLK: + { + DamagerDamaged* old = active; + active = closest (activeAtk->blockers, NULL, static_cast (active)); + if (old != active) + { + if (old) + old->zoom = kZoom_none; + if (active) + active->zoom = kZoom_level1; + } + } + break; + } + break; + case JGE_BTN_RIGHT: + switch (cursor_pos) + { + case NONE: + case OK: + break; + case BLK: + { + DamagerDamaged* old = active; + active = closest (activeAtk->blockers, NULL, static_cast (active)); + if (old != active) + { + if (old) + old->zoom = kZoom_none; + if (active) + active->zoom = kZoom_level1; + } + } + break; + case ATK: + { + DamagerDamaged* old = active; + active = closest (attackers, NULL, static_cast (active)); + if (active == oldActive) + { + active = activeAtk = NULL; + cursor_pos = OK; + } + else + { + if (old != active) + { + if (old) + old->zoom = kZoom_none; + if (active) + active->zoom = kZoom_level1; + } + activeAtk = static_cast (active); + } + } + break; + } + break; case JGE_BTN_DOWN: - if (ORDER == step || BLK != cursor_pos || active->sumDamages() <= 0) break; - removeOne(active, step); - break; + if (ORDER == step || BLK != cursor_pos || active->sumDamages() <= 0) + break; + removeOne(active, step); + break; case JGE_BTN_UP: - if (ORDER == step || BLK != cursor_pos) break; - addOne(active, step); - break; + if (ORDER == step || BLK != cursor_pos) + break; + addOne(active, step); + break; case JGE_BTN_PRI: - active = activeAtk = NULL; cursor_pos = OK; - break; + active = activeAtk = NULL; + cursor_pos = OK; + break; case JGE_BTN_NEXT: - if (!options[Options::REVERSETRIGGERS].number) return false; - active = activeAtk = NULL; cursor_pos = OK; - break; + if (!options[Options::REVERSETRIGGERS].number) + return false; + active = activeAtk = NULL; + cursor_pos = OK; + break; case JGE_BTN_PREV: - if (options[Options::REVERSETRIGGERS].number) return false; - active = activeAtk = NULL; cursor_pos = OK; - break; + if (options[Options::REVERSETRIGGERS].number) + return false; + active = activeAtk = NULL; + cursor_pos = OK; + break; default: - ; + ; } - if (oldActive != active) + if (oldActive != active) { - if (oldActive && oldActive != activeAtk) oldActive->zoom = kZoom_level2; - if (active) active->zoom = kZoom_level3; - if (ATK == cursor_pos) remaskBlkViews(dynamic_cast(oldActive), static_cast(active)); + if (oldActive && oldActive != activeAtk) + oldActive->zoom = kZoom_level2; + if (active) + active->zoom = kZoom_level3; + if (ATK == cursor_pos) + remaskBlkViews(dynamic_cast (oldActive), static_cast (active)); } - if (OK == cursor_pos) ok.zoom = 1.5; else ok.zoom = kZoom_none; - return true; + if (OK == cursor_pos) + ok.zoom = 1.5; + else + ok.zoom = kZoom_none; + return true; } void GuiCombat::Render() { - if (NONE == cursor_pos) return; - JRenderer* renderer = JRenderer::GetInstance(); - renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); + if (NONE == cursor_pos) + return; + JRenderer* renderer = JRenderer::GetInstance(); + renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - if ((*it)->show) (*it)->Render(step); - if (activeAtk) + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->show) + (*it)->Render(step); + if (activeAtk) { - signed damage = activeAtk->card->stepPower(step); - for (vector::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q) - { - (*q)->Render(step); - damage -= (*q)->sumDamages(); - } - if (damage < 0) damage = 0; - if (activeAtk->card->has(Constants::TRAMPLE)) - { - go->opponent()->mAvatar->SetHotSpot(18, 25); - enemy_avatar.Render(go->opponent()->mAvatar); - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetColor(ARGB(255, 255, 64, 0)); - { - char buf[10]; sprintf(buf, "%i", damage); - mFont->DrawString(buf, enemy_avatar.actX - 25, enemy_avatar.actY - 40); - } - } + signed damage = activeAtk->card->stepPower(step); + for (vector::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q) + { + (*q)->Render(step); + damage -= (*q)->sumDamages(); + } + if (damage < 0) + damage = 0; + if (activeAtk->card->has(Constants::TRAMPLE)) + { + go->opponent()->mAvatar->SetHotSpot(18, 25); + enemy_avatar.Render(go->opponent()->mAvatar); + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetColor(ARGB(255, 255, 64, 0)); + { + char buf[10]; + sprintf(buf, "%i", damage); + mFont->DrawString(buf, enemy_avatar.actX - 25, enemy_avatar.actY - 40); + } + } } - if (ok_tex) { - JQuad *ok_quad = resources.RetrieveTempQuad("Ok.png"); - ok_quad->SetHotSpot(28, 22); - ok.Render(ok_quad); - } - renderer->DrawLine(0, SCREEN_HEIGHT / 2 + 10, SCREEN_WIDTH, SCREEN_HEIGHT / 2 + 10, ARGB(255, 255, 64, 0)); - if (FIRST_STRIKE == step) + if (ok_tex) { - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetColor(ARGB(255, 64, 255, 64)); - mFont->DrawString("First strike damage", 370, 2); + JQuad *ok_quad = resources.RetrieveTempQuad("Ok.png"); + ok_quad->SetHotSpot(28, 22); + ok.Render(ok_quad); + } + renderer->DrawLine(0, SCREEN_HEIGHT / 2 + 10, SCREEN_WIDTH, SCREEN_HEIGHT / 2 + 10, ARGB(255, 255, 64, 0)); + if (FIRST_STRIKE == step) + { + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetColor(ARGB(255, 64, 255, 64)); + mFont->DrawString("First strike damage", 370, 2); } } int GuiCombat::resolve() // Returns the number of damage objects dealt this turn. { - DamageStack* stack = NEW DamageStack(); - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + DamageStack* stack = NEW DamageStack(); + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) { - MTGCardInstance * attacker = (*it)->card; - signed dmg = attacker->stepPower(step); + MTGCardInstance * attacker = (*it)->card; + signed dmg = attacker->stepPower(step); for (vector::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q) - { + { for (vector::iterator d = (*q)->damages.begin(); d != (*q)->damages.end(); ++d) - stack->Add(NEW Damage(*d)); + stack->Add(NEW Damage(*d)); dmg -= (*q)->sumDamages(); - } - - if (dmg > 0 && ( (!attacker->blocked) || attacker->has(Constants::TRAMPLE)) ) stack->Add(NEW Damage((*it)->card, go->opponent(), dmg, DAMAGE_COMBAT)); - for (vector::iterator d = (*it)->damages.begin(); d != (*it)->damages.end(); ++d) - stack->Add(NEW Damage(*d)); + } + + if (dmg > 0 && ((!attacker->blocked) || attacker->has(Constants::TRAMPLE))) + stack->Add(NEW Damage((*it)->card, go->opponent(), dmg, DAMAGE_COMBAT)); + for (vector::iterator d = (*it)->damages.begin(); d != (*it)->damages.end(); ++d) + stack->Add(NEW Damage(*d)); } - int v = stack->mCount; - if (v > 0){ - go->mLayers->stackLayer()->Add(stack); - go->mLayers->stackLayer()->resolve(); // This will delete the damage stack which will in turn delete the Damage it contains - }else - SAFE_DELETE(stack); - return v; + int v = stack->mCount; + if (v > 0) + { + go->mLayers->stackLayer()->Add(stack); + go->mLayers->stackLayer()->resolve(); // This will delete the damage stack which will in turn delete the Damage it contains + } + else + SAFE_DELETE(stack); + return v; } int GuiCombat::receiveEventPlus(WEvent* e) { - if (WEventCreatureAttacker* event = dynamic_cast(e)) + if (WEventCreatureAttacker* event = dynamic_cast(e)) { - if (NULL == event->after) return 0; - AttackerDamaged* t = NEW AttackerDamaged(event->card, *(event->card->view), true, NULL); - attackers.push_back(t); - return 1; + if (NULL == event->after) + return 0; + AttackerDamaged* t = NEW AttackerDamaged(event->card, *(event->card->view), true, NULL); + attackers.push_back(t); + return 1; } - else if (WEventCreatureBlocker* event = dynamic_cast(e)) + else if (WEventCreatureBlocker* event = dynamic_cast(e)) { - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - if ((*it)->card == event->after) - { - DefenserDamaged* t = NEW DefenserDamaged(event->card, *(event->card->view), true, NULL); - t->y = t->actY = TOP_LINE; t->actT = t->t = 0; t->actZ = t->zoom = kZoom_level2; - (*it)->blockers.push_back(t); - return 1; - } - return 0; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->after) + { + DefenserDamaged* t = NEW DefenserDamaged(event->card, *(event->card->view), true, NULL); + t->y = t->actY = TOP_LINE; + t->actT = t->t = 0; + t->actZ = t->zoom = kZoom_level2; + (*it)->blockers.push_back(t); + return 1; + } + return 0; } - else if (WEventCreatureBlockerRank* event = dynamic_cast(e)) + else if (WEventCreatureBlockerRank* event = dynamic_cast(e)) { - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - if ((*it)->card == event->attacker) - { - vector::iterator it1, it2; - for (it1 = (*it)->blockers.begin(); it1 != (*it)->blockers.end(); ++it1) if ((*it1)->card == event->card) break; - if ((*it)->blockers.end() == it1) return 1; - for (it2 = (*it)->blockers.begin(); it2 != (*it)->blockers.end(); ++it2) if ((*it2)->card == event->exchangeWith) break; - if ((*it)->blockers.end() == it2) return 1; - float x = (*it1)->x; - (*it1)->x = (*it2)->x; - (*it2)->x = x; - std::iter_swap(it1, it2); - autoaffectDamage(*it, DAMAGE); - } - return 1; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->attacker) + { + vector::iterator it1, it2; + for (it1 = (*it)->blockers.begin(); it1 != (*it)->blockers.end(); ++it1) + if ((*it1)->card == event->card) + break; + if ((*it)->blockers.end() == it1) + return 1; + for (it2 = (*it)->blockers.begin(); it2 != (*it)->blockers.end(); ++it2) + if ((*it2)->card == event->exchangeWith) + break; + if ((*it)->blockers.end() == it2) + return 1; + float x = (*it1)->x; + (*it1)->x = (*it2)->x; + (*it2)->x = x; + std::iter_swap(it1, it2); + autoaffectDamage(*it, DAMAGE); + } + return 1; } - return 0; + return 0; } int GuiCombat::receiveEventMinus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) - if (go->players[0]->game->inPlay == event->from || go->players[1]->game->inPlay == event->from) - { - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - if ((*it)->card == event->card->previous || (*it)->card == event->card ) - { - AttackerDamaged* d = *it; - if (activeAtk == *it) activeAtk = NULL; - attackers.erase(it); - trash(d); - return 1; - } - else - for (vector::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q) - if ((*q)->card == event->card->previous || (*q)->card == event->card) + if (WEventZoneChange* event = dynamic_cast(e)) + if (go->players[0]->game->inPlay == event->from || go->players[1]->game->inPlay == event->from) + { + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->card->previous || (*it)->card == event->card) { - DefenserDamaged* d = *q; - (*it)->blockers.erase(q); - trash(d); - return 1; + AttackerDamaged* d = *it; + if (activeAtk == *it) + activeAtk = NULL; + attackers.erase(it); + trash(d); + return 1; } - return 0; - } - if (WEventCreatureAttacker* event = dynamic_cast(e)) + else + for (vector::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q) + if ((*q)->card == event->card->previous || (*q)->card == event->card) + { + DefenserDamaged* d = *q; + (*it)->blockers.erase(q); + trash(d); + return 1; + } + return 0; + } + if (WEventCreatureAttacker* event = dynamic_cast(e)) { - if (NULL == event->before) return 0; - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - if ((*it)->card == event->card) - { - AttackerDamaged* d = *it; - attackers.erase(it); - trash(d); - return 1; - } - return 0; - } - else if (WEventCreatureBlocker* event = dynamic_cast(e)) - { - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - if ((*it)->card == event->before) - for (vector::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q) - if ((*q)->card == event->card) - { - DefenserDamaged* d = *q; - (*it)->blockers.erase(q); + if (NULL == event->before) + return 0; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->card == event->card) + { + AttackerDamaged* d = *it; + attackers.erase(it); trash(d); return 1; - } - return 0; + } + return 0; } - else if (WEventPhaseChange* event = dynamic_cast(e)) + else if (WEventCreatureBlocker* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_COMBATDAMAGE == event->to->id) step = BLOCKERS; - else cursor_pos = NONE; - } - else if (WEventCombatStepChange* event = dynamic_cast(e)) - switch (event->step) - { - case BLOCKERS: - break; - - case TRIGGERS: - step = TRIGGERS; - return 1; - - case ORDER: - { - if (ORDER == step) return 0; // Why do I take this twice ? >.> - if (!go->currentPlayer->displayStack()) { go->nextCombatStep(); return 1; } - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - { - (*it)->show = (1 < (*it)->blockers.size()); - autoaffectDamage(*it, DAMAGE); - } - active = NULL; - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - if ((*it)->show) - { - (*it)->y = 210; - (*it)->zoom = kZoom_level2; (*it)->t = 0; - if (!active) active = *it; - } - repos(attackers.begin(), attackers.end(), 0); - if (active) - { - active->zoom = kZoom_level3; - activeAtk = static_cast(active); - remaskBlkViews(NULL, static_cast(active)); - cursor_pos = ATK; - step = ORDER; - } - else - go->nextGamePhase(); - return 1; - } - case FIRST_STRIKE: - step = FIRST_STRIKE; - for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) - if ((*attacker)->card->has(Constants::FIRSTSTRIKE) || (*attacker)->card->has(Constants::DOUBLESTRIKE)) goto DAMAGE; - go->nextCombatStep(); - break; - case END_FIRST_STRIKE: - step = END_FIRST_STRIKE; - for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) - autoaffectDamage(*attacker, FIRST_STRIKE); - if (0 == resolve()) - go->nextCombatStep(); - //else go->mLayers->stackLayer()->AddNextGamePhase(); //uncomment to add "interrupt" offer after first strike, rather than giving priority to current player - return 1; - case DAMAGE: DAMAGE: - step = event->step; - if (!go->currentPlayer->displayStack()) { - ((AIPlayer *)go->currentPlayer)->affectCombatDamages(step); - go->nextGamePhase(); - return 1; - } - for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) - autoaffectDamage(*attacker, step); for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) - (*it)->show = ((*it)->card->has(Constants::DOUBLESTRIKE) || ((*it)->card->has(Constants::FIRSTSTRIKE) ^ (DAMAGE == step))) && - (((*it)->card->has(Constants::TRAMPLE) ? (size_t) 0 : (size_t) 1) < (*it)->blockers.size() - ); - repos(attackers.begin(), attackers.end(), 0); - active = NULL; - for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) if ((*it)->show) { active = *it; break; } - if (active) - { - active->zoom = kZoom_level3; - activeAtk = static_cast(active); - remaskBlkViews(NULL, static_cast(active)); - cursor_pos = ATK; - } + if ((*it)->card == event->before) + for (vector::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q) + if ((*q)->card == event->card) + { + DefenserDamaged* d = *q; + (*it)->blockers.erase(q); + trash(d); + return 1; + } + return 0; + } + else if (WEventPhaseChange* event = dynamic_cast(e)) + { + if (Constants::MTG_PHASE_COMBATDAMAGE == event->to->id) + step = BLOCKERS; else - go->nextCombatStep(); - return 1; - case END_DAMAGE: - step = END_DAMAGE; - if (0 == resolve()) - go->nextGamePhase(); - return 1; - } - return 0; + cursor_pos = NONE; + } + else if (WEventCombatStepChange* event = dynamic_cast(e)) + switch (event->step) + { + case BLOCKERS: + break; + + case TRIGGERS: + step = TRIGGERS; + return 1; + + case ORDER: + { + if (ORDER == step) + return 0; // Why do I take this twice ? >.> + if (!go->currentPlayer->displayStack()) + { + go->nextCombatStep(); + return 1; + } + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + { + (*it)->show = (1 < (*it)->blockers.size()); + autoaffectDamage(*it, DAMAGE); + } + active = NULL; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->show) + { + (*it)->y = 210; + (*it)->zoom = kZoom_level2; + (*it)->t = 0; + if (!active) + active = *it; + } + repos (attackers.begin(), attackers.end(), 0); + if (active) + { + active->zoom = kZoom_level3; + activeAtk = static_cast (active); + remaskBlkViews(NULL, static_cast (active)); + cursor_pos = ATK; + step = ORDER; + } + else + go->nextGamePhase(); + return 1; + } + case FIRST_STRIKE: + step = FIRST_STRIKE; + for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) + if ((*attacker)->card->has(Constants::FIRSTSTRIKE) || (*attacker)->card->has(Constants::DOUBLESTRIKE)) + goto DAMAGE; + go->nextCombatStep(); + break; + case END_FIRST_STRIKE: + step = END_FIRST_STRIKE; + for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) + autoaffectDamage(*attacker, FIRST_STRIKE); + if (0 == resolve()) + go->nextCombatStep(); + //else go->mLayers->stackLayer()->AddNextGamePhase(); //uncomment to add "interrupt" offer after first strike, rather than giving priority to current player + return 1; + case DAMAGE: + DAMAGE: step = event->step; + if (!go->currentPlayer->displayStack()) + { + ((AIPlayer *) go->currentPlayer)->affectCombatDamages(step); + go->nextGamePhase(); + return 1; + } + for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker) + autoaffectDamage(*attacker, step); + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + (*it)->show = ((*it)->card->has(Constants::DOUBLESTRIKE) || ((*it)->card->has(Constants::FIRSTSTRIKE) ^ (DAMAGE + == step))) && (((*it)->card->has(Constants::TRAMPLE) ? (size_t) 0 : (size_t) 1) + < (*it)->blockers.size()); + repos (attackers.begin(), attackers.end(), 0); + active = NULL; + for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) + if ((*it)->show) + { + active = *it; + break; + } + if (active) + { + active->zoom = kZoom_level3; + activeAtk = static_cast (active); + remaskBlkViews(NULL, static_cast (active)); + cursor_pos = ATK; + } + else + go->nextCombatStep(); + return 1; + case END_DAMAGE: + step = END_DAMAGE; + if (0 == resolve()) + go->nextGamePhase(); + return 1; + } + return 0; } diff --git a/projects/mtg/src/GuiFrame.cpp b/projects/mtg/src/GuiFrame.cpp index 632266fe3..f59d14e67 100644 --- a/projects/mtg/src/GuiFrame.cpp +++ b/projects/mtg/src/GuiFrame.cpp @@ -5,28 +5,29 @@ GuiFrame::GuiFrame() { - if (resources.GetTexture("wood.png")) - wood = resources.RetrieveQuad("wood.png", 0, 0, SCREEN_WIDTH, 28); - else{ - wood = NULL; - GameApp::systemError += "Can't load wood texture : " __FILE__ "\n"; + if (resources.GetTexture("wood.png")) + wood = resources.RetrieveQuad("wood.png", 0, 0, SCREEN_WIDTH, 28); + else + { + wood = NULL; + GameApp::systemError += "Can't load wood texture : " __FILE__ "\n"; } - - goldGlow = gold1 = gold2 = NULL; - if (resources.GetTexture("gold.png")){ - gold1 = resources.RetrieveQuad("gold.png", 0, 0, SCREEN_WIDTH, 6, "gold1"); - gold2 = resources.RetrieveQuad("gold.png", 0, 6, SCREEN_WIDTH, 6, "gold2"); - if (resources.GetTexture("goldglow.png")) - goldGlow = resources.RetrieveQuad("goldglow.png", 1, 1, SCREEN_WIDTH - 2, 18); - if (gold2){ - gold2->SetColor(ARGB(127, 255, 255, 255)); - gold2->SetHFlip(true); + goldGlow = gold1 = gold2 = NULL; + if (resources.GetTexture("gold.png")) + { + gold1 = resources.RetrieveQuad("gold.png", 0, 0, SCREEN_WIDTH, 6, "gold1"); + gold2 = resources.RetrieveQuad("gold.png", 0, 6, SCREEN_WIDTH, 6, "gold2"); + if (resources.GetTexture("goldglow.png")) + goldGlow = resources.RetrieveQuad("goldglow.png", 1, 1, SCREEN_WIDTH - 2, 18); + if (gold2) + { + gold2->SetColor(ARGB(127, 255, 255, 255)); + gold2->SetHFlip(true); + } } - } - - step = 0.0; + step = 0.0; } @@ -36,28 +37,34 @@ GuiFrame::~GuiFrame() void GuiFrame::Render() { - JRenderer* renderer = JRenderer::GetInstance(); - float sized = step / 4; if (sized > SCREEN_WIDTH) sized -= SCREEN_WIDTH; - renderer->RenderQuad(wood, 0, 0); - if(gold1){ - renderer->RenderQuad(gold1, -sized, 16); - renderer->RenderQuad(gold1, -sized + 479, 16); - - if(goldGlow){ - goldGlow->SetColor(ARGB((100+(rand()%50)), 255, 255, 255)); - renderer->RenderQuad(goldGlow, -sized, 9); - renderer->RenderQuad(goldGlow, -sized + 480, 9); - } + JRenderer* renderer = JRenderer::GetInstance(); + float sized = step / 4; + if (sized > SCREEN_WIDTH) + sized -= SCREEN_WIDTH; + renderer->RenderQuad(wood, 0, 0); + if (gold1) + { + renderer->RenderQuad(gold1, -sized, 16); + renderer->RenderQuad(gold1, -sized + 479, 16); - if(gold2){ - renderer->RenderQuad(gold2, step / 2, 16); - renderer->RenderQuad(gold2, step / 2 - 479, 16); + if (goldGlow) + { + goldGlow->SetColor(ARGB((100+(rand()%50)), 255, 255, 255)); + renderer->RenderQuad(goldGlow, -sized, 9); + renderer->RenderQuad(goldGlow, -sized + 480, 9); + } + + if (gold2) + { + renderer->RenderQuad(gold2, step / 2, 16); + renderer->RenderQuad(gold2, step / 2 - 479, 16); + } } - } } void GuiFrame::Update(float dt) { - step += dt * 5; - if (step > 2*SCREEN_WIDTH) step -= 2*SCREEN_WIDTH; + step += dt * 5; + if (step > 2 * SCREEN_WIDTH) + step -= 2 * SCREEN_WIDTH; } diff --git a/projects/mtg/src/GuiHand.cpp b/projects/mtg/src/GuiHand.cpp index 8ccd53604..8894cc139 100644 --- a/projects/mtg/src/GuiHand.cpp +++ b/projects/mtg/src/GuiHand.cpp @@ -18,270 +18,298 @@ const float GuiHand::ClosedY = SCREEN_HEIGHT; bool HandLimitor::select(Target* t) { - if (CardView* c = dynamic_cast(t)) - return hand->isInHand(c); - else return false; + if (CardView* c = dynamic_cast(t)) + return hand->isInHand(c); + else + return false; } bool HandLimitor::greyout(Target* t) { - return true; + return true; } -HandLimitor::HandLimitor(GuiHand* hand) : hand(hand) {} - -GuiHand::GuiHand(MTGHand* hand) : GuiLayer(), hand(hand) +HandLimitor::HandLimitor(GuiHand* hand) : + hand(hand) { - back = resources.RetrieveTempQuad("handback.png"); - if(back) back->SetTextureRect(1, 0, 100, 250); - else GameApp::systemError = "Error loading hand texture : " __FILE__; +} + +GuiHand::GuiHand(MTGHand* hand) : + GuiLayer(), hand(hand) +{ + back = resources.RetrieveTempQuad("handback.png"); + if (back) + back->SetTextureRect(1, 0, 100, 250); + else + GameApp::systemError = "Error loading hand texture : " __FILE__; } GuiHand::~GuiHand() { - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - delete(*it); + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + delete (*it); } void GuiHand::Update(float dt) { - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - (*it)->Update(dt); + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + (*it)->Update(dt); } bool GuiHand::isInHand(CardView* card) { - vector::iterator it; - it = find(cards.begin(), cards.end(), card); - return (it != cards.end()); + vector::iterator it; + it = find(cards.begin(), cards.end(), card); + return (it != cards.end()); } -GuiHandOpponent::GuiHandOpponent(MTGHand* hand) : GuiHand(hand) {} +GuiHandOpponent::GuiHandOpponent(MTGHand* hand) : + GuiHand(hand) +{ +} void GuiHandOpponent::Render() { - JQuad * quad = resources.GetQuad("back_thumb"); + JQuad * quad = resources.GetQuad("back_thumb"); - float x = 45; - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + float x = 45; + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) { - (*it)->x = x; - (*it)->y = 2; - (*it)->zoom = 0.3f; - (*it)->Render(quad); - x += 18; + (*it)->x = x; + (*it)->y = 2; + (*it)->zoom = 0.3f; + (*it)->Render(quad); + x += 18; } } -GuiHandSelf::GuiHandSelf(MTGHand* hand) : GuiHand(hand), state(Closed), backpos(ClosedX, SCREEN_HEIGHT - 250, 1.0, 0, 255) +GuiHandSelf::GuiHandSelf(MTGHand* hand) : + GuiHand(hand), state(Closed), backpos(ClosedX, SCREEN_HEIGHT - 250, 1.0, 0, 255) { - limitor = NEW HandLimitor(this); - if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) + limitor = NEW HandLimitor(this); + if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) { - backpos.t = M_PI/2; - backpos.y = ClosedY; - backpos.x = SCREEN_WIDTH - 30 * 7 - 14; - backpos.UpdateNow(); + backpos.t = M_PI / 2; + backpos.y = ClosedY; + backpos.x = SCREEN_WIDTH - 30 * 7 - 14; + backpos.UpdateNow(); } } -GuiHandSelf::~GuiHandSelf(){ - SAFE_DELETE(limitor); +GuiHandSelf::~GuiHandSelf() +{ + SAFE_DELETE(limitor); } void GuiHandSelf::Repos() { - float y = 48.0; - if (Closed == state && OptionClosedHand::VISIBLE == options[Options::CLOSEDHAND].number) + float y = 48.0; + if (Closed == state && OptionClosedHand::VISIBLE == options[Options::CLOSEDHAND].number) { - float dist = 180.0f / cards.size(); - if (dist > 20) - dist = 20.0; - else - y = 40.0; - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - { - (*it)->x = ClosedRowX; (*it)->y = y; - y += dist; - } - } - else - { - bool q = (Closed == state); - if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) - { - y = SCREEN_WIDTH - 30; - float dist = 240.0f / cards.size(); if (dist > 30) dist = 30; else y = SCREEN_WIDTH - 15; - for (vector::reverse_iterator it = cards.rbegin(); it != cards.rend(); ++it) - { - (*it)->x = y; - (*it)->y = SCREEN_HEIGHT - 30; - y -= dist; - (*it)->alpha = static_cast(q ? 0 : 255); - } - backpos.x = y + SCREEN_HEIGHT - 14; - } - else - { - float dist = 224.0f / ((cards.size() + 1) / 2); if (dist > 65) dist = 65; - bool flip = false; + float dist = 180.0f / cards.size(); + if (dist > 20) + dist = 20.0; + else + y = 40.0; for (vector::iterator it = cards.begin(); it != cards.end(); ++it) { - (*it)->x = flip ? RightRowX : LeftRowX; - (*it)->y = y; - if (flip) y += dist; - flip = !flip; - (*it)->alpha = static_cast(q ? 0 : 255); + (*it)->x = ClosedRowX; + (*it)->y = y; + y += dist; + } + } + else + { + bool q = (Closed == state); + if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) + { + y = SCREEN_WIDTH - 30; + float dist = 240.0f / cards.size(); + if (dist > 30) + dist = 30; + else + y = SCREEN_WIDTH - 15; + for (vector::reverse_iterator it = cards.rbegin(); it != cards.rend(); ++it) + { + (*it)->x = y; + (*it)->y = SCREEN_HEIGHT - 30; + y -= dist; + (*it)->alpha = static_cast (q ? 0 : 255); + } + backpos.x = y + SCREEN_HEIGHT - 14; + } + else + { + float dist = 224.0f / ((cards.size() + 1) / 2); + if (dist > 65) + dist = 65; + bool flip = false; + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + { + (*it)->x = flip ? RightRowX : LeftRowX; + (*it)->y = y; + if (flip) + y += dist; + flip = !flip; + (*it)->alpha = static_cast (q ? 0 : 255); + } } - } } } bool GuiHandSelf::CheckUserInput(JButton key) { - JButton trigger = (options[Options::REVERSETRIGGERS].number ? JGE_BTN_PREV : JGE_BTN_NEXT); - if (trigger == key) + JButton trigger = (options[Options::REVERSETRIGGERS].number ? JGE_BTN_PREV : JGE_BTN_NEXT); + if (trigger == key) { - state = (Open == state ? Closed : Open); - if (Open == state) CardSelectorSingleton::Instance()->Push(); - CardSelectorSingleton::Instance()->Limit(Open == state ? limitor : NULL, CardView::handZone); - if (Closed == state) CardSelectorSingleton::Instance()->Pop(); - if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) - backpos.y = Open == state ? OpenY : ClosedY; - else - backpos.x = Open == state ? OpenX : ClosedX; - if (Open == state && OptionClosedHand::INVISIBLE == options[Options::CLOSEDHAND].number) + state = (Open == state ? Closed : Open); + if (Open == state) + CardSelectorSingleton::Instance()->Push(); + CardSelectorSingleton::Instance()->Limit(Open == state ? limitor : NULL, CardView::handZone); + if (Closed == state) + CardSelectorSingleton::Instance()->Pop(); + if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) + backpos.y = Open == state ? OpenY : ClosedY; + else + backpos.x = Open == state ? OpenX : ClosedX; + if (Open == state && OptionClosedHand::INVISIBLE == options[Options::CLOSEDHAND].number) { - if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - { - (*it)->y = SCREEN_HEIGHT + 30; (*it)->UpdateNow(); - } - else - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - { - (*it)->x = SCREEN_WIDTH + 30; (*it)->UpdateNow(); - } + if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + { + (*it)->y = SCREEN_HEIGHT + 30; + (*it)->UpdateNow(); + } + else + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + { + (*it)->x = SCREEN_WIDTH + 30; + (*it)->UpdateNow(); + } } - Repos(); - return true; + Repos(); + return true; } - return false; + return false; } - void GuiHandSelf::Update(float dt) { - backpos.Update(dt); - GuiHand::Update(dt); + backpos.Update(dt); + GuiHand::Update(dt); } void GuiHandSelf::Render() { - //Empty hand - if (state == Open && cards.size() == 0){ - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetColor(ARGB(255,255,0,0)); - if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number){ - back->SetColor(ARGB(255,255,0,0)); - JRenderer::GetInstance()->RenderQuad(back,backpos.actX, backpos.actY, backpos.actT, backpos.actZ, backpos.actZ); - back->SetColor(ARGB(255,255,255,255)); - mFont->DrawString("0",SCREEN_WIDTH - 10,backpos.actY); + //Empty hand + if (state == Open && cards.size() == 0) + { + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetColor(ARGB(255,255,0,0)); + if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) + { + back->SetColor(ARGB(255,255,0,0)); + JRenderer::GetInstance()->RenderQuad(back, backpos.actX, backpos.actY, backpos.actT, backpos.actZ, backpos.actZ); + back->SetColor(ARGB(255,255,255,255)); + mFont->DrawString("0", SCREEN_WIDTH - 10, backpos.actY); + } + else + backpos.Render(back); + return; } - else - backpos.Render(back); - return; - } - backpos.Render(back); - if (OptionClosedHand::VISIBLE == options[Options::CLOSEDHAND].number || state == Open) - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - (*it)->Render(); + backpos.Render(back); + if (OptionClosedHand::VISIBLE == options[Options::CLOSEDHAND].number || state == Open) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + (*it)->Render(); } float GuiHandSelf::LeftBoundary() { - float min = SCREEN_WIDTH + 10; - if (OptionClosedHand::VISIBLE == options[Options::CLOSEDHAND].number || state == Open) - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if ((*it)->x - CardGui::Width / 2 < min) min = (*it)->x - CardGui::Width / 2; - return min; + float min = SCREEN_WIDTH + 10; + if (OptionClosedHand::VISIBLE == options[Options::CLOSEDHAND].number || state == Open) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if ((*it)->x - CardGui::Width / 2 < min) + min = (*it)->x - CardGui::Width / 2; + return min; } int GuiHandSelf::receiveEventPlus(WEvent* e) { - if (WEventZoneChange* ev = dynamic_cast(e)) - if (hand == ev->to) - { - CardView* card; - if (ev->card->view) { + if (WEventZoneChange* ev = dynamic_cast(e)) + if (hand == ev->to) + { + CardView* card; + if (ev->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 - ev->card->view->alpha = 255; + //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 + ev->card->view->alpha = 255; - card = NEW CardView(CardView::handZone, ev->card, *(ev->card->view)); + card = NEW CardView(CardView::handZone, ev->card, *(ev->card->view)); + } + else + card = NEW CardView(CardView::handZone, ev->card, ClosedRowX, 0); + card->t = 6 * M_PI; + cards.push_back(card); + CardSelectorSingleton::Instance()->Add(card); + Repos(); + return 1; } - else - card = NEW CardView(CardView::handZone, ev->card, ClosedRowX, 0); - card->t = 6*M_PI; - cards.push_back(card); - CardSelectorSingleton::Instance()->Add(card); - Repos(); - return 1; - } - return 0; + return 0; } int GuiHandSelf::receiveEventMinus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) + if (WEventZoneChange* event = dynamic_cast(e)) { - if (hand == event->from) - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if (event->card->previous == (*it)->card) - { - CardView* cv = *it; - CardSelectorSingleton::Instance()->Remove(cv); - cards.erase(it); - Repos(); - trash(cv); - return 1; - } - return 1; + if (hand == event->from) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if (event->card->previous == (*it)->card) + { + CardView* cv = *it; + CardSelectorSingleton::Instance()->Remove(cv); + cards.erase(it); + Repos(); + trash(cv); + return 1; + } + return 1; } - return 0; + return 0; } int GuiHandOpponent::receiveEventPlus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) - if (hand == event->to) - { - CardView* card; - if (event->card->view) - card = NEW CardView(CardView::handZone, event->card, *(event->card->view)); - else - card = NEW CardView(CardView::handZone, event->card, ClosedRowX, 0); - card->alpha = 255; card->t = -4*M_PI; - cards.push_back(card); - return 1; - } - return 0; + if (WEventZoneChange* event = dynamic_cast(e)) + if (hand == event->to) + { + CardView* card; + if (event->card->view) + card = NEW CardView(CardView::handZone, event->card, *(event->card->view)); + else + card = NEW CardView(CardView::handZone, event->card, ClosedRowX, 0); + card->alpha = 255; + card->t = -4 * M_PI; + cards.push_back(card); + return 1; + } + return 0; } int GuiHandOpponent::receiveEventMinus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) + if (WEventZoneChange* event = dynamic_cast(e)) { - if (hand == event->from) - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if (event->card->previous == (*it)->card) - { - CardView* cv = *it; - cards.erase(it); - trash(cv); - return 1; - } - return 0; + if (hand == event->from) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if (event->card->previous == (*it)->card) + { + CardView* cv = *it; + cards.erase(it); + trash(cv); + return 1; + } + return 0; } - return 0; + return 0; } // I wanna write it like that. GCC doesn't want me to without -O. diff --git a/projects/mtg/src/GuiLayers.cpp b/projects/mtg/src/GuiLayers.cpp index b27f81ac3..88004181d 100644 --- a/projects/mtg/src/GuiLayers.cpp +++ b/projects/mtg/src/GuiLayers.cpp @@ -3,71 +3,82 @@ #include "GuiLayers.h" #include "Player.h" -GuiLayer::GuiLayer(){ - modal = 0; - hasFocus = false; - mCount = 0; - mCurr = 0; - mActionButton = JGE_BTN_OK; +GuiLayer::GuiLayer() +{ + modal = 0; + hasFocus = false; + mCount = 0; + mCurr = 0; + mActionButton = JGE_BTN_OK; } -GuiLayer::~GuiLayer(){ - resetObjects(); +GuiLayer::~GuiLayer() +{ + resetObjects(); } -void GuiLayer::Add(JGuiObject *object){ - mObjects.push_back(object); - mCount++; +void GuiLayer::Add(JGuiObject *object) +{ + mObjects.push_back(object); + mCount++; } -int GuiLayer::Remove(JGuiObject *object){ - for (int i=0;iRender(); +} + +void GuiLayer::Update(float dt) +{ + for (int i = 0; i < mCount; i++) + if (mObjects[i] != NULL) + mObjects[i]->Update(dt); +} + +void GuiLayer::resetObjects() +{ + for (int i = 0; i < mCount; i++) + if (mObjects[i]) + delete mObjects[i]; + mObjects.clear(); + mCount = 0; + mCurr = 0; +} + +int GuiLayer::getIndexOf(JGuiObject * object) +{ + for (int i = 0; i < mCount; i++) + { + if (mObjects[i] == object) + return i; } - return 0; + return -1; } -int GuiLayer::getMaxId(){ - return mCount; -} - -void GuiLayer::Render(){ - for (int i=0;iRender(); -} - -void GuiLayer::Update(float dt){ - for (int i=0;iUpdate(dt); -} - - -void GuiLayer::resetObjects(){ - for (int i=0;inEmission = 114; - psi->fLifetime = -1; - psi->fParticleLifeMin = 1.1507937f; - psi->fParticleLifeMax = 1.4682540f; - psi->fSpeedMin = 0.0099999998f; - psi->fSizeStart = 0.5f; - psi->fSizeEnd = 0.69999999f; - psi->fSizeVar = 0.25396827f; - psi->fSpinStart = -5.5555553f; - psi->fAlphaVar = 0.77777779f; - psi->sprite = mq; + switch (color) + { + case Constants::MTG_COLOR_RED: + psi = resources.RetrievePSI("manared.psi", mq); + break; + case Constants::MTG_COLOR_BLUE: + psi = resources.RetrievePSI("manablue.psi", mq); + break; + case Constants::MTG_COLOR_GREEN: + psi = resources.RetrievePSI("managreen.psi", mq); + break; + case Constants::MTG_COLOR_BLACK: + psi = resources.RetrievePSI("manablack.psi", mq); + break; + case Constants::MTG_COLOR_WHITE: + psi = resources.RetrievePSI("manawhite.psi", mq); + break; + default: + psi = resources.RetrievePSI("mana.psi", mq); } - switch(color){ - case Constants::MTG_COLOR_RED : - psi->colColorStart.SetHWColor(ARGB(161,240,40,44)); - psi->colColorEnd.SetHWColor(ARGB(14,242,155,153)); - break; - case Constants::MTG_COLOR_BLUE : - psi->colColorStart.SetHWColor(ARGB(161,28,40,224)); - psi->colColorEnd.SetHWColor(ARGB(14,255,255,255)); - break; - case Constants::MTG_COLOR_GREEN : - psi->colColorStart.SetHWColor(ARGB(161,36,242,44)); - psi->colColorEnd.SetHWColor(ARGB(14,129,244,153)); - break; - case Constants::MTG_COLOR_BLACK : - psi->colColorStart.SetHWColor(ARGB(161,210,117,210)); - psi->colColorEnd.SetHWColor(ARGB(14,80,56,80)); - break; - case Constants::MTG_COLOR_WHITE : - psi->colColorStart.SetHWColor(ARGB(151,151,127,38)); - psi->colColorEnd.SetHWColor(ARGB(8,255,255,255)); - break; - default: - psi->colColorStart.SetHWColor(ARGB(161,236,242,232)); - psi->colColorEnd.SetHWColor(ARGB(14,238,244,204)); - break; + if (!psi) + { + psi = NEW hgeParticleSystemInfo(); + if (!psi) + return; + hgeParticleSystemInfo * defaults = resources.RetrievePSI("mana.psi", mq); + if (defaults) + { + memcpy(psi, defaults, sizeof(hgeParticleSystemInfo)); + } + else + { + memset(psi, 0, sizeof(hgeParticleSystemInfo)); + + //Default values for particle system! Cribbed from mana.psi + //Really, we should just be loading that and then changing colors... + psi->nEmission = 114; + psi->fLifetime = -1; + psi->fParticleLifeMin = 1.1507937f; + psi->fParticleLifeMax = 1.4682540f; + psi->fSpeedMin = 0.0099999998f; + psi->fSizeStart = 0.5f; + psi->fSizeEnd = 0.69999999f; + psi->fSizeVar = 0.25396827f; + psi->fSpinStart = -5.5555553f; + psi->fAlphaVar = 0.77777779f; + psi->sprite = mq; + } + + switch (color) + { + case Constants::MTG_COLOR_RED: + psi->colColorStart.SetHWColor(ARGB(161,240,40,44)); + psi->colColorEnd.SetHWColor(ARGB(14,242,155,153)); + break; + case Constants::MTG_COLOR_BLUE: + psi->colColorStart.SetHWColor(ARGB(161,28,40,224)); + psi->colColorEnd.SetHWColor(ARGB(14,255,255,255)); + break; + case Constants::MTG_COLOR_GREEN: + psi->colColorStart.SetHWColor(ARGB(161,36,242,44)); + psi->colColorEnd.SetHWColor(ARGB(14,129,244,153)); + break; + case Constants::MTG_COLOR_BLACK: + psi->colColorStart.SetHWColor(ARGB(161,210,117,210)); + psi->colColorEnd.SetHWColor(ARGB(14,80,56,80)); + break; + case Constants::MTG_COLOR_WHITE: + psi->colColorStart.SetHWColor(ARGB(151,151,127,38)); + psi->colColorEnd.SetHWColor(ARGB(8,255,255,255)); + break; + default: + psi->colColorStart.SetHWColor(ARGB(161,236,242,232)); + psi->colColorEnd.SetHWColor(ARGB(14,238,244,204)); + break; + } + + particleSys = NEW hgeParticleSystem(psi); + SAFE_DELETE(psi); //This version of psi is not handled by cache, so kill it here. } + else + particleSys = NEW hgeParticleSystem(psi); //Cache will clean psi up later. - particleSys = NEW hgeParticleSystem(psi); - SAFE_DELETE(psi); //This version of psi is not handled by cache, so kill it here. - } - else - particleSys = NEW hgeParticleSystem(psi); //Cache will clean psi up later. + // if we want to throttle the amount of particles for mana, + // here's where to do it - this is hardcoded to something like 114 in the psi file + particleSys->info.nEmission = 60; + icon = manaIcons[color]; - // if we want to throttle the amount of particles for mana, - // here's where to do it - this is hardcoded to something like 114 in the psi file - particleSys->info.nEmission = 60; - icon = manaIcons[color]; + particleSys->FireAt(x, y); - particleSys->FireAt(x, y); + zoomP1 = 0.2f + 0.1f * ((float) rand() / (float) RAND_MAX); + zoomP2 = 0.2f + 0.1f * ((float) rand() / (float) RAND_MAX); + zoomP3 = 2 * M_PI * ((float) rand() / (float) RAND_MAX); + zoomP4 = 2 * M_PI * ((float) rand() / (float) RAND_MAX); + zoomP5 = 0.5f + ((float) rand() / (float) RAND_MAX); + zoomP6 = 0.5f + ((float) rand() / (float) RAND_MAX); - zoomP1 = 0.2f + 0.1f * ((float)rand() / (float)RAND_MAX); - zoomP2 = 0.2f + 0.1f * ((float)rand() / (float)RAND_MAX); - zoomP3 = 2 * M_PI * ((float)rand() / (float)RAND_MAX); - zoomP4 = 2 * M_PI * ((float)rand() / (float)RAND_MAX); - zoomP5 = 0.5f + ((float)rand() / (float)RAND_MAX); - zoomP6 = 0.5f + ((float)rand() / (float)RAND_MAX); + xP1 = 2 * M_PI * ((float) rand() / (float) RAND_MAX); + xP2 = 5 + 30 * ((float) rand() / (float) RAND_MAX); + xP3 = 0.5f + ((float) rand() / (float) RAND_MAX); + yP1 = 2 * M_PI * ((float) rand() / (float) RAND_MAX); + yP2 = 5 + 10 * ((float) rand() / (float) RAND_MAX); + yP3 = 0.5f + ((float) rand() / (float) RAND_MAX); - xP1 = 2 * M_PI * ((float)rand() / (float)RAND_MAX); - xP2 = 5 + 30 * ((float)rand() / (float)RAND_MAX); - xP3 = 0.5f + ((float)rand() / (float)RAND_MAX); - yP1 = 2 * M_PI * ((float)rand() / (float)RAND_MAX); - yP2 = 5 + 10 * ((float)rand() / (float)RAND_MAX); - yP3 = 0.5f + ((float)rand() / (float)RAND_MAX); - - actT = 0; - tP1 = 0; + actT = 0; + tP1 = 0; } ManaIcon::~ManaIcon() { - SAFE_DELETE(particleSys); + SAFE_DELETE(particleSys); } void ManaIcon::Render() { - if(!particleSys) - return; + if (!particleSys) + return; - JRenderer* renderer = JRenderer::GetInstance(); + JRenderer* renderer = JRenderer::GetInstance(); - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); - particleSys->Render(); - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - renderer->RenderQuad(icon, actX, actY, actT, actZ + zoomP1 * sinf(M_PI * zoomP3), actZ + zoomP2 * cosf(M_PI * zoomP4)); + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); + particleSys->Render(); + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + renderer->RenderQuad(icon, actX, actY, actT, actZ + zoomP1 * sinf(M_PI * zoomP3), actZ + zoomP2 * cosf(M_PI * zoomP4)); } void ManaIcon::Update(float dt, float shift) { - xP1 += xP3 * dt; - actX = x + xP2 * sinf(M_PI * xP1); - zoomP3 += zoomP5 * dt; - zoomP4 += zoomP6 * dt; + xP1 += xP3 * dt; + actX = x + xP2 * sinf(M_PI * xP1); + zoomP3 += zoomP5 * dt; + zoomP4 += zoomP6 * dt; - if (OptionManaDisplay::STATIC == options[Options::MANADISPLAY].number) - shift = 0; + if (OptionManaDisplay::STATIC == options[Options::MANADISPLAY].number) + shift = 0; - switch (mode) + switch (mode) { - case DROPPING : - f += dt * 700; - actY += f * dt; - if (actY > SCREEN_HEIGHT * 2) mode = DEAD; - break; - case WITHERING : - actT += dt * 4; - actZ /= f; zoomP1 /= f; zoomP2 /= f; - f -= dt; - actZ *= f; zoomP1 *= f; zoomP2 *= f; - yP1 += yP3 * dt; - actY = y + yP2 * sinf(M_PI * yP1); - if (f < 0) mode = DEAD; - break; - case ALIVE : - x += 10 * dt * (destx - x); - y += 10 * dt * (desty + shift - y); - yP1 += yP3 * dt; - actY = y + yP2 * sinf(M_PI * yP1); + case DROPPING: + f += dt * 700; + actY += f * dt; + if (actY > SCREEN_HEIGHT * 2) + mode = DEAD; + break; + case WITHERING: + actT += dt * 4; + actZ /= f; + zoomP1 /= f; + zoomP2 /= f; + f -= dt; + actZ *= f; + zoomP1 *= f; + zoomP2 *= f; + yP1 += yP3 * dt; + actY = y + yP2 * sinf(M_PI * yP1); + if (f < 0) + mode = DEAD; + break; + case ALIVE: + x += 10 * dt * (destx - x); + y += 10 * dt * (desty + shift - y); + yP1 += yP3 * dt; + actY = y + yP2 * sinf(M_PI * yP1); - if (particleSys && (fabs(destx - x) < 5) && (fabs(desty + shift - y) < 5)){ - if (OptionManaDisplay::STATIC == options[Options::MANADISPLAY].number){ - SAFE_DELETE(particleSys); //Static Mana Only: avoid expensive particle processing + if (particleSys && (fabs(destx - x) < 5) && (fabs(desty + shift - y) < 5)) + { + if (OptionManaDisplay::STATIC == options[Options::MANADISPLAY].number) + { + SAFE_DELETE(particleSys); //Static Mana Only: avoid expensive particle processing + } } - } - break; - case DEAD : - break; + break; + case DEAD: + break; } - if (particleSys){ - particleSys->MoveTo(actX, actY); - particleSys->Update(dt); - } + if (particleSys) + { + particleSys->MoveTo(actX, actY); + particleSys->Update(dt); + } } void ManaIcon::Wither() { - mode = WITHERING; - f = 1.0; - if (particleSys) particleSys->Stop(); + mode = WITHERING; + f = 1.0; + if (particleSys) + particleSys->Stop(); } void ManaIcon::Drop() { - mode = DROPPING; - if (f < 0) f = 0; - if (particleSys) particleSys->Stop(); + mode = DROPPING; + if (f < 0) + f = 0; + if (particleSys) + particleSys->Stop(); } -GuiMana::GuiMana(float x, float y, Player *p):x(x),y(y),owner(p) +GuiMana::GuiMana(float x, float y, Player *p) : + x(x), y(y), owner(p) { } -GuiMana::~GuiMana(){ - for (vector::iterator it = manas.begin(); it != manas.end(); ++it){ - delete(*it); - } +GuiMana::~GuiMana() +{ + for (vector::iterator it = manas.begin(); it != manas.end(); ++it) + { + delete (*it); + } } +void GuiMana::RenderStatic() +{ + int values[Constants::MTG_NB_COLORS]; + int totalColors = 0; + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + JRenderer * r = JRenderer::GetInstance(); + for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) + values[i] = 0; + for (vector::iterator it = manas.begin(); it != manas.end(); ++it) + if (ManaIcon::ALIVE == (*it)->mode) + { + values[(*it)->color]++; + if (values[(*it)->color] == 1) + totalColors++; + } -void GuiMana::RenderStatic(){ - int values[Constants::MTG_NB_COLORS]; - int totalColors = 0; - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - JRenderer * r = JRenderer::GetInstance(); - for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) - values[i] = 0; - for (vector::iterator it = manas.begin(); it != manas.end(); ++it) - if (ManaIcon::ALIVE == (*it)->mode) { - values[(*it)->color]++; - if (values[(*it)->color] == 1) totalColors++; + if (!totalColors) + return; + + float x0 = x - 20 * totalColors; + if (x0 < 10) + x0 = 10; + float xEnd = x0 + 20 * totalColors; + r->FillRoundRect(x0, y - 5, static_cast (20 * totalColors + 5), 20, 2, ARGB(128,0,0,0)); + + int offset = 0; + for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) + { + if (values[i]) + { + offset -= 20; + r->RenderQuad(manaIcons[i], xEnd + 15 + offset, y + 5, 0, 0.7f, 0.7f); + } } - - if (!totalColors) return; - - float x0 = x - 20*totalColors; - if (x0 < 10) x0 = 10; - float xEnd = x0 + 20*totalColors; - r->FillRoundRect(x0, y - 5, static_cast(20 * totalColors + 5), 20, 2, ARGB(128,0,0,0)); - - int offset = 0; - for (int i = 0; i < Constants::MTG_NB_COLORS; ++i){ - if (values[i]){ - offset-=20; - r->RenderQuad(manaIcons[i],xEnd + 15 + offset, y + 5, 0, 0.7f, 0.7f); + r->FillRoundRect(x0, y, static_cast (20 * totalColors + 5), 8, 2, ARGB(100,0,0,0)); + offset = 0; + for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) + { + if (values[i]) + { + offset -= 20; + char buf[4]; + sprintf(buf, "%i", values[i]); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(buf, xEnd + offset + 9, y); + } } - } - r->FillRoundRect(x0, y, static_cast(20 * totalColors + 5), 8, 2, ARGB(100,0,0,0)); - offset = 0; - for (int i = 0; i < Constants::MTG_NB_COLORS; ++i){ - if (values[i]){ - offset-=20; - char buf[4]; - sprintf(buf,"%i",values[i]); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(buf,xEnd+offset + 9, y); - } - } } void GuiMana::Render() { - for (vector::iterator it = manas.begin(); it != manas.end(); ++it) - (*it)->Render(); + for (vector::iterator it = manas.begin(); it != manas.end(); ++it) + (*it)->Render(); - if (OptionManaDisplay::DYNAMIC != options[Options::MANADISPLAY].number) - RenderStatic(); + if (OptionManaDisplay::DYNAMIC != options[Options::MANADISPLAY].number) + RenderStatic(); } -bool remove_dead(ManaIcon* m) { return ManaIcon::DEAD != m->mode; } +bool remove_dead(ManaIcon* m) +{ + return ManaIcon::DEAD != m->mode; +} void GuiMana::Update(float dt) { - { - float shift = 0; - for (vector::iterator it = manas.begin(); it != manas.end(); ++it) - { (*it)->Update(dt, shift); shift += 15; } - } - vector::iterator it = partition(manas.begin(), manas.end(), &remove_dead); - if (it != manas.end()) { - for (vector::iterator q = it; q != manas.end(); ++q) - SAFE_DELETE(*q); - manas.erase(it, manas.end()); + float shift = 0; + for (vector::iterator it = manas.begin(); it != manas.end(); ++it) + { + (*it)->Update(dt, shift); + shift += 15; + } + } + vector::iterator it = partition(manas.begin(), manas.end(), &remove_dead); + if (it != manas.end()) + { + for (vector::iterator q = it; q != manas.end(); ++q) + SAFE_DELETE(*q); + manas.erase(it, manas.end()); } } int GuiMana::receiveEventPlus(WEvent* e) { - if (WEventEngageMana *event = dynamic_cast(e)) + if (WEventEngageMana *event = dynamic_cast(e)) { - if (event->destination != owner->getManaPool()) return 0; - if (event->card && event->card->view) - manas.push_back(NEW ManaIcon(event->color, event->card->view->actX, event->card->view->actY, x, y)); - else - manas.push_back(NEW ManaIcon(event->color, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, x, y)); - return 1; + if (event->destination != owner->getManaPool()) + return 0; + if (event->card && event->card->view) + manas.push_back(NEW ManaIcon(event->color, event->card->view->actX, event->card->view->actY, x, y)); + else + manas.push_back(NEW ManaIcon(event->color, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, x, y)); + return 1; } - else return 0; + else + return 0; } int GuiMana::receiveEventMinus(WEvent* e) { - if (WEventConsumeMana *event = dynamic_cast(e)) + if (WEventConsumeMana *event = dynamic_cast(e)) { - if (event->source != owner->getManaPool()) return 0; - for (vector::iterator it = manas.begin(); it != manas.end(); ++it) - if ((event->color == (*it)->color) && (ManaIcon::ALIVE == (*it)->mode)) { - (*it)->Wither(); - return 1; - } - return 1; + if (event->source != owner->getManaPool()) + return 0; + for (vector::iterator it = manas.begin(); it != manas.end(); ++it) + if ((event->color == (*it)->color) && (ManaIcon::ALIVE == (*it)->mode)) + { + (*it)->Wither(); + return 1; + } + return 1; } - else if (WEventEmptyManaPool *event2 = dynamic_cast(e)) + else if (WEventEmptyManaPool *event2 = dynamic_cast(e)) { - if (event2->source != owner->getManaPool()) return 0; - for (vector::iterator it = manas.begin(); it != manas.end(); ++it) - (*it)->Drop(); - return 1; + if (event2->source != owner->getManaPool()) + return 0; + for (vector::iterator it = manas.begin(); it != manas.end(); ++it) + (*it)->Drop(); + return 1; } - return 0; + return 0; } diff --git a/projects/mtg/src/GuiMessageBox.cpp b/projects/mtg/src/GuiMessageBox.cpp index 8fbcff139..94b22ac0c 100644 --- a/projects/mtg/src/GuiMessageBox.cpp +++ b/projects/mtg/src/GuiMessageBox.cpp @@ -1,55 +1,56 @@ #include "GuiMessageBox.h" -bool GuiMessageBox::CheckUserInput(JButton key){ - if (mActionButton == key) +bool GuiMessageBox::CheckUserInput(JButton key) +{ + if (mActionButton == key) { - if (mObjects[mCurr] != NULL && mObjects[mCurr]->ButtonPressed()) - { - if (mListener != NULL) - { - mListener->ButtonPressed(mId, mObjects[mCurr]->GetId()); - return true; - } - } + if (mObjects[mCurr] != NULL && mObjects[mCurr]->ButtonPressed()) + { + if (mListener != NULL) + { + mListener->ButtonPressed(mId, mObjects[mCurr]->GetId()); + return true; + } + } } - if ((PSP_CTRL_LEFT == key) || (PSP_CTRL_UP == key)) // || mEngine->GetAnalogY()<64) + if ((PSP_CTRL_LEFT == key) || (PSP_CTRL_UP == key)) // || mEngine->GetAnalogY()<64) { - int n = mCurr; - n--; - if (n<0) - { - if ((mStyle&JGUI_STYLE_WRAPPING)) - n = mCount-1; - else - n = 0; - } + int n = mCurr; + n--; + if (n < 0) + { + if ((mStyle & JGUI_STYLE_WRAPPING)) + n = mCount - 1; + else + n = 0; + } - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_UP)) - { - mCurr = n; - mObjects[mCurr]->Entering(); - } - return true; + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_UP)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + return true; } - else if ((PSP_CTRL_RIGHT == key) || (PSP_CTRL_DOWN == key)) // || mEngine->GetAnalogY()>192) + else if ((PSP_CTRL_RIGHT == key) || (PSP_CTRL_DOWN == key)) // || mEngine->GetAnalogY()>192) { - int n = mCurr; - n++; - if (n>mCount-1) - { - if ((mStyle&JGUI_STYLE_WRAPPING)) - n = 0; - else - n = mCount-1; - } + int n = mCurr; + n++; + if (n > mCount - 1) + { + if ((mStyle & JGUI_STYLE_WRAPPING)) + n = 0; + else + n = mCount - 1; + } - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN)) - { - mCurr = n; - mObjects[mCurr]->Entering(); - } - return true; + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + return true; } - return false; + return false; } diff --git a/projects/mtg/src/GuiPhaseBar.cpp b/projects/mtg/src/GuiPhaseBar.cpp index 833987e10..761857fe0 100644 --- a/projects/mtg/src/GuiPhaseBar.cpp +++ b/projects/mtg/src/GuiPhaseBar.cpp @@ -6,49 +6,51 @@ #include "Translate.h" /* -static int colors[] = - { - ARGB(255, 255, 255, 255), - ARGB(255, 255, 000, 000), - ARGB(255, 000, 255, 000), - ARGB(255, 000, 000, 255), - ARGB(255, 255, 255, 000), - ARGB(255, 255, 000, 255), - ARGB(255, 000, 255, 255), - ARGB(255, 000, 000, 000), - ARGB(255, 255, 255, 255), - ARGB(255, 255, 255, 255), - ARGB(255, 255, 255, 255), - ARGB(255, 255, 255, 255) - }; -*/ + static int colors[] = + { + ARGB(255, 255, 255, 255), + ARGB(255, 255, 000, 000), + ARGB(255, 000, 255, 000), + ARGB(255, 000, 000, 255), + ARGB(255, 255, 255, 000), + ARGB(255, 255, 000, 255), + ARGB(255, 000, 255, 255), + ARGB(255, 000, 000, 000), + ARGB(255, 255, 255, 255), + ARGB(255, 255, 255, 255), + ARGB(255, 255, 255, 255), + ARGB(255, 255, 255, 255) + }; + */ namespace { - const float kWidth = 28; - const float kHeight = kWidth; - const unsigned kPhases = 12; + const float kWidth = 28; + const float kHeight = kWidth; + const unsigned kPhases = 12; - const float ICONSCALE = 1.5; - const float CENTER = SCREEN_HEIGHT_F / 2 + 10; + const float ICONSCALE = 1.5; + const float CENTER = SCREEN_HEIGHT_F / 2 + 10; - - void DrawGlyph(JQuad* inQuad, int inGlyph, float inY, float inAngle, unsigned int inP, float inScale) - { - float xPos = static_cast((inP + inGlyph * (int)(kWidth+1)) % (kPhases * (int)(kWidth+1))); - inQuad->SetTextureRect(xPos, 0, kWidth, kHeight); - JRenderer::GetInstance()->RenderQuad(inQuad, 0, inY, 0.0, inScale, inScale); - } + void DrawGlyph(JQuad* inQuad, int inGlyph, float inY, float inAngle, unsigned int inP, float inScale) + { + float xPos = static_cast ((inP + inGlyph * (int) (kWidth + 1)) % (kPhases * (int) (kWidth + 1))); + inQuad->SetTextureRect(xPos, 0, kWidth, kHeight); + JRenderer::GetInstance()->RenderQuad(inQuad, 0, inY, 0.0, inScale, inScale); + } } -GuiPhaseBar::GuiPhaseBar() : phase(NULL), angle(0.0f) +GuiPhaseBar::GuiPhaseBar() : + phase(NULL), angle(0.0f) { - JQuad * quad = NULL; - if ((quad = resources.GetQuad("phasebar")) != NULL){ - quad->mHeight = kHeight; - quad->mWidth = kWidth; - } - else GameApp::systemError = "Error loading phasebar texture : " __FILE__; + JQuad * quad = NULL; + if ((quad = resources.GetQuad("phasebar")) != NULL) + { + quad->mHeight = kHeight; + quad->mWidth = kWidth; + } + else + GameApp::systemError = "Error loading phasebar texture : " __FILE__; } GuiPhaseBar::~GuiPhaseBar() @@ -57,74 +59,84 @@ GuiPhaseBar::~GuiPhaseBar() void GuiPhaseBar::Update(float dt) { - if (angle > 3*dt) angle -= 3*dt; else angle = 0; + if (angle > 3 * dt) + angle -= 3 * dt; + else + angle = 0; } void GuiPhaseBar::Render() { - GameObserver * g = GameObserver::GetInstance(); - JQuad * quad = resources.GetQuad("phasebar"); - - JRenderer::GetInstance()->DrawLine(0, CENTER, SCREEN_WIDTH, CENTER, ARGB(255, 255, 255, 255)); + GameObserver * g = GameObserver::GetInstance(); + JQuad * quad = resources.GetQuad("phasebar"); - unsigned int p = (phase->id + kPhases - 4) * (int)(kWidth+1); - float centerYPosition = CENTER + (kWidth / 2) * angle * ICONSCALE / (M_PI / 6) - ICONSCALE * kWidth / 4; - float yPos = centerYPosition; - float scale = 0; - for (int glyph = 3; glyph < 6; ++glyph) - { - scale = ICONSCALE * sinf(angle + glyph * M_PI / 6) / 2; - DrawGlyph(quad, glyph, yPos, angle, p, scale); - yPos += kWidth * scale; - } + JRenderer::GetInstance()->DrawLine(0, CENTER, SCREEN_WIDTH, CENTER, ARGB(255, 255, 255, 255)); - yPos = centerYPosition; - for (int glyph = 2; glyph > 0; --glyph) - { - scale = ICONSCALE * sinf(angle + glyph * M_PI / 6) / 2; - yPos -= kWidth * scale; - DrawGlyph(quad, glyph, yPos, angle, p, scale); - } - - if (angle > 0) - { - scale = ICONSCALE * sinf(angle)/2; - yPos -= kWidth * scale; - float xPos = static_cast(p % (kPhases * (int)(kWidth+1))); - quad->SetTextureRect(xPos, kHeight, kWidth, kHeight); - JRenderer::GetInstance()->RenderQuad(quad, 0, yPos, 0.0, scale, scale); - } - - //print phase name - WFont * font = resources.GetWFont(Fonts::MAIN_FONT); - string currentP = _("your turn"); - string interrupt = ""; - if (g->currentPlayer == g->players[1]){ - currentP = _("opponent's turn"); - } - font->SetColor(ARGB(255, 255, 255, 255)); - if (g->currentlyActing()->isAI()){ - font->SetColor(ARGB(255, 128, 128, 128)); - } - if (g->currentlyActing() != g->currentPlayer){ - if (g->currentPlayer == g->players[0]) { - interrupt = _(" - ")+_("opponent plays"); - }else{ - interrupt = _(" - ")+_("you play"); + unsigned int p = (phase->id + kPhases - 4) * (int) (kWidth + 1); + float centerYPosition = CENTER + (kWidth / 2) * angle * ICONSCALE / (M_PI / 6) - ICONSCALE * kWidth / 4; + float yPos = centerYPosition; + float scale = 0; + for (int glyph = 3; glyph < 6; ++glyph) + { + scale = ICONSCALE * sinf(angle + glyph * M_PI / 6) / 2; + DrawGlyph(quad, glyph, yPos, angle, p, scale); + yPos += kWidth * scale; } - } - char buf[64]; sprintf(buf, _("(%s%s) %s").c_str(), currentP.c_str(),interrupt.c_str(),_(PhaseRing::phaseName(phase->id)).c_str()); - font->DrawString(buf, SCREEN_WIDTH-5, 2,JGETEXT_RIGHT); + yPos = centerYPosition; + for (int glyph = 2; glyph > 0; --glyph) + { + scale = ICONSCALE * sinf(angle + glyph * M_PI / 6) / 2; + yPos -= kWidth * scale; + DrawGlyph(quad, glyph, yPos, angle, p, scale); + } + + if (angle > 0) + { + scale = ICONSCALE * sinf(angle) / 2; + yPos -= kWidth * scale; + float xPos = static_cast (p % (kPhases * (int) (kWidth + 1))); + quad->SetTextureRect(xPos, kHeight, kWidth, kHeight); + JRenderer::GetInstance()->RenderQuad(quad, 0, yPos, 0.0, scale, scale); + } + + //print phase name + WFont * font = resources.GetWFont(Fonts::MAIN_FONT); + string currentP = _("your turn"); + string interrupt = ""; + if (g->currentPlayer == g->players[1]) + { + currentP = _("opponent's turn"); + } + font->SetColor(ARGB(255, 255, 255, 255)); + if (g->currentlyActing()->isAI()) + { + font->SetColor(ARGB(255, 128, 128, 128)); + } + if (g->currentlyActing() != g->currentPlayer) + { + if (g->currentPlayer == g->players[0]) + { + interrupt = _(" - ") + _("opponent plays"); + } + else + { + interrupt = _(" - ") + _("you play"); + } + } + + char buf[64]; + sprintf(buf, _("(%s%s) %s").c_str(), currentP.c_str(), interrupt.c_str(), _(PhaseRing::phaseName(phase->id)).c_str()); + font->DrawString(buf, SCREEN_WIDTH - 5, 2, JGETEXT_RIGHT); } int GuiPhaseBar::receiveEventMinus(WEvent *e) { - WEventPhaseChange *event = dynamic_cast(e); - if (event) + WEventPhaseChange *event = dynamic_cast (e); + if (event) { - angle = M_PI / 6; - phase = event->to; + angle = M_PI / 6; + phase = event->to; } - return 1; + return 1; } diff --git a/projects/mtg/src/GuiPlay.cpp b/projects/mtg/src/GuiPlay.cpp index f61ffe8ba..8f7811578 100644 --- a/projects/mtg/src/GuiPlay.cpp +++ b/projects/mtg/src/GuiPlay.cpp @@ -12,293 +12,366 @@ 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; + 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) + 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; + 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() {} +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; + 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(); + 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; + 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) { - if (0 == count % 3) { x += CARD_WIDTH; y = 0; } - card->x = x + baseX; card->y = y + baseY; - y += 12; - if (++count == total-1 && y == 12) y += 12; + if (0 == count % 3) + { + 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(); + 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; } +inline float GuiPlay::VertStack::nextX() +{ + if (0 == count) + return x + CARD_WIDTH; + else + return x; +} -GuiPlay::BattleField::BattleField() : attackers(0), blockers(0), height(0.0), red(0), colorFlow(0) {} +GuiPlay::BattleField::BattleField() : + attackers(0), blockers(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::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) { - GameObserver* game = GameObserver::GetInstance(); - card->x = currentAttacker * (HORZWIDTH-20) / (attackers + 1); card->y = baseY + (game->players[0] == card->card->controller() ? 20 + y : -20 - y); - ++currentAttacker; - // JRenderer::GetInstance()->RenderQuad(resources.GetQuad("BattleIcon"), card->actX, card->actY, 0, 0.5 + 0.1 * sinf(JGE::GetInstance()->GetTime()), 0.5 + 0.1 * sinf(JGE::GetInstance()->GetTime())); + GameObserver* game = GameObserver::GetInstance(); + card->x = currentAttacker * (HORZWIDTH - 20) / (attackers + 1); + card->y = baseY + (game->players[0] == card->card->controller() ? 20 + y : -20 - y); + ++currentAttacker; + // JRenderer::GetInstance()->RenderQuad(resources.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) { - GameObserver* game = GameObserver::GetInstance(); - 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 + (game->players[0] == card->card->controller() ? 20 + y + 6 * offset : -20 - y + 6 * offset); + GameObserver* game = GameObserver::GetInstance(); + 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 + (game->players[0] == 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 (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; - } + 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(22, SCREEN_HEIGHT / 2 + 10 - height / 2, 250, height, ARGB(127, red, 0, 0)); + if (height > 3) + JRenderer::GetInstance()->FillRect(22, SCREEN_HEIGHT / 2 + 10 - height / 2, 250, height, ARGB(127, red, 0, 0)); } -GuiPlay::GuiPlay(GameObserver* game) : game(game) +GuiPlay::GuiPlay(GameObserver* game) : + game(game) { - end_spells = cards.end(); + end_spells = cards.end(); } GuiPlay::~GuiPlay() { - for (iterator it = cards.begin(); it != cards.end(); ++it){ - delete(*it); - } + for (iterator it = cards.begin(); it != cards.end(); ++it) + { + delete (*it); + } } -bool isSpell(CardView* c) { return c->card->isSpell() && !c->card->isCreature(); } +bool isSpell(CardView* c) +{ + return c->card->isSpell() && !c->card->isCreature(); +} void GuiPlay::Replace() { - unsigned opponentSpellsN = 0, selfSpellsN = 0, opponentLandsN = 0, opponentCreaturesN = 0, - battleFieldAttackersN = 0, battleFieldBlockersN = 0, selfCreaturesN = 0, selfLandsN = 0; + 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); + end_spells = stable_partition(cards.begin(), cards.end(), &isSpell); - for (iterator it = cards.begin(); it != end_spells; ++it) - if (!(*it)->card->target) - { - if (game->players[0] == (*it)->card->controller()) ++selfSpellsN; - else ++opponentSpellsN; - } - for (iterator it = end_spells; it != cards.end(); ++it) + for (iterator it = cards.begin(); it != end_spells; ++it) + if (!(*it)->card->target) + { + if (game->players[0] == (*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 (game->players[0] == (*it)->card->controller()) ++selfCreaturesN; - else ++opponentCreaturesN; - } - else if ((*it)->card->isLand()) - { - if (game->players[0] == (*it)->card->controller()) ++selfLandsN; - else ++opponentLandsN; - } + if ((*it)->card->isCreature()) + { + if ((*it)->card->isAttacker()) + ++battleFieldAttackersN; + else if ((*it)->card->isDefenser()) + ++battleFieldBlockersN; + else if (game->players[0] == (*it)->card->controller()) + ++selfCreaturesN; + else + ++opponentCreaturesN; + } + else if ((*it)->card->isLand()) + { + if (game->players[0] == (*it)->card->controller()) + ++selfLandsN; + else + ++opponentLandsN; + } } - opponentSpells.reset(opponentSpellsN, 18, 60); - selfSpells.reset(selfSpellsN, 18, 215); + opponentSpells.reset(opponentSpellsN, 18, 60); + selfSpells.reset(selfSpellsN, 18, 215); - for (iterator it = cards.begin(); it != end_spells; ++it) - if (!(*it)->card->target) - { - if (game->players[0] == (*it)->card->controller()) selfSpells.Enstack(*it); - else opponentSpells.Enstack(*it); - } + for (iterator it = cards.begin(); it != end_spells; ++it) + if (!(*it)->card->target) + { + if (game->players[0] == (*it)->card->controller()) + selfSpells.Enstack(*it); + else + opponentSpells.Enstack(*it); + } - float x = 24 + opponentSpells.nextX(); -//seperated the varible X into 2 different varibles. There are 2 players here!! -//we should not be using a single varible 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 varible do? i can comment it out with no reprocussions...is this being double handled? - selfCreatures.reset(selfCreaturesN, myx, 195); - selfLands.reset(selfLandsN, myx, 240); + float x = 24 + opponentSpells.nextX(); + //seperated the varible X into 2 different varibles. There are 2 players here!! + //we should not be using a single varible 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 varible do? i can comment it out with no reprocussions...is this being double handled? + selfCreatures.reset(selfCreaturesN, myx, 195); + selfLands.reset(selfLandsN, myx, 240); - - for (iterator it = end_spells; it != cards.end(); ++it) + 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 (game->players[0] == (*it)->card->controller()) selfCreatures.Enstack(*it); - else opponentCreatures.Enstack(*it); - } - else if ((*it)->card->isLand()) - { - if (game->players[0] == (*it)->card->controller()) selfLands.Enstack(*it); - else opponentLands.Enstack(*it); - } + if ((*it)->card->isCreature()) + { + if ((*it)->card->isAttacker()) + battleField.EnstackAttacker(*it); + else if ((*it)->card->isDefenser()) + battleField.EnstackBlocker(*it); + else if (game->players[0] == (*it)->card->controller()) + selfCreatures.Enstack(*it); + else + opponentCreatures.Enstack(*it); + } + else if ((*it)->card->isLand()) + { + if (game->players[0] == (*it)->card->controller()) + selfLands.Enstack(*it); + else + opponentLands.Enstack(*it); + } } } void GuiPlay::Render() { - battleField.Render(); + battleField.Render(); - for (iterator it = cards.begin(); it != cards.end(); ++it) - if ((*it)->card->isLand()) - { - if (game->players[0] == (*it)->card->controller()) selfLands.Render(*it, cards.begin(), end_spells); - else opponentLands.Render(*it, cards.begin(), end_spells); - } - else if ((*it)->card->isCreature()) - { - if (game->players[0] == (*it)->card->controller()) selfCreatures.Render(*it, cards.begin(), end_spells); - else opponentCreatures.Render(*it, cards.begin(), end_spells); - } - else{ - if (!(*it)->card->target) { - if (game->players[0] == (*it)->card->controller()) selfSpells.Render(*it, cards.begin(), end_spells); - else opponentSpells.Render(*it, cards.begin(), end_spells); - } - } + for (iterator it = cards.begin(); it != cards.end(); ++it) + if ((*it)->card->isLand()) + { + if (game->players[0] == (*it)->card->controller()) + selfLands.Render(*it, cards.begin(), end_spells); + else + opponentLands.Render(*it, cards.begin(), end_spells); + } + else if ((*it)->card->isCreature()) + { + if (game->players[0] == (*it)->card->controller()) + selfCreatures.Render(*it, cards.begin(), end_spells); + else + opponentCreatures.Render(*it, cards.begin(), end_spells); + } + else + { + if (!(*it)->card->target) + { + if (game->players[0] == (*it)->card->controller()) + selfSpells.Render(*it, cards.begin(), end_spells); + else + opponentSpells.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); + 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 ((game->players[0]->inPlay() == event->to) || - (game->players[1]->inPlay() == event->to)) + if (WEventZoneChange *event = dynamic_cast(e)) { - 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; + if ((game->players[0]->inPlay() == event->to) || (game->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); - card->t = event->card->isTapped() ? M_PI / 2 : 0; - 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(); - CardSelectorSingleton::Instance()->Add(card); - return 1; + card = NEW CardView(CardView::playZone, event->card, *(event->card->view)); + } + else + card = NEW CardView(CardView::playZone, event->card, 0, 0); + cards.push_back(card); + card->t = event->card->isTapped() ? M_PI / 2 : 0; + 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(); + CardSelectorSingleton::Instance()->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)) - cv->t = event->after ? M_PI / 2 : 0; - else - event->card->view->actT = event->after ? M_PI / 2 : 0; - return 1; - } - else if (WEventPhaseChange *event = dynamic_cast(e)) - { - if (Constants::MTG_PHASE_COMBATEND == event->to->id) battleField.colorFlow = -1; - } - else if (dynamic_cast(e)) - Replace(); - return 0; + 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)) + cv->t = event->after ? M_PI / 2 : 0; + else + event->card->view->actT = event->after ? M_PI / 2 : 0; + return 1; + } + else if (WEventPhaseChange *event = dynamic_cast(e)) + { + if (Constants::MTG_PHASE_COMBATEND == event->to->id) + battleField.colorFlow = -1; + } + else if (dynamic_cast (e)) + Replace(); + return 0; } int GuiPlay::receiveEventMinus(WEvent * e) { - if (WEventZoneChange *event = dynamic_cast(e)) + if (WEventZoneChange *event = dynamic_cast(e)) { - if ((game->players[0]->inPlay() == event->from) || - (game->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; - CardSelectorSingleton::Instance()->Remove(cv); - cards.erase(it); - trash(cv); - Replace(); - return 1; - } - } - return 0; + if ((game->players[0]->inPlay() == event->from) || (game->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; + CardSelectorSingleton::Instance()->Remove(cv); + cards.erase(it); + trash(cv); + Replace(); + return 1; + } + } + return 0; } diff --git a/projects/mtg/src/GuiStatic.cpp b/projects/mtg/src/GuiStatic.cpp index 9cd39aa16..65883cdf7 100644 --- a/projects/mtg/src/GuiStatic.cpp +++ b/projects/mtg/src/GuiStatic.cpp @@ -3,315 +3,352 @@ #include "Trash.h" #include "GuiStatic.h" -GuiStatic::GuiStatic(float desiredHeight, float x, float y, bool hasFocus, GuiAvatars* parent) : PlayGuiObject(desiredHeight, x, y, hasFocus), parent(parent) {} -void GuiStatic::Entering() +GuiStatic::GuiStatic(float desiredHeight, float x, float y, bool hasFocus, GuiAvatars* parent) : + PlayGuiObject(desiredHeight, x, y, hasFocus), parent(parent) { - parent->Activate(this); -} -bool GuiStatic::Leaving(JButton key) -{ - parent->Deactivate(this); - return false; } -GuiAvatar::GuiAvatar(float x, float y, bool hasFocus, Player * player, Corner corner, GuiAvatars* parent) : GuiStatic(static_cast(GuiAvatar::Height), x, y, hasFocus, parent), avatarRed(255), currentLife(player->life),currentpoisonCount(player->poisonCount), corner(corner), player(player) { - type = GUI_AVATAR; +void GuiStatic::Entering() +{ + parent->Activate(this); +} + +bool GuiStatic::Leaving(JButton key) +{ + parent->Deactivate(this); + return false; +} + +GuiAvatar::GuiAvatar(float x, float y, bool hasFocus, Player * player, Corner corner, GuiAvatars* parent) : + GuiStatic(static_cast (GuiAvatar::Height), x, y, hasFocus, parent), avatarRed(255), currentLife(player->life), + currentpoisonCount(player->poisonCount), corner(corner), player(player) +{ + type = GUI_AVATAR; } void GuiAvatar::Render() { - GameObserver * game = GameObserver::GetInstance(); - JRenderer * r = JRenderer::GetInstance(); - int life = player->life; - int poisonCount = player->poisonCount; - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - //Avatar - int lifeDiff = life - currentLife; - if (lifeDiff < 0 && currentLife > 0){ - avatarRed = 192 + (3* 255 * lifeDiff) / currentLife / 4; - if (avatarRed < 0) avatarRed = 0; - } - int poisonDiff = poisonCount - currentpoisonCount; - if (poisonDiff < 0 && currentpoisonCount > 0){ - avatarRed = 192 + (3* 255 * poisonDiff) / currentpoisonCount / 4; - if (avatarRed < 0) avatarRed = 0; - } - currentpoisonCount = poisonCount; - currentLife = life; - - r->FillRect(actX+2, actY+2, Width * actZ, Height *actZ, ARGB((int)(actA / 2), 0, 0, 0)); - - float x0 = actX; - float y0 = actY; - - JQuad * quad = player->mAvatar; - if (quad) + GameObserver * game = GameObserver::GetInstance(); + JRenderer * r = JRenderer::GetInstance(); + int life = player->life; + int poisonCount = player->poisonCount; + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + //Avatar + int lifeDiff = life - currentLife; + if (lifeDiff < 0 && currentLife > 0) { - if (corner == BOTTOM_RIGHT){ - x0 -= quad->mWidth * actZ; - y0 -= quad->mHeight * actZ; - } - switch (corner) - { - case TOP_LEFT : quad->SetHotSpot(0, 0); break; - case BOTTOM_RIGHT : quad->SetHotSpot(35, 50); break; - } - quad->SetColor(ARGB((int)actA, 255, avatarRed, avatarRed)); - r->RenderQuad(quad, actX, actY, actT, actZ, actZ); - if (mHasFocus){ - r->FillRect(x0,x0,quad->mWidth * actZ,quad->mHeight * actZ, ARGB(abs(128 - wave),255,255,255)); - } + avatarRed = 192 + (3 * 255 * lifeDiff) / currentLife / 4; + if (avatarRed < 0) + avatarRed = 0; + } + int poisonDiff = poisonCount - currentpoisonCount; + if (poisonDiff < 0 && currentpoisonCount > 0) + { + avatarRed = 192 + (3 * 255 * poisonDiff) / currentpoisonCount / 4; + if (avatarRed < 0) + avatarRed = 0; + } + currentpoisonCount = poisonCount; + currentLife = life; + + r->FillRect(actX + 2, actY + 2, Width * actZ, Height * actZ, ARGB((int)(actA / 2), 0, 0, 0)); + + float x0 = actX; + float y0 = actY; + + JQuad * quad = player->mAvatar; + if (quad) + { + if (corner == BOTTOM_RIGHT) + { + x0 -= quad->mWidth * actZ; + y0 -= quad->mHeight * actZ; + } + switch (corner) + { + case TOP_LEFT: + quad->SetHotSpot(0, 0); + break; + case BOTTOM_RIGHT: + quad->SetHotSpot(35, 50); + break; + } + quad->SetColor(ARGB((int)actA, 255, avatarRed, avatarRed)); + r->RenderQuad(quad, actX, actY, actT, actZ, actZ); + if (mHasFocus) + { + r->FillRect(x0, x0, quad->mWidth * actZ, quad->mHeight * actZ, ARGB(abs(128 - wave),255,255,255)); + } } - if (avatarRed < 255){ - avatarRed += 3; - if (avatarRed > 255) - avatarRed = 255; - } - - - if (game->currentPlayer == player) - r->DrawRect(x0-1, y0-1, 36 * actZ, 51*actZ, ARGB((int)actA, 0, 255, 0)); - else if (game->currentActionPlayer == player) - r->DrawRect(x0, y0, 34 *actZ, 49 * actZ, ARGB((int)actA, 0, 0, 255)); - if (game->isInterrupting == player) - r->DrawRect(x0, y0, 34 * actZ, 49*actZ, ARGB((int)actA, 255, 0, 0)); - - - - - //Life - char buffer[5]; - sprintf(buffer, "%i",life); - switch (corner) + if (avatarRed < 255) { - case TOP_LEFT : - mFont->SetColor(ARGB((int)actA / 4, 0, 0, 0)); - mFont->DrawString(buffer, actX+2, actY+2); - mFont->SetColor(ARGB((int)actA, 255, 255, 255)); - mFont->DrawString(buffer, actX+1, actY+1); - break; - case BOTTOM_RIGHT : - mFont->SetColor(ARGB((int)actA, 255, 255, 255)); - mFont->DrawString(buffer, actX, actY-10, JGETEXT_RIGHT); - break; - } - //poison - char poison[5]; - if(poisonCount > 0){ - sprintf(poison, "%i",poisonCount); - switch (corner) + avatarRed += 3; + if (avatarRed > 255) + avatarRed = 255; + } + + if (game->currentPlayer == player) + r->DrawRect(x0 - 1, y0 - 1, 36 * actZ, 51 * actZ, ARGB((int)actA, 0, 255, 0)); + else if (game->currentActionPlayer == player) + r->DrawRect(x0, y0, 34 * actZ, 49 * actZ, ARGB((int)actA, 0, 0, 255)); + if (game->isInterrupting == player) + r->DrawRect(x0, y0, 34 * actZ, 49 * actZ, ARGB((int)actA, 255, 0, 0)); + + //Life + char buffer[5]; + sprintf(buffer, "%i", life); + switch (corner) { - case TOP_LEFT : - mFont->SetColor(ARGB((int)actA / 1, 0, 255, 0)); - mFont->DrawString(poison, actX+2, actY+10); - break; - case BOTTOM_RIGHT : - mFont->SetColor(ARGB((int)actA / 1 ,0, 255, 0)); - mFont->DrawString(poison, actX, actY-20, JGETEXT_RIGHT); - break; - } -} + case TOP_LEFT: + mFont->SetColor(ARGB((int)actA / 4, 0, 0, 0)); + mFont->DrawString(buffer, actX + 2, actY + 2); + mFont->SetColor(ARGB((int)actA, 255, 255, 255)); + mFont->DrawString(buffer, actX + 1, actY + 1); + break; + case BOTTOM_RIGHT: + mFont->SetColor(ARGB((int)actA, 255, 255, 255)); + mFont->DrawString(buffer, actX, actY - 10, JGETEXT_RIGHT); + break; + } + //poison + char poison[5]; + if (poisonCount > 0) + { + sprintf(poison, "%i", poisonCount); + switch (corner) + { + case TOP_LEFT: + mFont->SetColor(ARGB((int)actA / 1, 0, 255, 0)); + mFont->DrawString(poison, actX + 2, actY + 10); + break; + case BOTTOM_RIGHT: + mFont->SetColor(ARGB((int)actA / 1 ,0, 255, 0)); + mFont->DrawString(poison, actX, actY - 20, JGETEXT_RIGHT); + break; + } + } PlayGuiObject::Render(); } ostream& GuiAvatar::toString(ostream& out) const { - return out << "GuiAvatar ::: avatarRed : " << avatarRed - << " ; currentLife : " << currentLife - << " ; currentpoisonCount : " << currentpoisonCount - << " ; player : " << player; + return out << "GuiAvatar ::: avatarRed : " << avatarRed << " ; currentLife : " << currentLife << " ; currentpoisonCount : " + << currentpoisonCount << " ; player : " << player; } - -void GuiGameZone::toggleDisplay(){ - if (showCards) - showCards = 0; - else +void GuiGameZone::toggleDisplay() +{ + if (showCards) + showCards = 0; + else { - showCards = 1; - cd->init(zone); + showCards = 1; + cd->init(zone); } } +void GuiGameZone::Render() +{ + //Texture + JQuad * quad = resources.GetQuad("back_thumb"); + float scale = defaultHeight / quad->mHeight; + quad->SetColor(ARGB((int)(actA),255,255,255)); -void GuiGameZone::Render(){ - //Texture - JQuad * quad = resources.GetQuad("back_thumb"); - float scale = defaultHeight / quad->mHeight; - quad->SetColor(ARGB((int)(actA),255,255,255)); + JRenderer::GetInstance()->RenderQuad(quad, actX, actY, 0.0, scale * actZ, scale * actZ); - JRenderer::GetInstance()->RenderQuad(quad, actX, actY, 0.0, scale * actZ, scale * actZ); - - float x0 = actX; - if (x0 < SCREEN_WIDTH/2) { - x0+=7; - } - - if (mHasFocus) - JRenderer::GetInstance()->FillRect(actX,actY,quad->mWidth * scale * actZ,quad->mHeight *scale * actZ, ARGB(abs(128 - wave),255,255,255)); - - //Number of cards - WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - char buffer[11]; - int mAlpha = (int)(actA); - sprintf(buffer,"%i", zone->nb_cards); - mFont->SetColor(ARGB(mAlpha,0,0,0)); - mFont->DrawString(buffer, x0+1, actY+1); - if (actA > 120) mAlpha = 255; - mFont->SetColor(ARGB(mAlpha,255,255,255)); - mFont->DrawString(buffer, x0, actY); - - - - if (showCards) cd->Render(); - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - (*it)->Render(); - PlayGuiObject::Render(); -} - -void GuiGameZone::ButtonPressed(int controllerId, int controlId){ - GameObserver::GetInstance()->ButtonPressed(this); -} - -bool GuiGameZone::CheckUserInput(JButton key){ - if (showCards) return cd->CheckUserInput(key); - return false; -} - -bool GuiGameZone::CheckUserInput(int x, int y){ - if (showCards) return cd->CheckUserInput(x, y); - return false; -} - -void GuiGameZone::Update(float dt){ - if (showCards) cd->Update(dt); - PlayGuiObject::Update(dt); - - for (vector::iterator it = cards.begin(); it != cards.end(); ++it){ - CardView * c = (*it); - c->Update(dt); - - //Dirty fix for http://code.google.com/p/wagic/issues/detail?id=113 - if (fabs(c->actX - c->x) < 0.01 && fabs(c->actY - c->y)< 0.01){ - cards.erase(it); - trash(c); - return; + float x0 = actX; + if (x0 < SCREEN_WIDTH / 2) + { + x0 += 7; } - } + + if (mHasFocus) + JRenderer::GetInstance()->FillRect(actX, actY, quad->mWidth * scale * actZ, quad->mHeight * scale * actZ, + ARGB(abs(128 - wave),255,255,255)); + + //Number of cards + WFont * mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); + char buffer[11]; + int mAlpha = (int) (actA); + sprintf(buffer, "%i", zone->nb_cards); + mFont->SetColor(ARGB(mAlpha,0,0,0)); + mFont->DrawString(buffer, x0 + 1, actY + 1); + if (actA > 120) + mAlpha = 255; + mFont->SetColor(ARGB(mAlpha,255,255,255)); + mFont->DrawString(buffer, x0, actY); + + if (showCards) + cd->Render(); + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + (*it)->Render(); + PlayGuiObject::Render(); } -GuiGameZone::GuiGameZone(float x, float y, bool hasFocus, MTGGameZone* zone, GuiAvatars* parent): GuiStatic(static_cast(GuiGameZone::Height), x, y, hasFocus, parent), zone(zone){ - cd = NEW CardDisplay(0, GameObserver::GetInstance(), static_cast(x), static_cast(y), this); - cd->zone = zone; - showCards = 0; +void GuiGameZone::ButtonPressed(int controllerId, int controlId) +{ + GameObserver::GetInstance()->ButtonPressed(this); } -GuiGameZone::~GuiGameZone(){ - if (cd) delete cd; - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - delete(*it); +bool GuiGameZone::CheckUserInput(JButton key) +{ + if (showCards) + return cd->CheckUserInput(key); + return false; +} + +bool GuiGameZone::CheckUserInput(int x, int y) +{ + if (showCards) + return cd->CheckUserInput(x, y); + return false; +} + +void GuiGameZone::Update(float dt) +{ + if (showCards) + cd->Update(dt); + PlayGuiObject::Update(dt); + + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + { + CardView * c = (*it); + c->Update(dt); + + //Dirty fix for http://code.google.com/p/wagic/issues/detail?id=113 + if (fabs(c->actX - c->x) < 0.01 && fabs(c->actY - c->y) < 0.01) + { + cards.erase(it); + trash(c); + return; + } + } +} + +GuiGameZone::GuiGameZone(float x, float y, bool hasFocus, MTGGameZone* zone, GuiAvatars* parent) : + GuiStatic(static_cast (GuiGameZone::Height), x, y, hasFocus, parent), zone(zone) +{ + cd = NEW CardDisplay(0, GameObserver::GetInstance(), static_cast (x), static_cast (y), this); + cd->zone = zone; + showCards = 0; +} + +GuiGameZone::~GuiGameZone() +{ + if (cd) + delete cd; + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + delete (*it); } ostream& GuiGameZone::toString(ostream& out) const { - return out << "GuiGameZone ::: zone : " << zone - << " ; cd : " << cd - << " ; showCards : " << showCards; + return out << "GuiGameZone ::: zone : " << zone << " ; cd : " << cd << " ; showCards : " << showCards; } -GuiGraveyard::GuiGraveyard(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) : GuiGameZone(x, y, hasFocus, player->game->graveyard, parent), player(player) { - type = GUI_GRAVEYARD; +GuiGraveyard::GuiGraveyard(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) : + GuiGameZone(x, y, hasFocus, player->game->graveyard, parent), player(player) +{ + type = GUI_GRAVEYARD; } int GuiGraveyard::receiveEventPlus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) - if (event->to == zone) - { - CardView* t; - if (event->card->view) - t = NEW CardView(CardView::nullZone, event->card, *(event->card->view)); - else - t = NEW CardView(CardView::nullZone, event->card, x, y); - t->x = x + Width / 2; t->y = y + Height / 2; t->zoom = 0.6f; t->alpha = 0; - cards.push_back(t); - return 1; - } - return 0; + if (WEventZoneChange* event = dynamic_cast(e)) + if (event->to == zone) + { + CardView* t; + if (event->card->view) + t = NEW CardView(CardView::nullZone, event->card, *(event->card->view)); + else + t = NEW CardView(CardView::nullZone, event->card, x, y); + t->x = x + Width / 2; + t->y = y + Height / 2; + t->zoom = 0.6f; + t->alpha = 0; + cards.push_back(t); + return 1; + } + return 0; } int GuiGraveyard::receiveEventMinus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) - if (event->from == zone) - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if (event->card->previous == (*it)->card) - { - CardView* cv = *it; - cards.erase(it); - trash(cv); - return 1; - } - return 0; + if (WEventZoneChange* event = dynamic_cast(e)) + if (event->from == zone) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if (event->card->previous == (*it)->card) + { + CardView* cv = *it; + cards.erase(it); + trash(cv); + return 1; + } + return 0; } ostream& GuiGraveyard::toString(ostream& out) const { - return out << "GuiGraveyard :::"; + return out << "GuiGraveyard :::"; } - //opponenthand begins -GuiOpponentHand::GuiOpponentHand(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) : GuiGameZone(x, y, hasFocus, player->game->hand, parent), player(player) { - type = GUI_OPPONENTHAND; +GuiOpponentHand::GuiOpponentHand(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) : + GuiGameZone(x, y, hasFocus, player->game->hand, parent), player(player) +{ + type = GUI_OPPONENTHAND; } int GuiOpponentHand::receiveEventPlus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) - if (event->to == zone) - { - CardView* t; - if (event->card->view) - t = NEW CardView(CardView::nullZone, event->card, *(event->card->view)); - else - t = NEW CardView(CardView::nullZone, event->card, x, y); - t->x = x + Width / 2; t->y = y + Height / 2; t->zoom = 0.6f; t->alpha = 0; - cards.push_back(t); - return 1; - } - return 0; + if (WEventZoneChange* event = dynamic_cast(e)) + if (event->to == zone) + { + CardView* t; + if (event->card->view) + t = NEW CardView(CardView::nullZone, event->card, *(event->card->view)); + else + t = NEW CardView(CardView::nullZone, event->card, x, y); + t->x = x + Width / 2; + t->y = y + Height / 2; + t->zoom = 0.6f; + t->alpha = 0; + cards.push_back(t); + return 1; + } + return 0; } int GuiOpponentHand::receiveEventMinus(WEvent* e) { - if (WEventZoneChange* event = dynamic_cast(e)) - if (event->from == zone) - for (vector::iterator it = cards.begin(); it != cards.end(); ++it) - if (event->card->previous == (*it)->card) - { - CardView* cv = *it; - cards.erase(it); - trash(cv); - return 1; - } - return 0; + if (WEventZoneChange* event = dynamic_cast(e)) + if (event->from == zone) + for (vector::iterator it = cards.begin(); it != cards.end(); ++it) + if (event->card->previous == (*it)->card) + { + CardView* cv = *it; + cards.erase(it); + trash(cv); + return 1; + } + return 0; } ostream& GuiOpponentHand::toString(ostream& out) const { - return out << "GuiOpponentHand :::"; + return out << "GuiOpponentHand :::"; } -GuiLibrary::GuiLibrary(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) : GuiGameZone(x, y, hasFocus,player->game->library, parent), player(player) { - type = GUI_LIBRARY; +GuiLibrary::GuiLibrary(float x, float y, bool hasFocus, Player * player, GuiAvatars* parent) : + GuiGameZone(x, y, hasFocus, player->game->library, parent), player(player) +{ + type = GUI_LIBRARY; } - ostream& GuiLibrary::toString(ostream& out) const { - return out << "GuiLibrary :::"; + return out << "GuiLibrary :::"; } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 8bc2ee5f1..fc73ce3e7 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -11,84 +11,98 @@ #include "Translate.h" #include "ThisDescriptor.h" - int AbilityFactory::countCards(TargetChooser * tc, Player * player, int option) { - int result = 0; - GameObserver * game = GameObserver::GetInstance(); - for (int i = 0; i < 2 ; i++) - { - if (player && player!= game->players[i]) continue; - MTGGameZone * zones[] = {game->players[i]->game->inPlay,game->players[i]->game->graveyard,game->players[i]->game->hand}; - for (int k = 0; k < 3; k++) + int result = 0; + GameObserver * game = GameObserver::GetInstance(); + for (int i = 0; i < 2; i++) { - for (int j = zones[k]->nb_cards-1; j >=0 ; j--) - { - MTGCardInstance * current = zones[k]->cards[j]; - if (tc->canTarget(current)) + if (player && player != game->players[i]) + continue; + MTGGameZone * zones[] = { game->players[i]->game->inPlay, game->players[i]->game->graveyard, game->players[i]->game->hand }; + for (int k = 0; k < 3; k++) { - switch (option){ - case COUNT_POWER: - result+= current->power; - break; - default: - result++; - break; - } + for (int j = zones[k]->nb_cards - 1; j >= 0; j--) + { + MTGCardInstance * current = zones[k]->cards[j]; + if (tc->canTarget(current)) + { + switch (option) + { + case COUNT_POWER: + result += current->power; + break; + default: + result++; + break; + } + } + } } - } } - } - return result; + return result; } -Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target, Spell * spell) { - int nb = 1; - string name = ""; - size_t start = 0; - size_t end = s.length(); - size_t separator = s.find(",", start); - if (separator == string::npos) separator = s.find(".", start); - if (separator != string::npos){ - size_t separator2 = s.find(",", separator+1); - if (separator2 == string::npos) separator2 = s.find(".", separator+1); - if (separator2 != string::npos) { - name = s.substr(separator2+1,end-separator2-1); - } - string nbstr = s.substr(separator+1,separator2-separator-1); - WParsedInt * wpi; - if (target){ - wpi = NEW WParsedInt(nbstr,spell,target); - }else{ - wpi = NEW WParsedInt(atoi(nbstr.c_str())); +Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target, Spell * spell) +{ + int nb = 1; + string name = ""; + size_t start = 0; + size_t end = s.length(); + size_t separator = s.find(",", start); + if (separator == string::npos) + separator = s.find(".", start); + if (separator != string::npos) + { + size_t separator2 = s.find(",", separator + 1); + if (separator2 == string::npos) + separator2 = s.find(".", separator + 1); + if (separator2 != string::npos) + { + name = s.substr(separator2 + 1, end - separator2 - 1); + } + string nbstr = s.substr(separator + 1, separator2 - separator - 1); + WParsedInt * wpi; + if (target) + { + wpi = NEW WParsedInt(nbstr, spell, target); + } + else + { + wpi = NEW WParsedInt(atoi(nbstr.c_str())); + } + nb = wpi->getValue(); + delete (wpi); + end = separator; } - nb = wpi->getValue(); - delete(wpi); - end = separator; - } - - string spt = s.substr(start,end-start); - int power, toughness; - if ( parsePowerToughness(spt,&power, &toughness)){ - Counter * counter = NEW Counter(target,name.c_str(),power,toughness); - counter->nb = nb; - return counter; - } - return NULL; + + string spt = s.substr(start, end - start); + int power, toughness; + if (parsePowerToughness(spt, &power, &toughness)) + { + Counter * counter = NEW Counter(target, name.c_str(), power, toughness); + counter->nb = nb; + return counter; + } + return NULL; } -int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness){ +int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness) +{ size_t found = s.find("/"); - if (found != string::npos){ - size_t end = s.find(" ", found); - if (end == string::npos) end = s.size(); - size_t start = s.find_last_of(" ",found); - if (start == string::npos) start = -1; + if (found != string::npos) + { + size_t end = s.find(" ", found); + if (end == string::npos) + end = s.size(); + size_t start = s.find_last_of(" ", found); + if (start == string::npos) + start = -1; - *power = atoi(s.substr(start+1,s.size()-found).c_str()); - *toughness = atoi(s.substr(found+1,end-found-1).c_str()); + *power = atoi(s.substr(start + 1, s.size() - found).c_str()); + *toughness = atoi(s.substr(found + 1, end - found - 1).c_str()); - return 1; + return 1; } return 0; } @@ -96,1649 +110,2025 @@ int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness){ // evaluate trigger ability // ie auto=@attacking(mytgt):destroy target(*) // eval only the text between the @ and the first : -TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int id, Spell * spell, MTGCardInstance *card, Targetable * target){ - size_t found = string::npos; +TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int id, Spell * spell, MTGCardInstance *card, + Targetable * target) +{ + size_t found = string::npos; - //Card Changed Zone - found = s.find("movedto("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+8,end - found - 8); - TargetChooserFactory tcf; + //Card Changed Zone + found = s.find("movedto("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 8, end - found - 8); + TargetChooserFactory tcf; - TargetChooser *toTc = NULL; - TargetChooser *toTcCard = NULL; - end = starget.find ("|"); - if (end == string::npos) { - toTcCard = tcf.createTargetChooser("*",card); - found = 0; - }else{ - toTcCard = tcf.createTargetChooser(starget.substr(0, end).append("|*"),card); - found = end + 1; + TargetChooser *toTc = NULL; + TargetChooser *toTcCard = NULL; + end = starget.find("|"); + if (end == string::npos) + { + toTcCard = tcf.createTargetChooser("*", card); + found = 0; + } + else + { + toTcCard = tcf.createTargetChooser(starget.substr(0, end).append("|*"), card); + found = end + 1; + } + toTcCard->setAllZones(); + starget = starget.substr(found, end - found).insert(0, "*|"); + toTc = tcf.createTargetChooser(starget, card); + toTc->targetter = NULL; + + TargetChooser *fromTc = NULL; + TargetChooser * fromTcCard = NULL; + found = s.find("from("); + if (found != string::npos) + { + end = s.find("|", found); + if (end == string::npos) + { + fromTcCard = tcf.createTargetChooser("*", card); + found = found + 5; + } + else + { + fromTcCard = tcf.createTargetChooser(s.substr(found + 5, end - found - 5).append("|*"), card); + found = end + 1; + } + fromTcCard->setAllZones(); + end = s.find(")", found); + starget = s.substr(found, end - found).insert(0, "*|"); + fromTc = tcf.createTargetChooser(starget, card); + fromTc->targetter = NULL; + } + return NEW TrCardAddedToZone(id, card, (TargetZoneChooser *) toTc, toTcCard, (TargetZoneChooser *) fromTc, fromTcCard); } - toTcCard->setAllZones(); - starget = starget.substr(found,end - found).insert(0,"*|"); - toTc = tcf.createTargetChooser(starget,card); - toTc->targetter = NULL; - TargetChooser *fromTc = NULL; - TargetChooser * fromTcCard = NULL; - found = s.find("from("); - if (found != string::npos){ - end = s.find ("|", found); - if (end == string::npos) { - fromTcCard = tcf.createTargetChooser("*",card); - found = found + 5; - }else{ - fromTcCard = tcf.createTargetChooser(s.substr(found + 5, end - found - 5).append("|*"),card); - found = end + 1; - } - fromTcCard->setAllZones(); - end = s.find (")", found); - starget = s.substr(found,end - found).insert(0,"*|"); - fromTc = tcf.createTargetChooser(starget,card); - fromTc->targetter = NULL; + //Card unTapped + found = s.find("untapped("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 9, end - found - 9); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; + + return NEW TrCardTapped(id, card, tc, false); } - return NEW TrCardAddedToZone(id,card,(TargetZoneChooser *)toTc, toTcCard,(TargetZoneChooser *)fromTc,fromTcCard); - } - //Card unTapped - found = s.find("untapped("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+9,end - found - 9); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card Tapped + found = s.find("tapped("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 7, end - found - 7); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - return NEW TrCardTapped(id,card,tc,false); - } + return NEW TrCardTapped(id, card, tc, true); + } - //Card Tapped - found = s.find("tapped("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+7,end - found - 7); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card Tapped for mana + found = s.find("tappedformana("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 14, end - found - 14); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - return NEW TrCardTapped(id,card,tc,true); - } + return NEW TrCardTappedformana(id, card, tc, true); + } - //Card Tapped for mana - found = s.find("tappedformana("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+14,end - found - 14); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card is attacking + found = s.find("attacking("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 10, end - found - 10); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - return NEW TrCardTappedformana(id,card,tc,true); - } + return NEW TrCardAttacked(id, card, tc); + } + //Card is attacking alone + found = s.find("attackedalone("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 14, end - found - 14); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - //Card is attacking - found = s.find("attacking("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+10,end - found - 10); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + return NEW TrCardAttackedAlone(id, card, tc); + } - return NEW TrCardAttacked(id,card,tc); - } - //Card is attacking alone - found = s.find("attackedalone("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+14,end - found - 14); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card card attacked and is not blocked + found = s.find("notblocked("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 11, end - found - 11); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - return NEW TrCardAttackedAlone(id,card,tc); - } + return NEW TrCardAttackedNotBlocked(id, card, tc); + } - //Card card attacked and is not blocked - found = s.find("notblocked("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+11,end - found - 11); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card card attacked and is blocked + found = s.find("blocked("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 8, end - found - 8); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; + found = s.find("from("); - return NEW TrCardAttackedNotBlocked(id,card,tc); - } + TargetChooser *fromTc = NULL; + if (found != string::npos) + { + end = s.find(")", found); + starget = s.substr(found + 5, end - found - 5); + fromTc = tcf.createTargetChooser(starget, card); + fromTc->targetter = NULL; + } - //Card card attacked and is blocked - found = s.find("blocked("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+8,end - found - 8); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; - found = s.find("from("); - - TargetChooser *fromTc = NULL; - if (found != string::npos){ - end = s.find (")", found); - starget = s.substr(found+5,end - found - 5); - fromTc = tcf.createTargetChooser(starget,card); - fromTc->targetter = NULL; - } + return NEW TrCardAttackedBlocked(id, card, tc, fromTc); + } - return NEW TrCardAttackedBlocked(id,card,tc,fromTc); - } + //Card card is a blocker + found = s.find("blocking("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 9, end - found - 9); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; + found = s.find("from("); - //Card card is a blocker - found = s.find("blocking("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+9,end - found - 9); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; - found = s.find("from("); - - TargetChooser *fromTc = NULL; - if (found != string::npos){ - end = s.find (")", found); - starget = s.substr(found+5,end - found - 5); - fromTc = tcf.createTargetChooser(starget,card); - fromTc->targetter = NULL; - } + TargetChooser *fromTc = NULL; + if (found != string::npos) + { + end = s.find(")", found); + starget = s.substr(found + 5, end - found - 5); + fromTc = tcf.createTargetChooser(starget, card); + fromTc->targetter = NULL; + } - return NEW TrCardBlocked(id,card,tc,fromTc); - } + return NEW TrCardBlocked(id, card, tc, fromTc); + } - //Card card is drawn - found = s.find("drawn("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+6,end - found - 6); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card card is drawn + found = s.find("drawn("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 6, end - found - 6); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - return NEW TrcardDrawn(id,card,tc); - } + return NEW TrcardDrawn(id, card, tc); + } - //Card is sacrificed - found = s.find("sacrificed("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+11,end - found - 11); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card is sacrificed + found = s.find("sacrificed("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 11, end - found - 11); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - return NEW TrCardSacrificed(id,card,tc); - } + return NEW TrCardSacrificed(id, card, tc); + } - //Card is sacrificed - found = s.find("discarded("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+10,end - found - 10); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; + //Card is sacrificed + found = s.find("discarded("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 10, end - found - 10); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; - return NEW TrCardDiscarded(id,card,tc); - } + return NEW TrCardDiscarded(id, card, tc); + } + //Card Damaging non combat + found = s.find("noncombatdamaged("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 17, end - found - 17); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; + found = s.find("from("); - //Card Damaging non combat - found = s.find("noncombatdamaged("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+17,end - found - 17); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; - found = s.find("from("); - - TargetChooser *fromTc = NULL; - if (found != string::npos){ - end = s.find (")", found); - starget = s.substr(found+5,end - found - 5); - fromTc = tcf.createTargetChooser(starget,card); - fromTc->targetter = NULL; - } - return NEW TrDamaged(id,card,tc,fromTc, 2); - } + TargetChooser *fromTc = NULL; + if (found != string::npos) + { + end = s.find(")", found); + starget = s.substr(found + 5, end - found - 5); + fromTc = tcf.createTargetChooser(starget, card); + fromTc->targetter = NULL; + } + return NEW TrDamaged(id, card, tc, fromTc, 2); + } - //Card Damaging combat - found = s.find("combatdamaged("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+14,end - found - 14); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; - found = s.find("from("); - - TargetChooser *fromTc = NULL; - if (found != string::npos){ - end = s.find (")", found); - starget = s.substr(found+5,end - found - 5); - fromTc = tcf.createTargetChooser(starget,card); - fromTc->targetter = NULL; - } - return NEW TrDamaged(id,card,tc,fromTc, 1); - } + //Card Damaging combat + found = s.find("combatdamaged("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 14, end - found - 14); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; + found = s.find("from("); + + TargetChooser *fromTc = NULL; + if (found != string::npos) + { + end = s.find(")", found); + starget = s.substr(found + 5, end - found - 5); + fromTc = tcf.createTargetChooser(starget, card); + fromTc->targetter = NULL; + } + return NEW TrDamaged(id, card, tc, fromTc, 1); + } //Card Damaging - found = s.find("damaged("); - if (found != string::npos){ - size_t end = s.find (")"); - string starget = s.substr(found+8,end - found - 8); - TargetChooserFactory tcf; - TargetChooser *tc = tcf.createTargetChooser(starget,card); - tc->targetter = NULL; - found = s.find("from("); - - TargetChooser *fromTc = NULL; - if (found != string::npos){ - end = s.find (")", found); - starget = s.substr(found+5,end - found - 5); - fromTc = tcf.createTargetChooser(starget,card); - fromTc->targetter = NULL; - } - return NEW TrDamaged(id,card,tc,fromTc, 0); - } + found = s.find("damaged("); + if (found != string::npos) + { + size_t end = s.find(")"); + string starget = s.substr(found + 8, end - found - 8); + TargetChooserFactory tcf; + TargetChooser *tc = tcf.createTargetChooser(starget, card); + tc->targetter = NULL; + found = s.find("from("); - int who = 0; - if (s.find("my") != string::npos) who = 1; - if (s.find("opponent") != string::npos) who = -1; - if (s.find("targetcontroller") != string::npos) who = -2; - - //Next Time... - found = s.find("next"); - if (found != string::npos){ - for (int i = 0; i < Constants::NB_MTG_PHASES; i++){ - found = s.find(Constants::MTGPhaseCodeNames[i]); - if (found != string::npos){ - return NEW TriggerNextPhase(id, card,target,i,who); - } + TargetChooser *fromTc = NULL; + if (found != string::npos) + { + end = s.find(")", found); + starget = s.substr(found + 5, end - found - 5); + fromTc = tcf.createTargetChooser(starget, card); + fromTc->targetter = NULL; + } + return NEW TrDamaged(id, card, tc, fromTc, 0); + } + + int who = 0; + if (s.find("my") != string::npos) + who = 1; + if (s.find("opponent") != string::npos) + who = -1; + if (s.find("targetcontroller") != string::npos) + who = -2; + + //Next Time... + found = s.find("next"); + if (found != string::npos) + { + for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + { + found = s.find(Constants::MTGPhaseCodeNames[i]); + if (found != string::npos) + { + return NEW TriggerNextPhase(id, card, target, i, who); + } + } } - } //Each Time... - found = magicText.find("each"); - if (found != string::npos){ - for (int i = 0; i < Constants::NB_MTG_PHASES; i++){ - found = magicText.find(Constants::MTGPhaseCodeNames[i]); - if (found != string::npos){ - return NEW TriggerAtPhase(id, card,target,i,who); - } - } - } - - return NULL; -} - -int AbilityFactory::parseRestriction(string s){ - if (s.find("myturnonly") != string::npos) return ActivatedAbility::PLAYER_TURN_ONLY; - if (s.find("assorcery") != string::npos) return ActivatedAbility::AS_SORCERY; - - string types[] = {"my","opponent", ""}; - int starts[] = {ActivatedAbility::MY_BEFORE_BEGIN,ActivatedAbility::OPPONENT_BEFORE_BEGIN,ActivatedAbility::BEFORE_BEGIN}; - for (int j = 0; j < 3; ++j){ - size_t found = s.find(types[j]); - if (found !=string::npos){ - for (int i = 0; i < Constants::NB_MTG_PHASES; i++){ - string toFind = types[j]; - toFind.append(Constants::MTGPhaseCodeNames[i]).append("only"); - found = s.find(toFind); - if (found != string::npos){ - return starts[j] + i; + found = magicText.find("each"); + if (found != string::npos) + { + for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + { + found = magicText.find(Constants::MTGPhaseCodeNames[i]); + if (found != string::npos) + { + return NEW TriggerAtPhase(id, card, target, i, who); + } } - } } - } - return ActivatedAbility::NO_RESTRICTION; + return NULL; } -MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a){ - GenericTargetAbility * gta = dynamic_cast(a); - if (gta) return getCoreAbility(gta->ability); +int AbilityFactory::parseRestriction(string s) +{ + if (s.find("myturnonly") != string::npos) + return ActivatedAbility::PLAYER_TURN_ONLY; + if (s.find("assorcery") != string::npos) + return ActivatedAbility::AS_SORCERY; - GenericActivatedAbility * gaa = dynamic_cast(a); - if (gaa) return getCoreAbility(gaa->ability); + string types[] = { "my", "opponent", "" }; + int starts[] = { ActivatedAbility::MY_BEFORE_BEGIN, ActivatedAbility::OPPONENT_BEFORE_BEGIN, ActivatedAbility::BEFORE_BEGIN }; + for (int j = 0; j < 3; ++j) + { + size_t found = s.find(types[j]); + if (found != string::npos) + { + for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + { + string toFind = types[j]; + toFind.append(Constants::MTGPhaseCodeNames[i]).append("only"); + found = s.find(toFind); + if (found != string::npos) + { + return starts[j] + i; + } + } + } + } - if (MultiAbility * abi = dynamic_cast(a)) return getCoreAbility(abi->abilities[0]); + return ActivatedAbility::NO_RESTRICTION; +} - return a; +MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a) +{ + GenericTargetAbility * gta = dynamic_cast (a); + if (gta) + return getCoreAbility(gta->ability); + + GenericActivatedAbility * gaa = dynamic_cast (a); + if (gaa) + return getCoreAbility(gaa->ability); + + if (MultiAbility * abi = dynamic_cast(a)) + return getCoreAbility(abi->abilities[0]); + + return a; } //Parses a string and returns the corresponding MTGAbility object //Returns NULL if parsing failed //Beware, Spell CAN be null when the function is called by the AI trying to analyze the effects of a given card -MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTGCardInstance *card, int activated, int forceUEOT, int oneShot,int forceFOREVER, MTGGameZone * dest){ - size_t found; - trim(s); +MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTGCardInstance *card, int activated, int forceUEOT, + int oneShot, int forceFOREVER, MTGGameZone * dest) +{ + size_t found; + trim(s); - //TODO This block redundant with calling function - if (!card && spell) card = spell->source; - if (!card) return NULL; - MTGCardInstance * target = card->target; - if (!target) target = card; + //TODO This block redundant with calling function + if (!card && spell) + card = spell->source; + if (!card) + return NULL; + MTGCardInstance * target = card->target; + if (!target) + target = card; - found = s.find("@"); - if ( found != string::npos ) - { - found = s.find(":", found); + found = s.find("@"); + if (found != string::npos) + { + found = s.find(":", found); + if (found != string::npos) + { + + TriggeredAbility * trigger = NULL; + string triggerText = s.substr(0, found); + trigger = parseTrigger(triggerText, s, id, spell, card, target); + //Dirty way to remove the trigger text (could get in the way) + if (trigger) + { + //found = s.find(":", found); + string s1 = s.substr(found + 1); + MTGAbility * a = parseMagicLine(s1, id, spell, card, activated); + if (!a) + { + delete trigger; + return NULL; + } + return NEW GenericTriggeredAbility(id, card, trigger, a, NULL, target); + } + } + } + int doTap = 0; //Tap in the cost ? + if (s.find("{t}") != string::npos) + doTap = 1; + + int restrictions = parseRestriction(s); + + TargetChooser * tc = NULL; + string sWithoutTc = s; + //Target Abilities + found = s.find("target("); + if (found != string::npos) + { + int end = s.find(")", found); + string starget = s.substr(found + 7, end - found - 7); + TargetChooserFactory tcf; + tc = tcf.createTargetChooser(starget, card); + if (tc && s.find("notatarget(") != string::npos) + { + tc->targetter = NULL; + found = found - 4; + } + string temp = s.substr(0, found); + temp.append(s.substr(end + 1)); + sWithoutTc = temp; + } + + size_t delimiter = sWithoutTc.find("}:"); + size_t firstNonSpace = sWithoutTc.find_first_not_of(" "); + if (delimiter != string::npos && firstNonSpace != string::npos && sWithoutTc[firstNonSpace] == '{') + { + ManaCost * cost = ManaCost::parseManaCost(sWithoutTc.substr(0, delimiter + 1), NULL, card); + if (doTap || cost) + { + string s1 = sWithoutTc.substr(delimiter + 2); + + MTGAbility * a = parseMagicLine(s1, id, spell, card, 1); + if (!a) + { + DebugTrace("ABILITYFACTORY Error parsing: " << sWithoutTc); + return NULL; + } + + //A stupid Special case for ManaProducers because they don't use the stack :( + AManaProducer * amp = dynamic_cast (a); + if (amp) + { + amp->cost = cost; + amp->oneShot = 0; + amp->tap = doTap; + return amp; + } + + int limit = 0; + size_t limit_str = sWithoutTc.find("limit:"); + if (limit_str != string::npos) + { + limit = atoi(sWithoutTc.substr(limit_str + 6).c_str()); + } + + AEquip *ae = dynamic_cast (a); + if (ae) + { + ae->cost = cost; + if (!tc) + { + TargetChooserFactory tcf; + tc = tcf.createTargetChooser("creature|myBattlefield", card); + } + ae->tc = tc; + return ae; + } + + if (tc) + return NEW GenericTargetAbility(id, card, tc, a, cost, doTap, limit, restrictions, dest); + return NEW GenericActivatedAbility(id, card, a, cost, doTap, limit, restrictions, dest); + } + SAFE_DELETE(cost); + } + + // figure out alternative cost effects + string keyword; + int costType = -1; + if (s.find(Constants::kKickerKeyword) == 0) + { + costType = ManaCost::MANA_PAID_WITH_KICKER; + keyword = Constants::kKickerKeyword; + } + if (s.find(Constants::kRetraceKeyword) == 0) + { + costType = ManaCost::MANA_PAID_WITH_RETRACE; + keyword = Constants::kRetraceKeyword; + } + if (s.find(Constants::kAlternativeKeyword) == 0) + { + costType = ManaCost::MANA_PAID_WITH_ALTERNATIVE; + keyword = Constants::kAlternativeKeyword; + } + if (s.find(Constants::kBuyBackKeyword) == 0) + { + costType = ManaCost::MANA_PAID_WITH_BUYBACK; + keyword = Constants::kBuyBackKeyword; + } + if (s.find(Constants::kFlashBackKeyword) == 0) + { + costType = ManaCost::MANA_PAID_WITH_FLASHBACK; + keyword = Constants::kFlashBackKeyword; + } + + if ((costType > -1) && (!keyword.empty())) + { + if (spell && spell->FullfilledAlternateCost(costType)) + { + string s1 = s.substr(keyword.length()); + return parseMagicLine(s1, id, spell, card); + } + DebugTrace("INFO parseMagicLine: Alternative Cost was not fulfilled for " << s); + return NULL; + } + + //When...comes into play, you may... + found = s.find("may "); + if (found == 0) + { + string s1 = sWithoutTc.substr(found + 4); + MTGAbility * a1 = parseMagicLine(s1, id, spell, card); + if (!a1) + return NULL; + + if (tc) + a1 = NEW GenericTargetAbility(id, card, tc, a1); + else + a1 = NEW GenericActivatedAbility(id, card, a1, NULL); + return NEW MayAbility(id, a1, card); + } + //When...comes into play, choose one... + found = s.find("choice "); + if (found == 0) + { + string s1 = sWithoutTc.substr(found + 7); + MTGAbility * a1 = parseMagicLine(s1, id, spell, card); + if (!a1) + return NULL; + + if (tc) + a1 = NEW GenericTargetAbility(id, card, tc, a1); + else + a1 = NEW GenericActivatedAbility(id, card, a1, NULL); + return NEW MayAbility(id, a1, card, true); + } + + //Multiple abilities for ONE cost + found = s.find("&&"); + if (found != string::npos) + { + SAFE_DELETE(tc); + string s1 = s.substr(0, found); + string s2 = s.substr(found + 2); + MultiAbility * multi = NEW MultiAbility(id, card, target, NULL, NULL); + MTGAbility * a1 = parseMagicLine(s1, id, spell, card, activated); + MTGAbility * a2 = parseMagicLine(s2, id, spell, card, activated); + multi->Add(a1); + multi->Add(a2); + multi->oneShot = 1; + return multi; + } + + //rather dirty way to stop thises and lords from conflicting with each other. + string prelords[] = { "foreach(", "lord(", "aslongas(", "teach(", "all(" }; + size_t lord = string::npos; + for (int j = 0; j < 5; ++j) + { + size_t found2 = s.find(prelords[j]); + if (found2 != string::npos && ((found == string::npos) || found2 < found)) + { + lord = found2; + } + } + + //This, ThisForEach; + string thises[] = { "this(", "thisforeach(" }; + found = string::npos; + int i = -1; + for (int j = 0; j < 2; ++j) + { + size_t found2 = s.find(thises[j]); + if (found2 != string::npos && ((found == string::npos) || found2 < found)) + { + found = found2; + i = j; + } + } + if (found != string::npos && found < lord) + { + //why does tc even exist here? This shouldn't happen... + SAFE_DELETE(tc); //http://code.google.com/p/wagic/issues/detail?id=424 + + size_t header = thises[i].size(); + size_t end = s.find(")", found + header); + string s1; + if (found == 0 || end != s.size() - 1) + { + s1 = s.substr(end + 1); + } + else + { + s1 = s.substr(0, found); + } + if (end != string::npos) + { + string thisDescriptorString = s.substr(found + header, end - found - header); + ThisDescriptorFactory tdf; + ThisDescriptor * td = tdf.createThisDescriptor(thisDescriptorString); + + if (!td) + { + DebugTrace("MTGABILITY: Parsing Error:" << s); + return NULL; + } + + MTGAbility * a = parseMagicLine(s1, id, spell, card, 0, activated); + if (!a) + { + SAFE_DELETE(td); + return NULL; + } + MTGAbility * result = NULL; + int oneShot = 0; + found = s.find(" oneshot"); + if (found != string::npos) + oneShot = 1; + if (activated) + oneShot = 1; + if (card->hasType("sorcery") || card->hasType("instant")) + oneShot = 1; + if (a->oneShot) + oneShot = 1; + Damageable * _target = NULL; + if (spell) + _target = spell->getNextDamageableTarget(); + if (!_target) + _target = target; + + switch (i) + { + case 0: + result = NEW AThis(id, card, _target, td, a); + break; + case 1: + result = NEW AThisForEach(id, card, _target, td, a); + break; + default: + result = NULL; + } + if (result) + { + result->oneShot = oneShot; + } + return result; + } + return NULL; + } + + //Lord, foreach, aslongas + string lords[] = { "lord(", "foreach(", "aslongas(", "teach(", "all(" }; + found = string::npos; + i = -1; + for (int j = 0; j < 5; ++j) + { + size_t found2 = s.find(lords[j]); + if (found2 != string::npos && ((found == string::npos) || found2 < found)) + { + found = found2; + i = j; + } + } + if (found != string::npos) + { + SAFE_DELETE(tc); + size_t header = lords[i].size(); + size_t end = s.find(")", found + header); + string s1; + if (found == 0 || end != s.size() - 1) + { + s1 = s.substr(end + 1); + } + else + { + s1 = s.substr(0, found); + } + if (end != string::npos) + { + int lordIncludeSelf = 1; + size_t other = s1.find(" other"); + if (other != string::npos) + { + lordIncludeSelf = 0; + s1.replace(other, 6, ""); + } + string lordTargetsString = s.substr(found + header, end - found - header); + TargetChooserFactory tcf; + TargetChooser * lordTargets = tcf.createTargetChooser(lordTargetsString, card); + + if (!lordTargets) + { + DebugTrace("MTGABILITY: Parsing Error: " << s); + return NULL; + } + + MTGAbility * a = parseMagicLine(s1, id, spell, card, 0, activated); //activated lords usually force an end of turn ability + if (!a) + { + SAFE_DELETE(lordTargets); + return NULL; + } + MTGAbility * result = NULL; + int oneShot = 0; + found = s.find(" oneshot"); + if (found != string::npos) + oneShot = 1; + if (activated) + oneShot = 1; + if (card->hasType("sorcery") || card->hasType("instant")) + oneShot = 1; + if (i == 4) + oneShot = 1; + if (a->oneShot) + oneShot = 1; + Damageable * _target = NULL; + if (spell) + _target = spell->getNextDamageableTarget(); + if (!_target) + _target = target; + + int mini = 0; + int maxi = 0; + + found = s.find(" >"); + if (found != string::npos) + mini = atoi(s.substr(found + 2, 1).c_str()); + + found = s.find(" <"); + if (found != string::npos) + maxi = atoi(s.substr(found + 2, 1).c_str()); + + switch (i) + { + case 0: + result = NEW ALord(id, card, lordTargets, lordIncludeSelf, a); + break; + case 1: + result = NEW AForeach(id, card, _target, lordTargets, lordIncludeSelf, a, mini, maxi); + break; + case 2: + result = NEW AAsLongAs(id, card, _target, lordTargets, lordIncludeSelf, a, mini, maxi); + break; + case 3: + result = NEW ATeach(id, card, lordTargets, lordIncludeSelf, a); + break; + case 4: + result = NEW ALord(id, card, lordTargets, lordIncludeSelf, a); + break; + default: + result = NULL; + } + if (result) + result->oneShot = oneShot; + return result; + } + return NULL; + } + + if (!activated && tc) + { + + MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card); + if (!a) + { + DebugTrace("ABILITYFACTORY Error parsing: " << s); + return NULL; + } + a = NEW GenericTargetAbility(id, card, tc, a); + return NEW MayAbility(id, a, card, true); + } + + SAFE_DELETE(tc); + + //Upkeep Cost + found = s.find("upcost"); + if (found != string::npos) + { + size_t start = s.find("["); + size_t end = s.find("]", start); + string s1 = s.substr(start + 1, end - start - 1); + size_t seperator = s1.find(";"); + int phase = Constants::MTG_PHASE_UPKEEP; + int once = 0; + if (seperator != string::npos) + { + for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + { + if (s1.find("next") != string::npos) + once = 1; + if (s1.find(Constants::MTGPhaseCodeNames[i]) != string::npos) + { + phase = i; + } + } + s1 = s1.substr(0, seperator - 1); + } + ManaCost * cost = ManaCost::parseManaCost(s1); + + if (!cost) + { + DebugTrace("MTGABILITY: Parsing Error: " << s); + return NULL; + } + + string sAbility = s.substr(end + 1); + MTGAbility * a = parseMagicLine(sAbility, id, spell, card); + + if (!a) + { + DebugTrace("MTGABILITY: Parsing Error: " << s); + delete (cost); + return NULL; + } + + return NEW AUpkeep(id, card, a, cost, doTap, restrictions, phase, once); + } + + //Cycling + found = s.find("cycling"); + if (found != string::npos) + { + MTGAbility * a = NEW ACycle(id, card, target); + a->oneShot = 1; + return a; + } + + //ninjutsu + found = s.find("ninjutsu"); + if (found != string::npos) + { + MTGAbility * a = NEW ANinja(id, card, target); + a->oneShot = 1; + return a; + } + + //combat removel + found = s.find("removefromcombat"); + if (found != string::npos) + { + MTGAbility * a = NEW ACombatRemovel(id, card, target); + a->oneShot = 1; + return a; + } + + //Fizzle (counterspell...) + found = s.find("fizzle"); + if (found != string::npos) + { + Spell * starget = NULL; + if (spell) + starget = spell->getNextSpellTarget(); + MTGAbility * a = NEW AAFizzler(id, card, starget); + a->oneShot = 1; + return a; + } + + //Regeneration + found = s.find("regenerate"); + if (found != string::npos) + { + MTGAbility * a = NEW AStandardRegenerate(id, card, target); + a->oneShot = 1; + return a; + } + + //Token creator. Name, type, p/t, abilities + found = s.find("token("); + if (found != string::npos) + { + WParsedInt * multiplier = NULL; + size_t star = s.find("*"); + if (star != string::npos) + multiplier = NEW WParsedInt(s.substr(star + 1), spell, card); + size_t end = s.find(")", found); + int tokenId = atoi(s.substr(found + 6, end - found - 6).c_str()); + int who; + size_t opponent = s.find("opponent"); + if (opponent != string::npos) + { + who = 1; + } + else + { + who = 0; + } + if (tokenId) + { + MTGCard * safetycard = GameApp::collection->getCardById(tokenId); + if (safetycard) + {//contenue + ATokenCreator * tok = NEW ATokenCreator(id, card, NULL, tokenId, 0, multiplier, who); + tok->oneShot = 1; + return tok; + } + else + { + tokenId = 0; + ATokenCreator * tok = NEW ATokenCreator(id, card, NULL, "ID NOT FOUND", "ERROR ID", NULL, NULL, "", 0, NULL); + return tok; + } + } + + end = s.find(",", found); + string sname = s.substr(found + 6, end - found - 6); + size_t previous = end + 1; + end = s.find(",", previous); + string stypes = s.substr(previous, end - previous); + previous = end + 1; + end = s.find(",", previous); + string spt = s.substr(previous, end - previous); + int value = 0; + int power, toughness; + if (!spt.find("X/X") || !spt.find("x/x")) + { + value = spell->computeX(card); + } + if (!spt.find("XX/XX") || !spt.find("xx/xx")) + { + value = spell->computeXX(card); + } + parsePowerToughness(spt, &power, &toughness); + string sabilities = s.substr(end + 1); + if (s.find("opponent")) + { + if (opponent != string::npos) + { + who = 1; + } + else + { + who = 0; + } + } + ATokenCreator * tok = NEW ATokenCreator(id, card, NULL, sname, stypes, power + value, toughness + value, sabilities, 0, + multiplier, who); + tok->oneShot = 1; + return tok; + } + + //name an ability line + found = s.find("name("); + if (found != string::npos) + { + size_t end = s.find(")", found); + string sname = s.substr(found + 5, end - found - 5); + size_t previous = end + 1; + ANamer * tok = NEW ANamer(id, card, NULL, sname, 0); + return tok; + } + + //Equipment + found = s.find("equip"); + if (found != string::npos) + { + MTGAbility * a = NEW AEquip(id, card); + return a; + } + + //Equipment (attach) + found = s.find("attach"); + if (found != string::npos) + { + MTGAbility * a = NEW AEquip(id, card, 0, 0, ActivatedAbility::NO_RESTRICTION); + return a; + } + + //MoveTo Move a card from a zone to another + found = s.find("moveto("); + if (found != string::npos) + { + int end = s.find(")", found + 1); + string szone = s.substr(found + 7, end - found - 7); + + //hack for http://code.google.com/p/wagic/issues/detail?id=120 + //We assume that auras don't move their own target... + if (card->hasType("aura")) + target = card; + + MTGAbility * a = NEW AAMover(id, card, target, szone); + a->oneShot = 1; + return a; + + } + + //Copy a target + found = s.find("copy"); + if (found != string::npos) + { + MTGAbility * a = NEW AACopier(id, card, target); + a->oneShot = 1; + return a; + } + + //clone + found = s.find("clone"); + if (found != string::npos) + { + int who; + who = 0; + found = s.find("opponent"); + if (found != string::npos) + { + who = 1; + } + string with; + found = s.find("with("); + if (found != string::npos) + { + size_t end = s.find(")", found); + with = s.substr(found + 5, end - found - 5); + } + MTGAbility * a = NEW AACloner(id, card, target, 0, who, with); + a->oneShot = 1; + return a; + } + + //Bury, destroy, sacrifice, reject(discard) + if (s.find("bury") != string::npos) + { + MTGAbility *a = NEW AABuryCard(id, card, target, NULL, AABanishCard::BURY); + a->oneShot = 1; + return a; + } + else if (s.find("destroy") != string::npos) + { + MTGAbility * a = NEW AADestroyCard(id, card, target, NULL, AABanishCard::DESTROY); + a->oneShot = 1; + return a; + } + else if (s.find("sacrifice") != string::npos) + { + MTGAbility *a = NEW AASacrificeCard(id, card, target, NULL, AABanishCard::SACRIFICE); + a->oneShot = 1; + return a; + } + else if (s.find("reject") != string::npos) + { + MTGAbility *a = NEW AADiscardCard(id, card, target, NULL, AABanishCard::DISCARD); + a->oneShot = 1; + return a; + } + + int who = TargetChooser::UNSET; + if (s.find(" controller") != string::npos) + who = TargetChooser::CONTROLLER; + if (s.find(" opponent") != string::npos) + who = TargetChooser::OPPONENT; + if (s.find(" targetcontroller") != string::npos) + who = TargetChooser::TARGET_CONTROLLER; + if (s.find(" owner") != string::npos) + who = TargetChooser::OWNER; + + found = s.find("ueot"); + if (found != string::npos) + forceUEOT = 1; + found = s.find("oneshot"); + if (found != string::npos) + oneShot = 1; + found = s.find("forever"); + if (found != string::npos) + forceFOREVER = 1; + + //PreventCombat Damage + found = s.find("preventallcombatdamage"); if (found != string::npos) { - TriggeredAbility * trigger = NULL; - string triggerText = s.substr(0, found ); - trigger = parseTrigger(triggerText, s,id,spell,card,target); - //Dirty way to remove the trigger text (could get in the way) - if (trigger) - { - //found = s.find(":", found); - string s1 = s.substr(found+1); - MTGAbility * a = parseMagicLine(s1, id, spell, card,activated); - if (!a){ - delete trigger; - return NULL; + string to = ""; + string from = ""; + + found = s.find("to("); + if (found != string::npos) + { + size_t end = s.find(")", found); + to = s.substr(found + 3, end - found - 3); } - return NEW GenericTriggeredAbility(id,card,trigger,a,NULL,target); - } - } - } - int doTap = 0; //Tap in the cost ? - if (s.find("{t}") != string::npos) doTap = 1; - int restrictions = parseRestriction(s); - - TargetChooser * tc = NULL; - string sWithoutTc = s; - //Target Abilities - found = s.find("target("); - if (found != string::npos){ - int end = s.find(")", found); - string starget = s.substr(found + 7,end - found - 7); - TargetChooserFactory tcf; - tc = tcf.createTargetChooser(starget, card); - if (tc && s.find("notatarget(") != string::npos){ - tc->targetter = NULL; - found = found - 4; - } - string temp = s.substr(0,found); - temp.append(s.substr(end+1)); - sWithoutTc = temp; - } - - size_t delimiter = sWithoutTc.find("}:"); - size_t firstNonSpace = sWithoutTc.find_first_not_of(" "); - if (delimiter!= string::npos && firstNonSpace !=string::npos && sWithoutTc[firstNonSpace] == '{'){ - ManaCost * cost = ManaCost::parseManaCost(sWithoutTc.substr(0,delimiter+1),NULL,card); - if (doTap || cost){ - string s1 = sWithoutTc.substr(delimiter+2); - - MTGAbility * a = parseMagicLine(s1, id, spell, card, 1); - if (!a){ - DebugTrace("ABILITYFACTORY Error parsing: " << sWithoutTc); - return NULL; - } - - //A stupid Special case for ManaProducers because they don't use the stack :( - AManaProducer * amp = dynamic_cast(a); - if (amp){ - amp->cost = cost; - amp->oneShot = 0; - amp->tap = doTap; - return amp; - } - - int limit = 0; - size_t limit_str = sWithoutTc.find("limit:"); - if (limit_str != string::npos){ - limit = atoi(sWithoutTc.substr(limit_str+6).c_str()); - } - - AEquip *ae = dynamic_cast(a); - if (ae){ - ae->cost = cost; - if (!tc) { - TargetChooserFactory tcf; - tc = tcf.createTargetChooser("creature|myBattlefield", card); + found = s.find("from("); + if (found != string::npos) + { + size_t end = s.find(")", found); + from = s.substr(found + 5, end - found - 5); } - ae->tc = tc; - return ae; - } - if (tc) return NEW GenericTargetAbility(id, card, tc, a,cost, doTap,limit,restrictions,dest); - return NEW GenericActivatedAbility(id, card, a,cost,doTap,limit,restrictions,dest); + MTGAbility * ab; + if (forceUEOT) + { + ab = NEW APreventDamageTypesUEOT(id, card, to, from); + } + else + { + ab = NEW APreventDamageTypes(id, card, to, from); + } + return ab; } - SAFE_DELETE(cost); - } - - // figure out alternative cost effects - string keyword; - int costType = -1; - if (s.find( Constants::kKickerKeyword ) == 0 ) - { - costType = ManaCost::MANA_PAID_WITH_KICKER; - keyword = Constants::kKickerKeyword; - } - if (s.find( Constants::kRetraceKeyword ) == 0 ) - { - costType = ManaCost::MANA_PAID_WITH_RETRACE; - keyword = Constants::kRetraceKeyword; - } - if (s.find( Constants::kAlternativeKeyword ) == 0 ) - { - costType = ManaCost::MANA_PAID_WITH_ALTERNATIVE; - keyword = Constants::kAlternativeKeyword ; - } - if (s.find( Constants::kBuyBackKeyword ) == 0 ) - { - costType = ManaCost::MANA_PAID_WITH_BUYBACK; - keyword = Constants::kBuyBackKeyword; - } - if (s.find( Constants::kFlashBackKeyword ) == 0 ) - { - costType = ManaCost::MANA_PAID_WITH_FLASHBACK; - keyword = Constants::kFlashBackKeyword; - } - - if ( (costType > -1) && (!keyword.empty()) ) - { - if ( spell && spell->FullfilledAlternateCost( costType )) + //Prevent all non combat damage Damage + found = s.find("preventallnoncombatdamage"); + if (found != string::npos) { - string s1 = s.substr(keyword.length()); - return parseMagicLine(s1, id, spell, card); - } - DebugTrace("INFO parseMagicLine: Alternative Cost was not fulfilled for " << s); - return NULL; - } - - - //When...comes into play, you may... - found = s.find("may "); - if (found == 0){ - string s1 = sWithoutTc.substr(found+4); - MTGAbility * a1 = parseMagicLine(s1,id,spell, card); - if (!a1) return NULL; - - if (tc) a1 = NEW GenericTargetAbility(id, card, tc, a1); - else a1 = NEW GenericActivatedAbility(id, card, a1,NULL); - return NEW MayAbility(id,a1,card); - } - //When...comes into play, choose one... - found = s.find("choice "); - if (found == 0){ - string s1 = sWithoutTc.substr(found+7); - MTGAbility * a1 = parseMagicLine(s1,id,spell, card); - if (!a1) return NULL; - - if (tc) a1 = NEW GenericTargetAbility(id, card, tc, a1); - else a1 = NEW GenericActivatedAbility(id, card, a1,NULL); - return NEW MayAbility(id,a1,card,true); - } - - //Multiple abilities for ONE cost - found = s.find("&&"); - if (found != string::npos){ - SAFE_DELETE(tc); - string s1 = s.substr(0,found); - string s2 = s.substr(found+2); - MultiAbility * multi = NEW MultiAbility(id, card,target,NULL,NULL); - MTGAbility * a1 = parseMagicLine(s1,id,spell, card,activated); - MTGAbility * a2 = parseMagicLine(s2,id,spell, card,activated); - multi->Add(a1); - multi->Add(a2); - multi->oneShot=1; - return multi; - } - - - //rather dirty way to stop thises and lords from conflicting with each other. - string prelords[] = {"foreach(","lord(","aslongas(","teach(", "all("}; - size_t lord = string::npos; - for (int j = 0; j < 5; ++j){ - size_t found2 = s.find(prelords[j]); - if (found2!=string::npos && ((found == string::npos) || found2 < found)){ - lord = found2; - } - } - - //This, ThisForEach; - string thises[] = {"this(","thisforeach("}; - found = string::npos; - int i = -1; - for (int j = 0; j < 2; ++j){ - size_t found2 = s.find(thises[j]); - if (found2!=string::npos && ((found == string::npos) || found2 < found)){ - found = found2; - i = j; - } - } - if (found != string::npos && found < lord) { - //why does tc even exist here? This shouldn't happen... - SAFE_DELETE(tc); //http://code.google.com/p/wagic/issues/detail?id=424 - - size_t header = thises[i].size(); - size_t end = s.find(")", found+header); - string s1; - if (found == 0 || end != s.size()-1){ - s1 = s.substr(end+1); - }else{ - s1 = s.substr(0, found); - } - if (end != string::npos){ - string thisDescriptorString = s.substr(found+header,end-found-header); - ThisDescriptorFactory tdf; - ThisDescriptor * td = tdf.createThisDescriptor(thisDescriptorString); - - if (!td){ - DebugTrace("MTGABILITY: Parsing Error:" << s); - return NULL; - } - - MTGAbility * a = parseMagicLine(s1,id,spell, card,0,activated); - if (!a){ - SAFE_DELETE(td); - return NULL; - } - MTGAbility * result = NULL; - int oneShot = 0; - found = s.find(" oneshot"); - if (found !=string::npos) oneShot = 1; - if (activated) oneShot = 1; - if (card->hasType("sorcery") || card->hasType("instant")) oneShot = 1; - if (a->oneShot) oneShot = 1; - Damageable * _target = NULL; - if (spell) _target = spell->getNextDamageableTarget(); - if (!_target) _target = target; - - switch(i){ - case 0: result = NEW AThis(id, card, _target, td, a); break; - case 1: result = NEW AThisForEach(id, card, _target, td, a); break; - default: result = NULL; - } - if (result){ result->oneShot = oneShot;} - return result; - } - return NULL; - } - - - //Lord, foreach, aslongas - string lords[] = {"lord(","foreach(","aslongas(","teach(", "all("}; - found = string::npos; - i = -1; - for (int j = 0; j < 5; ++j){ - size_t found2 = s.find(lords[j]); - if (found2!=string::npos && ((found == string::npos) || found2 < found)){ - found = found2; - i = j; - } - } - if (found != string::npos){ - SAFE_DELETE(tc); - size_t header = lords[i].size(); - size_t end = s.find(")", found+header); - string s1; - if (found == 0 || end != s.size()-1){ - s1 = s.substr(end+1); - }else{ - s1 = s.substr(0, found); - } - if (end != string::npos){ - int lordIncludeSelf = 1; - size_t other = s1.find(" other"); - if ( other != string::npos){ - lordIncludeSelf = 0; - s1.replace(other, 6,""); - } - string lordTargetsString = s.substr(found+header,end-found-header); - TargetChooserFactory tcf; - TargetChooser * lordTargets = tcf.createTargetChooser(lordTargetsString, card); - - if (!lordTargets){ - DebugTrace("MTGABILITY: Parsing Error: " << s); - return NULL; - } - - MTGAbility * a = parseMagicLine(s1,id,spell, card,0,activated); //activated lords usually force an end of turn ability - if (!a){ - SAFE_DELETE(lordTargets); - return NULL; - } - MTGAbility * result = NULL; - int oneShot = 0; - found = s.find(" oneshot"); - if (found !=string::npos) oneShot = 1; - if (activated) oneShot = 1; - if (card->hasType("sorcery") || card->hasType("instant")) oneShot = 1; - if (i == 4) oneShot = 1; - if (a->oneShot) oneShot = 1; - Damageable * _target = NULL; - if (spell) _target = spell->getNextDamageableTarget(); - if (!_target) _target = target; - - int mini = 0; - int maxi = 0; - - found = s.find(" >"); - if (found !=string::npos) mini = atoi(s.substr(found+2,1).c_str()); - - found = s.find(" <"); - if (found !=string::npos) maxi = atoi(s.substr(found+2,1).c_str()); - - switch(i){ - case 0: result = NEW ALord(id, card, lordTargets, lordIncludeSelf, a); break; - case 1: result = NEW AForeach(id, card, _target,lordTargets, lordIncludeSelf, a,mini,maxi); break; - case 2: result = NEW AAsLongAs(id, card, _target,lordTargets, lordIncludeSelf, a,mini,maxi); break; - case 3: result = NEW ATeach(id, card, lordTargets,lordIncludeSelf, a); break; - case 4: result = NEW ALord(id, card, lordTargets, lordIncludeSelf, a); break; - default: result = NULL; - } - if (result) result->oneShot = oneShot; - return result; - } - return NULL; - } - - if (!activated && tc){ - - MTGAbility * a = parseMagicLine(sWithoutTc, id, spell, card); - if (!a){ - DebugTrace("ABILITYFACTORY Error parsing: " << s); - return NULL; - } - a = NEW GenericTargetAbility(id,card,tc,a); - return NEW MayAbility(id,a,card,true); - } - - SAFE_DELETE(tc); - - //Upkeep Cost - found = s.find("upcost"); - if (found != string::npos){ - size_t start = s.find("["); - size_t end = s.find("]",start); - string s1 = s.substr(start + 1,end - start - 1); - size_t seperator = s1.find(";"); - int phase = Constants::MTG_PHASE_UPKEEP; - int once = 0; - if (seperator != string::npos){ - for (int i = 0; i < Constants::NB_MTG_PHASES; i++){ - if (s1.find("next") != string::npos) once = 1; - if(s1.find(Constants::MTGPhaseCodeNames[i]) != string::npos){ - phase = i; + string to = ""; + string from = ""; + found = s.find("to("); + if (found != string::npos) + { + size_t end = s.find(")", found); + to = s.substr(found + 3, end - found - 3); } - } - s1 = s1.substr(0,seperator - 1); + found = s.find("from("); + if (found != string::npos) + { + size_t end = s.find(")", found); + from = s.substr(found + 5, end - found - 5); + } + MTGAbility * ab; + if (forceUEOT) + { + ab = NEW APreventDamageTypesUEOT(id, card, to, from, 2); + } + else + { + ab = NEW APreventDamageTypes(id, card, to, from, 2); + } + return ab; } - ManaCost * cost = ManaCost::parseManaCost(s1); - - if (!cost){ - DebugTrace("MTGABILITY: Parsing Error: " << s); - return NULL; - } - - string sAbility = s.substr(end + 1); - MTGAbility * a = parseMagicLine(sAbility,id,spell,card); - - if (!a){ - DebugTrace("MTGABILITY: Parsing Error: " << s); - delete(cost); - return NULL; + //Prevent all damage + found = s.find("preventalldamage"); + if (found != string::npos) + { + string to = ""; + string from = ""; + found = s.find("to("); + if (found != string::npos) + { + size_t end = s.find(")", found); + to = s.substr(found + 3, end - found - 3); + } + found = s.find("from("); + if (found != string::npos) + { + size_t end = s.find(")", found); + from = s.substr(found + 5, end - found - 5); + } + MTGAbility * ab; + if (forceUEOT) + { + ab = NEW APreventDamageTypesUEOT(id, card, to, from, 1); + } + else + { + ab = NEW APreventDamageTypes(id, card, to, from, 1); + } + return ab; } - return NEW AUpkeep(id,card,a,cost,doTap,restrictions,phase,once); - } - - //Cycling - found = s.find("cycling"); - if (found != string::npos){ - MTGAbility * a = NEW ACycle(id,card,target); - a->oneShot = 1; - return a; - } - - //ninjutsu - found = s.find("ninjutsu"); - if (found != string::npos){ - MTGAbility * a = NEW ANinja(id,card,target); - a->oneShot = 1; - return a; - } - - //combat removel - found = s.find("removefromcombat"); - if (found != string::npos){ - MTGAbility * a = NEW ACombatRemovel(id,card,target); - a->oneShot = 1; - return a; - } - - //Fizzle (counterspell...) - found = s.find("fizzle"); - if (found != string::npos){ - Spell * starget = NULL; - if (spell) starget = spell->getNextSpellTarget(); - MTGAbility * a = NEW AAFizzler(id,card,starget); - a->oneShot = 1; - return a; - } - - //Regeneration - found = s.find("regenerate"); - if (found != string::npos){ - MTGAbility * a = NEW AStandardRegenerate(id,card,target); - a->oneShot = 1; - return a; - } - - - //Token creator. Name, type, p/t, abilities - found = s.find("token("); - if (found != string::npos){ - WParsedInt * multiplier = NULL; - size_t star = s.find("*"); - if (star != string::npos) multiplier = NEW WParsedInt(s.substr(star+1),spell,card); - size_t end = s.find(")", found); - int tokenId = atoi(s.substr(found + 6,end - found - 6).c_str()); - int who; - size_t opponent = s.find("opponent"); - if (opponent != string::npos){ - who = 1; - }else{ - who = 0; - } - if (tokenId){ - MTGCard * safetycard = GameApp::collection->getCardById(tokenId); - if (safetycard){//contenue - ATokenCreator * tok = NEW ATokenCreator(id,card,NULL,tokenId,0, multiplier,who); - tok->oneShot = 1; - return tok; - }else{ - tokenId = 0; - ATokenCreator * tok = NEW ATokenCreator(id,card,NULL,"ID NOT FOUND","ERROR ID",NULL,NULL,"",0,NULL); - return tok; - } - } - - end = s.find(",", found); - string sname = s.substr(found + 6,end - found - 6); - size_t previous = end+1; - end = s.find(",",previous); - string stypes = s.substr(previous,end - previous); - previous = end+1; - end = s.find(",",previous); - string spt = s.substr(previous,end - previous); - int value = 0; - int power, toughness; - if(!spt.find("X/X") || !spt.find("x/x")){value = spell->computeX(card);} - if(!spt.find("XX/XX") || !spt.find("xx/xx")){value = spell->computeXX(card);} - parsePowerToughness(spt,&power, &toughness); - string sabilities = s.substr(end+1); - if(s.find("opponent")){ - if (opponent != string::npos){ - who = 1; - }else{ - who = 0; - } - } - ATokenCreator * tok = NEW ATokenCreator(id,card,NULL,sname,stypes,power + value,toughness + value,sabilities,0, multiplier,who); - tok->oneShot = 1; - return tok; - } - - //name an ability line - found = s.find("name("); - if (found != string::npos){ - size_t end = s.find(")", found); - string sname = s.substr(found + 5,end - found - 5); - size_t previous = end+1; - ANamer * tok = NEW ANamer(id,card,NULL,sname,0); - return tok; - } - - - //Equipment - found = s.find("equip"); - if (found != string::npos){ - MTGAbility * a = NEW AEquip(id,card); - return a; - } - - //Equipment (attach) - found = s.find("attach"); - if (found != string::npos){ - MTGAbility * a = NEW AEquip(id,card,0,0,ActivatedAbility::NO_RESTRICTION); - return a; - } - - - //MoveTo Move a card from a zone to another - found = s.find("moveto("); - if (found != string::npos){ - int end = s.find(")",found+1); - string szone = s.substr(found + 7,end - found - 7); - - //hack for http://code.google.com/p/wagic/issues/detail?id=120 - //We assume that auras don't move their own target... - if (card->hasType("aura")) target = card; - - MTGAbility * a = NEW AAMover(id,card,target,szone); - a->oneShot = 1; - return a; - - } - - //Copy a target - found = s.find("copy"); - if (found != string::npos){ - MTGAbility * a = NEW AACopier(id,card,target); - a->oneShot = 1; - return a; - } - - //clone - found = s.find("clone"); - if (found != string::npos){ - int who; - who = 0; - found = s.find("opponent"); - if (found != string::npos){ - who = 1; - } - string with; - found = s.find("with("); - if (found != string::npos){ - size_t end = s.find (")", found); - with = s.substr(found+5,end - found - 5); - } - MTGAbility * a = NEW AACloner(id,card,target,0,who,with); - a->oneShot = 1; - return a; - } - - //Bury, destroy, sacrifice, reject(discard) - if ( s.find("bury") != string::npos ) - { - MTGAbility *a = NEW AABuryCard(id, card, target, NULL, AABanishCard::BURY); - a->oneShot = 1; - return a; - } - else if ( s.find("destroy") != string::npos ) - { - MTGAbility * a = NEW AADestroyCard(id, card, target, NULL, AABanishCard::DESTROY); - a->oneShot = 1; - return a; - } - else if ( s.find("sacrifice") != string::npos ) - { - MTGAbility *a = NEW AASacrificeCard(id, card, target, NULL, AABanishCard::SACRIFICE); - a->oneShot = 1; - return a; - } - else if ( s.find("reject") != string::npos ) - { - MTGAbility *a = NEW AADiscardCard(id, card, target, NULL, AABanishCard::DISCARD); - a->oneShot = 1; - return a; - } - - int who = TargetChooser::UNSET; - if (s.find(" controller") != string::npos) who=TargetChooser::CONTROLLER; - if (s.find(" opponent") != string::npos) who=TargetChooser::OPPONENT; - if (s.find(" targetcontroller") != string::npos) who=TargetChooser::TARGET_CONTROLLER; - if (s.find(" owner") != string::npos) who=TargetChooser::OWNER; - - found = s.find("ueot"); - if (found!= string::npos) forceUEOT = 1; - found = s.find("oneshot"); - if (found!= string::npos) oneShot = 1; - found = s.find("forever"); - if (found!= string::npos) forceFOREVER = 1; - - //PreventCombat Damage - found = s.find("preventallcombatdamage"); - if (found != string::npos){ - - - string to = ""; - string from = ""; - - found = s.find("to("); - if (found != string::npos){ - size_t end = s.find (")", found); - to = s.substr(found+3,end - found - 3); + //PreventCombat Damage + found = s.find("fog"); + if (found != string::npos) + { + string to = ""; + string from = ""; + found = s.find("to("); + if (found != string::npos) + { + size_t end = s.find(")", found); + to = s.substr(found + 3, end - found - 3); + } + found = s.find("from("); + if (found != string::npos) + { + size_t end = s.find(")", found); + from = s.substr(found + 5, end - found - 5); + } + MTGAbility * a = NEW APreventDamageTypesUEOT(id, card, to, from); + a->oneShot = 1; + return a; } - found = s.find("from("); - if (found != string::npos){ - size_t end = s.find (")", found); - from = s.substr(found+5,end - found - 5); - } - - MTGAbility * ab; - if (forceUEOT){ - ab = NEW APreventDamageTypesUEOT(id,card,to,from); - }else{ - ab = NEW APreventDamageTypes(id,card,to,from); - } - return ab; - } - //Prevent all non combat damage Damage - found = s.find("preventallnoncombatdamage"); - if (found != string::npos){ - string to = ""; - string from = ""; - found = s.find("to("); - if (found != string::npos){ - size_t end = s.find (")", found); - to = s.substr(found+3,end - found - 3); - } - found = s.find("from("); - if (found != string::npos){ - size_t end = s.find (")", found); - from = s.substr(found+5,end - found - 5); - } - MTGAbility * ab; - if (forceUEOT){ - ab = NEW APreventDamageTypesUEOT(id,card,to,from,2); - }else{ - ab = NEW APreventDamageTypes(id,card,to,from,2); - } - return ab; - } - //Prevent all damage - found = s.find("preventalldamage"); - if (found != string::npos){ - string to = ""; - string from = ""; - found = s.find("to("); - if (found != string::npos){ - size_t end = s.find (")", found); - to = s.substr(found+3,end - found - 3); - } - found = s.find("from("); - if (found != string::npos){ - size_t end = s.find (")", found); - from = s.substr(found+5,end - found - 5); - } - MTGAbility * ab; - if (forceUEOT){ - ab = NEW APreventDamageTypesUEOT(id,card,to,from,1); - }else{ - ab = NEW APreventDamageTypes(id,card,to,from,1); - } - return ab; - } - - //PreventCombat Damage - found = s.find("fog"); - if (found != string::npos){ - string to = ""; - string from = ""; - found = s.find("to("); - if (found != string::npos){ - size_t end = s.find (")", found); - to = s.substr(found+3,end - found - 3); - } - found = s.find("from("); - if (found != string::npos){ - size_t end = s.find (")", found); - from = s.substr(found+5,end - found - 5); - } - MTGAbility * a = NEW APreventDamageTypesUEOT(id,card,to,from); - a->oneShot = 1; - return a; - } - - //Damage - found = s.find("damage"); - if (found != string::npos){ - size_t start = s.find(":",found); - if (start == string::npos) start = s.find(" ",found); - size_t end = s.find(" ",start); - string d; - if (end != string::npos){ - d = s.substr(start+1,end-start-1); - }else{ - d = s.substr(start+1); - } - WParsedInt * damage = NEW WParsedInt(d,spell,card); - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AADamager(id,card,t, damage, NULL, 0, who); - a->oneShot = 1; - return a; - } - - //remove poison - found = s.find("alterpoison:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - int poison; - if (end != string::npos){ - poison = atoi(s.substr(start+1,end-start-1).c_str()); - }else{ - poison = atoi(s.substr(start+1).c_str()); + //Damage + found = s.find("damage"); + if (found != string::npos) + { + size_t start = s.find(":", found); + if (start == string::npos) + start = s.find(" ", found); + size_t end = s.find(" ", start); + string d; + if (end != string::npos) + { + d = s.substr(start + 1, end - start - 1); + } + else + { + d = s.substr(start + 1); + } + WParsedInt * damage = NEW WParsedInt(d, spell, card); + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AADamager(id, card, t, damage, NULL, 0, who); + a->oneShot = 1; + return a; } - Targetable * t = NULL; - if (spell) t = spell->getNextPlayerTarget(); - MTGAbility * a = NEW AAAlterPoison (id, card, t,poison,NULL,0,who); - a->oneShot = 1; - return a; - } - //prevent next damage - found = s.find("prevent:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - int preventing; - if (end != string::npos){ - preventing = atoi(s.substr(start+1,end-start-1).c_str()); - }else{ - preventing = atoi(s.substr(start+1).c_str()); - } + //remove poison + found = s.find("alterpoison:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + int poison; + if (end != string::npos) + { + poison = atoi(s.substr(start + 1, end - start - 1).c_str()); + } + else + { + poison = atoi(s.substr(start + 1).c_str()); + } - Targetable * t = NULL; - if (spell) t = spell->getNextDamageableTarget(); - MTGAbility * a = NEW AADamagePrevent (id, card, t,preventing,NULL,0,who); - a->oneShot = 1; - return a; - } -//set life total + Targetable * t = NULL; + if (spell) + t = spell->getNextPlayerTarget(); + MTGAbility * a = NEW AAAlterPoison(id, card, t, poison, NULL, 0, who); + a->oneShot = 1; + return a; + } + //prevent next damage + found = s.find("prevent:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + int preventing; + if (end != string::npos) + { + preventing = atoi(s.substr(start + 1, end - start - 1).c_str()); + } + else + { + preventing = atoi(s.substr(start + 1).c_str()); + } + + Targetable * t = NULL; + if (spell) + t = spell->getNextDamageableTarget(); + MTGAbility * a = NEW AADamagePrevent(id, card, t, preventing, NULL, 0, who); + a->oneShot = 1; + return a; + } + //set life total found = s.find("lifeset"); - if (found != string::npos){ - size_t start = s.find(":",found); - if (start == string::npos) start = s.find(" ",found); - size_t end = s.find(" ",start); - string d; - if (end != string::npos){ - d = s.substr(start+1,end-start-1); - }else{ - d = s.substr(start+1); + if (found != string::npos) + { + size_t start = s.find(":", found); + if (start == string::npos) + start = s.find(" ", found); + size_t end = s.find(" ", start); + string d; + if (end != string::npos) + { + d = s.substr(start + 1, end - start - 1); + } + else + { + d = s.substr(start + 1); + } + WParsedInt * life = NEW WParsedInt(d, spell, card); + Damageable * t = NULL; + if (spell) + t = spell->getNextDamageableTarget(); + MTGAbility * a = NEW AALifeSet(id, card, t, life, NULL, 0, who); + a->oneShot = 1; + return a; } - WParsedInt * life = NEW WParsedInt(d,spell,card); - Damageable * t = NULL; - if (spell) t = spell->getNextDamageableTarget(); - MTGAbility * a = NEW AALifeSet(id,card,t, life, NULL, 0, who); - a->oneShot = 1; - return a; - } - //gain/lose life - found = s.find("life:"); - if (found != string::npos){ - size_t start = found+4; - size_t end = s.find(" ",start); - string life_s; - if (end != string::npos){ - life_s = s.substr(start+1,end-start-1); - }else{ - life_s = s.substr(start+1); + //gain/lose life + found = s.find("life:"); + if (found != string::npos) + { + size_t start = found + 4; + size_t end = s.find(" ", start); + string life_s; + if (end != string::npos) + { + life_s = s.substr(start + 1, end - start - 1); + } + else + { + life_s = s.substr(start + 1); + } + WParsedInt * life = NEW WParsedInt(life_s, spell, card); + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AALifer(id, card, t, life, NULL, 0, who); + a->oneShot = 1; + return a; } - WParsedInt * life = NEW WParsedInt(life_s,spell,card); - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AALifer(id,card,t,life,NULL,0,who); - a->oneShot = 1; - return a; - } - // Win the game - found = s.find("wingame"); - if (found != string::npos){ - Damageable * d = NULL; - if (spell) d = spell->getNextDamageableTarget(); - MTGAbility * a = NEW AAWinGame(id,card,d,NULL,0,who); - a->oneShot = 1; - return a; - } - - //Draw - found = s.find("draw:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - string nbcardsStr; - if (end != string::npos){ - nbcardsStr = s.substr(start+1,end-start-1); - }else{ - nbcardsStr = s.substr(start+1); + // Win the game + found = s.find("wingame"); + if (found != string::npos) + { + Damageable * d = NULL; + if (spell) + d = spell->getNextDamageableTarget(); + MTGAbility * a = NEW AAWinGame(id, card, d, NULL, 0, who); + a->oneShot = 1; + return a; + } + + //Draw + found = s.find("draw:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + string nbcardsStr; + if (end != string::npos) + { + nbcardsStr = s.substr(start + 1, end - start - 1); + } + else + { + nbcardsStr = s.substr(start + 1); + } + WParsedInt * nbcards = NEW WParsedInt(nbcardsStr, spell, card); + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AADrawer(id, card, t, NULL, nbcards, 0, who); + a->oneShot = 1; + return a; } - WParsedInt * nbcards = NEW WParsedInt(nbcardsStr,spell,card); - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AADrawer(id,card,t,NULL,nbcards,0,who); - a->oneShot = 1; - return a; - } //additional lands per turn - found = s.find("land:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - string additionalStr; - if (end != string::npos){ - additionalStr = s.substr(start+1,end-start-1); - }else{ - additionalStr = s.substr(start+1); - } - WParsedInt * additional = NEW WParsedInt(additionalStr,spell,card); - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AAMoreLandPlz(id,card,t,NULL,additional,0,who); - a->oneShot = 1; - return a; - } - - //Deplete - found = s.find("deplete:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - int nbcards; - if (end != string::npos){ - nbcards = atoi(s.substr(start+1,end-start-1).c_str()); - }else{ - nbcards = atoi(s.substr(start+1).c_str()); + found = s.find("land:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + string additionalStr; + if (end != string::npos) + { + additionalStr = s.substr(start + 1, end - start - 1); + } + else + { + additionalStr = s.substr(start + 1); + } + WParsedInt * additional = NEW WParsedInt(additionalStr, spell, card); + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AAMoreLandPlz(id, card, t, NULL, additional, 0, who); + a->oneShot = 1; + return a; } - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AADepleter(id,card,t,nbcards,NULL,0,who); - a->oneShot = 1; - return a; - } + //Deplete + found = s.find("deplete:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + int nbcards; + if (end != string::npos) + { + nbcards = atoi(s.substr(start + 1, end - start - 1).c_str()); + } + else + { + nbcards = atoi(s.substr(start + 1).c_str()); + } + + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AADepleter(id, card, t, nbcards, NULL, 0, who); + a->oneShot = 1; + return a; + } //Shuffle - found = s.find("shuffle"); - if (found != string::npos){ - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AAShuffle(id,card,t,NULL,0,who); - a->oneShot = 1; - return a; - } - - - //cantcastspells - found = s.find("onlyonespell"); - if (found != string::npos){ - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AAOnlyOne(id,card,t,NULL,0,who); - a->oneShot = 1; - return a; - } - //cantcastspells - found = s.find("nospells"); - if (found != string::npos){ - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AANoSpells(id,card,t,NULL,0,who); - a->oneShot = 1; - return a; - } - //cantcastcreature - found = s.find("nocreatures"); - if (found != string::npos){ - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AANoCreatures(id,card,t,NULL,0,who); - a->oneShot = 1; - return a; + found = s.find("shuffle"); + if (found != string::npos) + { + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AAShuffle(id, card, t, NULL, 0, who); + a->oneShot = 1; + return a; } - //Discard - found = s.find("discard:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - int nbcards; - if (end != string::npos){ - nbcards = atoi(s.substr(start+1,end-start-1).c_str()); - }else{ - nbcards = atoi(s.substr(start+1).c_str()); + //cantcastspells + found = s.find("onlyonespell"); + if (found != string::npos) + { + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AAOnlyOne(id, card, t, NULL, 0, who); + a->oneShot = 1; + return a; + } + //cantcastspells + found = s.find("nospells"); + if (found != string::npos) + { + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AANoSpells(id, card, t, NULL, 0, who); + a->oneShot = 1; + return a; + } + //cantcastcreature + found = s.find("nocreatures"); + if (found != string::npos) + { + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AANoCreatures(id, card, t, NULL, 0, who); + a->oneShot = 1; + return a; } - Targetable * t = NULL; - if (spell) t = spell->getNextPlayerTarget(); - MTGAbility * a = NEW AARandomDiscarder (id, card, t,nbcards,NULL,0,who); - a->oneShot = 1; - return a; - } - - - - //rampage - found = s.find("rampage("); - if (found != string::npos){ - int end = s.find(",", found); - string spt = s.substr(8,end - 1); - int power, toughness; - if (parsePowerToughness(spt,&power, &toughness)){ - int MaxOpponent = atoi(s.substr(end+1,end+2).c_str()); - return NEW ARampageAbility(id,card,power,toughness,MaxOpponent); - } - return NULL; - } - - //bushido - found = s.find("bushido("); - if (found != string::npos){ - int end = s.find(")", found); - string spt = s.substr(8,end - 1); - int power, toughness; - if (parsePowerToughness(spt,&power, &toughness)){ - return NEW ABushidoAbility(id,card,power,toughness); - } - return NULL; - } - - //counter - found = s.find("counter("); - if (found != string::npos){ - size_t start = s.find("("); - size_t end = s.find(")"); - string counterString = s.substr(start+1,end-start-1); - Counter * counter = parseCounter(counterString,target,spell); - if (counter){ - MTGAbility * a = NEW AACounter(id,card,target,counter->name.c_str(),counter->power,counter->toughness,counter->nb); - delete(counter); - a->oneShot = 1; - return a; - } - return NULL; - } - //Becomes... (animate artifact...: becomes(Creature, manacost/manacost) - found = s.find("becomes("); - if (found != string::npos){ - size_t real_end = s.find(")", found); - size_t end = s.find(",", found); - if (end == string::npos) end = real_end; - string stypes = s.substr(found + 8,end - found - 8); - WParsedPT * pt = NULL; - string sabilities; - if (end != real_end){ - int previous = end+1; - end = s.find(",",previous); - if (end == string::npos) end = real_end; - string temp = s.substr(previous, end - previous); - pt = NEW WParsedPT(temp,spell,card); - if (!pt->ok){ - SAFE_DELETE(pt); - sabilities = temp; - } - } - if (pt && end != real_end){ - sabilities = s.substr(end+1, real_end - end); - } - MTGAbility * ab; - if (forceUEOT){ - ab = NEW ABecomesUEOT(id,card,target,stypes,pt,sabilities); - }else{ - ab = NEW ABecomes(id,card,target,stypes,pt,sabilities); - }return ab; - } - - //bloodthirst - found = s.find("bloodthirst:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - int amount; - if (end != string::npos){ - amount = atoi(s.substr(start+1,end-start-1).c_str()); - } else { - amount = atoi(s.substr(start+1).c_str()); - } - MTGAbility * a = NEW ABloodThirst(id,card,target,amount); - return a; - } - - if ( s.find("altercost(") != string::npos ) - return getManaReduxAbility( s.substr( s.find("altercost(") + 10), id, spell, card, target ); - - //resetcost dirty code - found = s.find("resetcost"); - if (found != string::npos){ - MTGAbility * a = NEW AResetCost(id,card,target); - return a; - } - //transform....(hivestone,living enchantment) - found = s.find("transforms("); - if (found != string::npos){ - size_t real_end = s.find(")", found); - size_t end = s.find(",", found); - if (end == string::npos) end = real_end; - string stypes = s.substr(found + 11,end - found - 11); - string sabilities; - if (end != real_end){ - int previous = end+1; - if (end == string::npos) end = real_end; - string temp = s.substr(previous, end - previous); - } - if (end != real_end){ - sabilities = s.substr(end+1, real_end - end); - } - MTGAbility * a; - if(forceFOREVER){ - a = NEW ATransformerFOREVER(id,card,target,stypes,sabilities); - } - else if (forceUEOT){ - a = NEW ATransformerUEOT(id,card,target,stypes,sabilities); - } - else{ - a = NEW ATransformer(id,card,target,stypes,sabilities); - } - return a; - } - //Change Power/Toughness - WParsedPT * wppt = NEW WParsedPT(s,spell,card); - if (wppt->ok){ - if (!activated){ - if(card->hasType("instant") || card->hasType("sorcery") || forceUEOT){ - return NEW AInstantPowerToughnessModifierUntilEOT(id, card, target,wppt); - } - return NEW APowerToughnessModifier(id, card, target,wppt); - } - return NEW APowerToughnessModifierUntilEndOfTurn(id,card,target,wppt); - } - else{ - delete wppt; - } - - //Mana Producer - found = s.find("add"); - if (found != string::npos){ - ManaCost * output = ManaCost::parseManaCost(s.substr(found)); - Targetable * t = NULL; - if (spell) t = spell->getNextTarget(); - MTGAbility * a = NEW AManaProducer(id, card, t, output, NULL, 1, who); - a->oneShot = 1; - return a; - } - - //Protection from... - found = s.find("protection from("); - if (found == 0){ - size_t end = s.find (")", found); - string targets = s.substr(found+16,end - found - 16); - TargetChooserFactory tcf; - TargetChooser * fromTc = tcf.createTargetChooser(targets, card); - if (!fromTc) return NULL; - fromTc->setAllZones(); - if (!activated){ - if(card->hasType("instant") || card->hasType("sorcery") || forceUEOT){ - return NULL; //TODO - } - return NEW AProtectionFrom(id, card,target,fromTc); - } - return NULL; //TODO - } - - //Can't be blocked by... - found = s.find("cantbeblockedby("); - if (found == 0){ - size_t end = s.find (")", found); - string targets = s.substr(found+16,end - found - 16); - TargetChooserFactory tcf; - TargetChooser * fromTc = tcf.createTargetChooser(targets, card); - if (!fromTc) return NULL; - //default target zone to opponentbattlefield here? - if (!activated){ - if(card->hasType("instant") || card->hasType("sorcery") || forceUEOT){ - return NULL; //TODO - } - return NEW ACantBeBlockedBy(id, card,target,fromTc); - } - return NULL; //TODO - } - - //frozen, next untap this does not untap. - found = s.find("frozen"); - if (found != string::npos){ - MTGAbility * a = NEW AAFrozen(id,card,target); - a->oneShot = 1; - return a; - } - - //identify what a leveler creature will max out at. - found = s.find("maxlevel:"); - if (found != string::npos){ - size_t start = s.find(":",found); - size_t end = s.find(" ",start); - int value; - if (end != string::npos){ - value = atoi(s.substr(start+1,end-start-1).c_str()); - } - else{ - value = atoi(s.substr(start+1).c_str()); - } - MTGAbility * a = NEW AAWhatsMax(id,card,card,NULL,0,value); - a->oneShot = 1; - return a; - } - - //switch targest power with toughness - found = s.find("swap"); - if (found != string::npos){ - MTGAbility * a = NEW ASwapPTUEOT(id,card,target); - a->oneShot = 1; - return a; - } - - //Gain/loose simple Ability - for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ - found = s.find(Constants::MTGBasicAbilities[j]); - if (found == 0 || found == 1){ - int modifier = 1; - if (found > 0 && s[found-1] == '-') modifier = 0; - if (!activated){ - if(card->hasType("instant") || card->hasType("sorcery") || forceUEOT){ - return NEW AInstantBasicAbilityModifierUntilEOT(id, card,target, j,modifier); + //Discard + found = s.find("discard:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + int nbcards; + if (end != string::npos) + { + nbcards = atoi(s.substr(start + 1, end - start - 1).c_str()); } - return NEW ABasicAbilityModifier(id, card,target, j,modifier); - } - return NEW ABasicAbilityAuraModifierUntilEOT(id, card,target, NULL,j,modifier); + else + { + nbcards = atoi(s.substr(start + 1).c_str()); + } + + Targetable * t = NULL; + if (spell) + t = spell->getNextPlayerTarget(); + MTGAbility * a = NEW AARandomDiscarder(id, card, t, nbcards, NULL, 0, who); + a->oneShot = 1; + return a; } - } - - //Untapper (Ley Druid...) - found = s.find("untap"); - if (found != string::npos){ - MTGAbility * a = NEW AAUntapper(id,card,target); - a->oneShot = 1; - return a; - } - //Tapper (icy manipulator) - found = s.find("tap"); - if (found != string::npos){ - MTGAbility * a = NEW AATapper(id,card,target); - a->oneShot = 1; - return a; - } + //rampage + found = s.find("rampage("); + if (found != string::npos) + { + int end = s.find(",", found); + string spt = s.substr(8, end - 1); + int power, toughness; + if (parsePowerToughness(spt, &power, &toughness)) + { + int MaxOpponent = atoi(s.substr(end + 1, end + 2).c_str()); + return NEW ARampageAbility(id, card, power, toughness, MaxOpponent); + } + return NULL; + } - DebugTrace(" no matching ability found. " << s); - return NULL; + //bushido + found = s.find("bushido("); + if (found != string::npos) + { + int end = s.find(")", found); + string spt = s.substr(8, end - 1); + int power, toughness; + if (parsePowerToughness(spt, &power, &toughness)) + { + return NEW ABushidoAbility(id, card, power, toughness); + } + return NULL; + } + + //counter + found = s.find("counter("); + if (found != string::npos) + { + size_t start = s.find("("); + size_t end = s.find(")"); + string counterString = s.substr(start + 1, end - start - 1); + Counter * counter = parseCounter(counterString, target, spell); + if (counter) + { + MTGAbility * a = + NEW AACounter(id, card, target, counter->name.c_str(), counter->power, counter->toughness, counter->nb); + delete (counter); + a->oneShot = 1; + return a; + } + return NULL; + } + //Becomes... (animate artifact...: becomes(Creature, manacost/manacost) + found = s.find("becomes("); + if (found != string::npos) + { + size_t real_end = s.find(")", found); + size_t end = s.find(",", found); + if (end == string::npos) + end = real_end; + string stypes = s.substr(found + 8, end - found - 8); + WParsedPT * pt = NULL; + string sabilities; + if (end != real_end) + { + int previous = end + 1; + end = s.find(",", previous); + if (end == string::npos) + end = real_end; + string temp = s.substr(previous, end - previous); + pt = NEW WParsedPT(temp, spell, card); + if (!pt->ok) + { + SAFE_DELETE(pt); + sabilities = temp; + } + } + if (pt && end != real_end) + { + sabilities = s.substr(end + 1, real_end - end); + } + MTGAbility * ab; + if (forceUEOT) + { + ab = NEW ABecomesUEOT(id, card, target, stypes, pt, sabilities); + } + else + { + ab = NEW ABecomes(id, card, target, stypes, pt, sabilities); + } + return ab; + } + + //bloodthirst + found = s.find("bloodthirst:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + int amount; + if (end != string::npos) + { + amount = atoi(s.substr(start + 1, end - start - 1).c_str()); + } + else + { + amount = atoi(s.substr(start + 1).c_str()); + } + MTGAbility * a = NEW ABloodThirst(id, card, target, amount); + return a; + } + + if (s.find("altercost(") != string::npos) + return getManaReduxAbility(s.substr(s.find("altercost(") + 10), id, spell, card, target); + + //resetcost dirty code + found = s.find("resetcost"); + if (found != string::npos) + { + MTGAbility * a = NEW AResetCost(id, card, target); + return a; + } + //transform....(hivestone,living enchantment) + found = s.find("transforms("); + if (found != string::npos) + { + size_t real_end = s.find(")", found); + size_t end = s.find(",", found); + if (end == string::npos) + end = real_end; + string stypes = s.substr(found + 11, end - found - 11); + string sabilities; + if (end != real_end) + { + int previous = end + 1; + if (end == string::npos) + end = real_end; + string temp = s.substr(previous, end - previous); + } + if (end != real_end) + { + sabilities = s.substr(end + 1, real_end - end); + } + MTGAbility * a; + if (forceFOREVER) + { + a = NEW ATransformerFOREVER(id, card, target, stypes, sabilities); + } + else if (forceUEOT) + { + a = NEW ATransformerUEOT(id, card, target, stypes, sabilities); + } + else + { + a = NEW ATransformer(id, card, target, stypes, sabilities); + } + return a; + } + //Change Power/Toughness + WParsedPT * wppt = NEW WParsedPT(s, spell, card); + if (wppt->ok) + { + if (!activated) + { + if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + { + return NEW AInstantPowerToughnessModifierUntilEOT(id, card, target, wppt); + } + return NEW APowerToughnessModifier(id, card, target, wppt); + } + return NEW APowerToughnessModifierUntilEndOfTurn(id, card, target, wppt); + } + else + { + delete wppt; + } + + //Mana Producer + found = s.find("add"); + if (found != string::npos) + { + ManaCost * output = ManaCost::parseManaCost(s.substr(found)); + Targetable * t = NULL; + if (spell) + t = spell->getNextTarget(); + MTGAbility * a = NEW AManaProducer(id, card, t, output, NULL, 1, who); + a->oneShot = 1; + return a; + } + + //Protection from... + found = s.find("protection from("); + if (found == 0) + { + size_t end = s.find(")", found); + string targets = s.substr(found + 16, end - found - 16); + TargetChooserFactory tcf; + TargetChooser * fromTc = tcf.createTargetChooser(targets, card); + if (!fromTc) + return NULL; + fromTc->setAllZones(); + if (!activated) + { + if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + { + return NULL; //TODO + } + return NEW AProtectionFrom(id, card, target, fromTc); + } + return NULL; //TODO + } + + //Can't be blocked by... + found = s.find("cantbeblockedby("); + if (found == 0) + { + size_t end = s.find(")", found); + string targets = s.substr(found + 16, end - found - 16); + TargetChooserFactory tcf; + TargetChooser * fromTc = tcf.createTargetChooser(targets, card); + if (!fromTc) + return NULL; + //default target zone to opponentbattlefield here? + if (!activated) + { + if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + { + return NULL; //TODO + } + return NEW ACantBeBlockedBy(id, card, target, fromTc); + } + return NULL; //TODO + } + + //frozen, next untap this does not untap. + found = s.find("frozen"); + if (found != string::npos) + { + MTGAbility * a = NEW AAFrozen(id, card, target); + a->oneShot = 1; + return a; + } + + //identify what a leveler creature will max out at. + found = s.find("maxlevel:"); + if (found != string::npos) + { + size_t start = s.find(":", found); + size_t end = s.find(" ", start); + int value; + if (end != string::npos) + { + value = atoi(s.substr(start + 1, end - start - 1).c_str()); + } + else + { + value = atoi(s.substr(start + 1).c_str()); + } + MTGAbility * a = NEW AAWhatsMax(id, card, card, NULL, 0, value); + a->oneShot = 1; + return a; + } + + //switch targest power with toughness + found = s.find("swap"); + if (found != string::npos) + { + MTGAbility * a = NEW ASwapPTUEOT(id, card, target); + a->oneShot = 1; + return a; + } + + //Gain/loose simple Ability + for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++) + { + found = s.find(Constants::MTGBasicAbilities[j]); + if (found == 0 || found == 1) + { + int modifier = 1; + if (found > 0 && s[found - 1] == '-') + modifier = 0; + if (!activated) + { + if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT) + { + return NEW AInstantBasicAbilityModifierUntilEOT(id, card, target, j, modifier); + } + return NEW ABasicAbilityModifier(id, card, target, j, modifier); + } + return NEW ABasicAbilityAuraModifierUntilEOT(id, card, target, NULL, j, modifier); + } + } + + //Untapper (Ley Druid...) + found = s.find("untap"); + if (found != string::npos) + { + MTGAbility * a = NEW AAUntapper(id, card, target); + a->oneShot = 1; + return a; + } + + //Tapper (icy manipulator) + found = s.find("tap"); + if (found != string::npos) + { + MTGAbility * a = NEW AATapper(id, card, target); + a->oneShot = 1; + return a; + } + + DebugTrace(" no matching ability found. " << s); + return NULL; } //Tells the AI if the ability should target itself or an ennemy -int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, TargetChooser * tc){ - if (!a) return BAKA_EFFECT_DONTKNOW; +int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, TargetChooser * tc) +{ + if (!a) + return BAKA_EFFECT_DONTKNOW; - if (GenericTargetAbility * abi = dynamic_cast(a)) { - if (mode == MODE_PUTINTOPLAY) return BAKA_EFFECT_GOOD; - return abilityEfficiency(abi->ability,p, mode, abi->tc); - } - if (GenericActivatedAbility * abi = dynamic_cast(a)) { - if (mode == MODE_PUTINTOPLAY) return BAKA_EFFECT_GOOD; - return abilityEfficiency(abi->ability,p, mode,tc); - } - if (MultiAbility * abi = dynamic_cast(a)) return abilityEfficiency(abi->abilities[0],p, mode,tc ); - if (MayAbility * abi = dynamic_cast(a)) return abilityEfficiency(abi->ability,p, mode,tc); - if (ALord * abi = dynamic_cast(a)) { - int myCards = countCards(abi->tc, p); - int theirCards = countCards(abi->tc, p->opponent()); - int efficiency = abilityEfficiency(abi->ability,p, mode,tc); - if (myCards > theirCards) return efficiency; - return -efficiency; - } - if (AAsLongAs * abi = dynamic_cast(a)) return abilityEfficiency(abi->ability,p, mode,tc); - if (AForeach * abi = dynamic_cast(a)) return abilityEfficiency(abi->ability,p, mode,tc); - if (dynamic_cast(a)) return BAKA_EFFECT_BAD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (dynamic_cast(a)) return BAKA_EFFECT_BAD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (dynamic_cast(a)) return BAKA_EFFECT_BAD; - if (AACounter * ac = dynamic_cast(a)) { - bool negative_effect = ac->power < 0 || ac->toughness < 0; - if ((ac->nb > 0 && negative_effect) || (ac->nb < 0 && !negative_effect)) return BAKA_EFFECT_BAD; - return BAKA_EFFECT_GOOD ; - } - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - - if (AAMover * aam = dynamic_cast(a)) { - MTGGameZone * z = aam->destinationZone(); - if (tc && tc->targetsZone(p->game->library)){ - if (z == p->game->hand || z == p->game->inPlay) return BAKA_EFFECT_GOOD; + if (GenericTargetAbility * abi = dynamic_cast(a)) + { + if (mode == MODE_PUTINTOPLAY) + return BAKA_EFFECT_GOOD; + return abilityEfficiency(abi->ability, p, mode, abi->tc); } - return BAKA_EFFECT_BAD; //TODO - } - - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (dynamic_cast(a)) return BAKA_EFFECT_BAD; - if (dynamic_cast(a)) return BAKA_EFFECT_BAD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (AALifer * abi = dynamic_cast(a)) return abi->life > 0 ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; - if (dynamic_cast(a)) return BAKA_EFFECT_BAD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (dynamic_cast(a)) return BAKA_EFFECT_BAD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (AInstantPowerToughnessModifierUntilEOT * abi = dynamic_cast(a)) return (abi->wppt->power.getValue()>=0 && abi->wppt->toughness.getValue()>=0) ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; - if (APowerToughnessModifier * abi = dynamic_cast(a)) return (abi->wppt->power.getValue()>=0 && abi->wppt->toughness.getValue()>=0) ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; - if (APowerToughnessModifierUntilEndOfTurn * abi = dynamic_cast(a)) return abilityEfficiency(abi->ability, p, mode,tc); - - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - - map badAbilities; - badAbilities[Constants::CANTATTACK] = true; - badAbilities[Constants::CANTBLOCK] = true; - badAbilities[Constants::CLOUD] = true; - badAbilities[Constants::DEFENDER] = true; - badAbilities[Constants::DOESNOTUNTAP] = true; - badAbilities[Constants::MUSTATTACK] = true; - badAbilities[Constants::CANTREGEN] = true; - - if (AInstantBasicAbilityModifierUntilEOT * abi = dynamic_cast(a)) { - int result = badAbilities[abi->ability] ? BAKA_EFFECT_BAD : BAKA_EFFECT_GOOD; - return (abi->value > 0) ? result : -result; + if (GenericActivatedAbility * abi = dynamic_cast(a)) + { + if (mode == MODE_PUTINTOPLAY) + return BAKA_EFFECT_GOOD; + return abilityEfficiency(abi->ability, p, mode, tc); } - if (ABasicAbilityModifier * abi = dynamic_cast(a)){ - int result = (badAbilities[abi->ability]) ? BAKA_EFFECT_BAD : BAKA_EFFECT_GOOD; - return (abi->modifier > 0) ? result : -result; - } - if (ABasicAbilityAuraModifierUntilEOT * abi = dynamic_cast(a)) - return abilityEfficiency(abi->ability, p, mode); - if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; - return BAKA_EFFECT_DONTKNOW; + if (MultiAbility * abi = dynamic_cast(a)) + return abilityEfficiency(abi->abilities[0], p, mode, tc); + if (MayAbility * abi = dynamic_cast(a)) + return abilityEfficiency(abi->ability, p, mode, tc); + if (ALord * abi = dynamic_cast(a)) + { + int myCards = countCards(abi->tc, p); + int theirCards = countCards(abi->tc, p->opponent()); + int efficiency = abilityEfficiency(abi->ability, p, mode, tc); + if (myCards > theirCards) + return efficiency; + return -efficiency; + } + if (AAsLongAs * abi = dynamic_cast(a)) + return abilityEfficiency(abi->ability, p, mode, tc); + if (AForeach * abi = dynamic_cast(a)) + return abilityEfficiency(abi->ability, p, mode, tc); + if (dynamic_cast (a)) + return BAKA_EFFECT_BAD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (dynamic_cast (a)) + return BAKA_EFFECT_BAD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (dynamic_cast (a)) + return BAKA_EFFECT_BAD; + if (AACounter * ac = dynamic_cast(a)) + { + bool negative_effect = ac->power < 0 || ac->toughness < 0; + if ((ac->nb > 0 && negative_effect) || (ac->nb < 0 && !negative_effect)) + return BAKA_EFFECT_BAD; + return BAKA_EFFECT_GOOD; + } + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + + if (AAMover * aam = dynamic_cast(a)) + { + MTGGameZone * z = aam->destinationZone(); + if (tc && tc->targetsZone(p->game->library)) + { + if (z == p->game->hand || z == p->game->inPlay) + return BAKA_EFFECT_GOOD; + } + return BAKA_EFFECT_BAD; //TODO + } + + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (dynamic_cast (a)) + return BAKA_EFFECT_BAD; + if (dynamic_cast (a)) + return BAKA_EFFECT_BAD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (AALifer * abi = dynamic_cast(a)) + return abi->life > 0 ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; + if (dynamic_cast (a)) + return BAKA_EFFECT_BAD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (dynamic_cast (a)) + return BAKA_EFFECT_BAD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (AInstantPowerToughnessModifierUntilEOT * abi = dynamic_cast(a)) + return (abi->wppt->power.getValue() >= 0 && abi->wppt->toughness.getValue() >= 0) ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; + if (APowerToughnessModifier * abi = dynamic_cast(a)) + return (abi->wppt->power.getValue() >= 0 && abi->wppt->toughness.getValue() >= 0) ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; + if (APowerToughnessModifierUntilEndOfTurn * abi = dynamic_cast(a)) + return abilityEfficiency(abi->ability, p, mode, tc); + + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + + map badAbilities; + badAbilities[Constants::CANTATTACK] = true; + badAbilities[Constants::CANTBLOCK] = true; + badAbilities[Constants::CLOUD] = true; + badAbilities[Constants::DEFENDER] = true; + badAbilities[Constants::DOESNOTUNTAP] = true; + badAbilities[Constants::MUSTATTACK] = true; + badAbilities[Constants::CANTREGEN] = true; + + if (AInstantBasicAbilityModifierUntilEOT * abi = dynamic_cast(a)) + { + int result = badAbilities[abi->ability] ? BAKA_EFFECT_BAD : BAKA_EFFECT_GOOD; + return (abi->value > 0) ? result : -result; + } + if (ABasicAbilityModifier * abi = dynamic_cast(a)) + { + int result = (badAbilities[abi->ability]) ? BAKA_EFFECT_BAD : BAKA_EFFECT_GOOD; + return (abi->modifier > 0) ? result : -result; + } + if (ABasicAbilityAuraModifierUntilEOT * abi = dynamic_cast(a)) + return abilityEfficiency(abi->ability, p, mode); + if (dynamic_cast (a)) + return BAKA_EFFECT_GOOD; + return BAKA_EFFECT_DONTKNOW; } //Returns the "X" cost that was paid for a spell -int AbilityFactory::computeX(Spell * spell, MTGCardInstance * card){ - if (spell) return spell->computeX(card); - return 0; +int AbilityFactory::computeX(Spell * spell, MTGCardInstance * card) +{ + if (spell) + return spell->computeX(card); + return 0; } //Returns the "XX" cost that was paid for a spell -int AbilityFactory::computeXX(Spell * spell, MTGCardInstance * card){ - if (spell) return spell->computeXX(card); - return 0; +int AbilityFactory::computeXX(Spell * spell, MTGCardInstance * card) +{ + if (spell) + return spell->computeXX(card); + return 0; } -int AbilityFactory::getAbilities(vector * v, Spell * spell, MTGCardInstance * card, int id, MTGGameZone * dest){ - - if (!card && spell) card = spell->source; - if (!card) return 0; - MTGCardInstance * target = card->target; - if (!target) target = card; - string magicText; - if (dest) { - GameObserver * g = GameObserver::GetInstance(); - for (int i = 0; i < 2 ; ++i){ - MTGPlayerCards * zones = g->players[i]->game; - if (dest == zones->hand){ - magicText = card->magicTexts["hand"]; - break; - } - if (dest == zones->graveyard){ - magicText = card->magicTexts["graveyard"]; - break; - } - if (dest == zones->stack){ - magicText = card->magicTexts["stack"]; - break; - } - if (dest == zones->exile){ - magicText = card->magicTexts["exile"]; - break; - } - if (dest == zones->library){ - magicText = card->magicTexts["library"]; - break; - } - //Other zones needed ? - return 0; - } - }else{ - magicText = card->magicText; - } - if (card->alias && magicText.size() == 0 && !dest){ - MTGCard * c = GameApp::collection->getCardById(card->alias); - if (!c) return 0; - magicText = c->data->magicText; - } - string line; - int size = magicText.size(); - if (size == 0) return 0; - size_t found; - int result = id; +int AbilityFactory::getAbilities(vector * v, Spell * spell, MTGCardInstance * card, int id, MTGGameZone * dest) +{ - while (magicText.size()){ - found = magicText.find("\n"); - if (found != string::npos){ - line = magicText.substr(0,found); - magicText = magicText.substr(found+1); - }else{ - line = magicText; - magicText = ""; + if (!card && spell) + card = spell->source; + if (!card) + return 0; + MTGCardInstance * target = card->target; + if (!target) + target = card; + string magicText; + if (dest) + { + GameObserver * g = GameObserver::GetInstance(); + for (int i = 0; i < 2; ++i) + { + MTGPlayerCards * zones = g->players[i]->game; + if (dest == zones->hand) + { + magicText = card->magicTexts["hand"]; + break; + } + if (dest == zones->graveyard) + { + magicText = card->magicTexts["graveyard"]; + break; + } + if (dest == zones->stack) + { + magicText = card->magicTexts["stack"]; + break; + } + if (dest == zones->exile) + { + magicText = card->magicTexts["exile"]; + break; + } + if (dest == zones->library) + { + magicText = card->magicTexts["library"]; + break; + } + //Other zones needed ? + return 0; + } } + else + { + magicText = card->magicText; + } + if (card->alias && magicText.size() == 0 && !dest) + { + MTGCard * c = GameApp::collection->getCardById(card->alias); + if (!c) + return 0; + magicText = c->data->magicText; + } + string line; + int size = magicText.size(); + if (size == 0) + return 0; + size_t found; + int result = id; - MTGAbility * a = parseMagicLine(line, result, spell, card,0,0,0,0,dest); - if (a){ - v->push_back(a); - result++; - }else{ - DebugTrace("ABILITYFACTORY ERROR: Parser returned NULL"); + while (magicText.size()) + { + found = magicText.find("\n"); + if (found != string::npos) + { + line = magicText.substr(0, found); + magicText = magicText.substr(found + 1); + } + else + { + line = magicText; + magicText = ""; + } + + MTGAbility * a = parseMagicLine(line, result, spell, card, 0, 0, 0, 0, dest); + if (a) + { + v->push_back(a); + result++; + } + else + { + DebugTrace("ABILITYFACTORY ERROR: Parser returned NULL"); + } } - } - return result; + return result; } //Some basic functionalities that can be added automatically in the text file @@ -1750,1424 +2140,1662 @@ int AbilityFactory::getAbilities(vector * v, Spell * spell, MTGCar * - target (if there ie a "target(" in the string, then this is a TargetAbility) * - doTap (a dirty way to know if tapping is included in the cost... */ -int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int mode, TargetChooser * tc,MTGGameZone * dest){ - int dryMode = 0; - if (!spell && !dest) dryMode = 1; +int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int mode, TargetChooser * tc, MTGGameZone * dest) +{ + int dryMode = 0; + if (!spell && !dest) + dryMode = 1; - vector v; - int result = getAbilities(&v,spell,card,id,dest); + vector v; + int result = getAbilities(&v, spell, card, id, dest); - for (size_t i = 0; i < v.size(); ++i){ - MTGAbility * a = v[i]; - if (dryMode){ - result = abilityEfficiency(a, card->controller(),mode,tc); - for (size_t i = 0; i < v.size(); ++i) - SAFE_DELETE(v[i]); - return result; + for (size_t i = 0; i < v.size(); ++i) + { + MTGAbility * a = v[i]; + if (dryMode) + { + result = abilityEfficiency(a, card->controller(), mode, tc); + for (size_t i = 0; i < v.size(); ++i) + SAFE_DELETE(v[i]); + return result; + } + + if (a) + { + if (a->oneShot) + { + a->resolve(); + delete (a); + } + else + { + a->addToGame(); + } + } + else + { + DebugTrace("ABILITYFACTORY ERROR: Parser returned NULL"); + } } - if (a){ - if (a->oneShot){ - a->resolve(); - delete(a); - }else{ - a->addToGame(); - } - }else{ - DebugTrace("ABILITYFACTORY ERROR: Parser returned NULL"); - } - } - return result; - + return result; } -void AbilityFactory::addAbilities(int _id, Spell * spell){ - MTGCardInstance * card = spell->source; +void AbilityFactory::addAbilities(int _id, Spell * spell) +{ + MTGCardInstance * card = spell->source; + if (spell->getNbTargets() == 1) + { + card->target = spell->getNextCardTarget(); + if (card->target && !spell->tc->canTarget(card->target)) + { + MTGPlayerCards * zones = card->controller()->game; + zones->putInZone(card, spell->from, card->owner->game->graveyard); + return; //fizzle + } + } + _id = magicText(_id, spell); - if (spell->getNbTargets()==1){ - card->target = spell->getNextCardTarget(); - if (card->target && !spell->tc->canTarget(card->target)){ - MTGPlayerCards * zones = card->controller()->game; - zones->putInZone(card,spell->from,card->owner->game->graveyard); - return; //fizzle - } - } - _id = magicText(_id, spell); - - GameObserver * game = GameObserver::GetInstance(); - MTGPlayerCards * zones = card->controller()->game; - - - int id = card->getId(); - if (card->alias) id = card->alias; - switch (id){ - case 1092: //Aladdin's lamp - { - AAladdinsLamp * ability = NEW AAladdinsLamp(_id, card); - game->addObserver(ability); - break; - } - case 1095: //Armageddon clock - { - AArmageddonClock * ability = NEW AArmageddonClock(_id,card); - game->addObserver(ability); - break; - } - - case 1191: //Blue Elemental Blast - { - if (card->target){ - card->target->controller()->game->putInGraveyard(card->target); - }else{ - Spell * starget = spell->getNextSpellTarget(); - game->mLayers->stackLayer()->Fizzle(starget); - } - break; - } - case 1282: //Chaoslace - { - if (card->target){ - card->target->setColor(Constants::MTG_COLOR_RED, 1); - }else{ - Spell * starget = spell->getNextSpellTarget(); - starget->source->setColor(Constants::MTG_COLOR_RED, 1); - } - break; - } - case 1335: //Circle of protection : black - { - game->addObserver(NEW ACircleOfProtection( _id,card, Constants::MTG_COLOR_BLACK)); - break; - } - case 1336: //Circle of protection : blue - { - game->addObserver(NEW ACircleOfProtection( _id,card, Constants::MTG_COLOR_BLUE)); - break; - } - case 1337: //Circle of protection : green - { - game->addObserver(NEW ACircleOfProtection( _id,card, Constants::MTG_COLOR_GREEN)); - break; - } - case 1338: //Circle of protection : red - { - game->addObserver(NEW ACircleOfProtection( _id,card, Constants::MTG_COLOR_RED)); - break; - } - case 1339: //Circle of protection : white - { - game->addObserver(NEW ACircleOfProtection( _id,card, Constants::MTG_COLOR_WHITE)); - break; - } - case 1101: //clockwork Beast - { - game->addObserver(NEW AClockworkBeast(_id,card)); - break; - } - case 1102: //Conservator - { - game->addObserver(NEW AConservator(_id,card)); - break; - } - - case 1103: //Crystal Rod - { - int cost[] = {Constants::MTG_COLOR_ARTIFACT, 1}; - ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_BLUE,NEW ManaCost(cost,1) , 1); - game->addObserver(ability); - break; - } - case 1152: //Deathlace - { - if (card->target){ - card->target->setColor(Constants::MTG_COLOR_BLACK, 1); - }else{ - Spell * starget = spell->getNextSpellTarget(); - starget->source->setColor(Constants::MTG_COLOR_BLACK, 1); - } - break; - } - case 1284: //Dragon Whelp - { - game->addObserver(NEW ADragonWhelp(_id,card)); - break; - } - - case 1345: //Farmstead - { - game->addObserver(NEW AFarmstead(_id, card,card->target)); - break; - } - case 1291: //Fireball - { - int x = computeX(spell,card); - game->addObserver(NEW AFireball(_id, card,spell, x)); - break; - } - case 1112: //Howling Mine - { - game->addObserver(NEW AHowlingMine(_id, card)); - break; - } - case 1113: //Iron Star - { - int cost[] = {Constants::MTG_COLOR_ARTIFACT, 1}; - ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_RED,NEW ManaCost(cost,1) , 1); - game->addObserver(ability); - break; - } - case 1351: // Island Sanctuary - { - game->addObserver(NEW AIslandSanctuary(_id, card)); - break; - } - case 1114: //Ivory cup - { - int cost[] = {Constants::MTG_COLOR_ARTIFACT, 1}; - ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_WHITE,NEW ManaCost(cost,1) , 1); - game->addObserver(ability); - break; - } - case 1117: //Jandors Ring - { - game->addObserver(NEW AJandorsRing( _id, card)); - break; - } - case 1121: //Kormus Bell - { - game->addObserver(NEW AConvertLandToCreatures(id, card, "swamp")); - break; - } - case 1254: //Kudzu - { - game->addObserver(NEW AKudzu(id, card, card->target)); - break; - } - case 1257: //Lifelace - { - if (card->target){ - card->target->setColor(Constants::MTG_COLOR_GREEN, 1); - }else{ - Spell * starget = spell->getNextSpellTarget(); - starget->source->setColor(Constants::MTG_COLOR_GREEN, 1); - } - break; - } - - case 1259: //Living lands - { - game->addObserver(NEW AConvertLandToCreatures(id, card, "forest")); - break; - } - case 1124: //Mana Vault (the rest is softcoded!) - { - game->addObserver(NEW ARegularLifeModifierAura(_id+2, card, card, Constants::MTG_PHASE_DRAW, -1, 1)); - break; - } - case 1215: //Power Leak - { - game->addObserver( NEW APowerLeak(_id ,card, card->target)); - break; - } - case 1358: //Purelace - { - if (card->target){ - card->target->setColor(Constants::MTG_COLOR_WHITE, 1); - }else{ - Spell * starget = spell->getNextSpellTarget(); - starget->source->setColor(Constants::MTG_COLOR_WHITE, 1); - } - break; - } - case 1312: //Red Elemental Blast - { - if (card->target){ - card->target->controller()->game->putInGraveyard(card->target); - }else{ - Spell * starget = spell->getNextSpellTarget(); - game->mLayers->stackLayer()->Fizzle(starget); - } - break; - } - - case 1139: //The Rack - { - game->addObserver( NEW ALifeZoneLink(_id ,card, Constants::MTG_PHASE_UPKEEP, -3)); - break; - } - - case 1140: //Throne of Bone - { - int cost[] = {Constants::MTG_COLOR_ARTIFACT, 1}; - ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_BLACK,NEW ManaCost(cost,1) , 1); - game->addObserver(ability); - break; - } - - case 1142: //Wooden Sphere - { - int cost[] = {Constants::MTG_COLOR_ARTIFACT, 1}; - ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_GREEN,NEW ManaCost(cost,1) , 1); - game->addObserver(ability); - break; - } - case 1143: //Animate Dead - { - AAnimateDead * a = NEW AAnimateDead(_id, card, card->target); - game->addObserver(a); - card->target = ((MTGCardInstance * )a->target); - break; - } - case 1156: //Drain Life - { - Damageable * target = spell->getNextDamageableTarget(); - int x = spell->cost->getConvertedCost() - 2; //TODO Fix that !!! + X should be only black mana, that needs to be checked ! - game->mLayers->stackLayer()->addDamage(card, target, x); - if (target->life < x) x = target->life; - game->currentlyActing()->life+=x; - break; - } - case 1159: //Erg Raiders - { - AErgRaiders* ability = NEW AErgRaiders(_id, card); - game->addObserver(ability); - break; - } - case 1202: //Hurkyl's Recall - { - Player * player = spell->getNextPlayerTarget(); - if (player){ - for (int i = 0; i < 2; i++){ - MTGInPlay * inplay = game->players[i]->game->inPlay; - for (int j= inplay->nb_cards -1 ; j >=0 ; j--){ - MTGCardInstance * card = inplay->cards[j]; - if (card->owner == player && card->hasType("artifact")){ - player->game->putInZone(card, inplay, player->game->hand); - } - } - } - } - break; - } - case 1165: //Hypnotic Specter - { - game->addObserver(NEW AHypnoticSpecter( _id, card)); - break; - } - case 1258: //Living Artifact - { - game->addObserver(NEW ALivingArtifact( _id, card, card->target)); - break; - } - case 1209: //Mana Short - { - Player * player = spell->getNextPlayerTarget(); - if (player){ - MTGInPlay * inplay = player->game->inPlay; - for (int i = 0; i < inplay->nb_cards; i++){ - MTGCardInstance * current = inplay->cards[i]; - if (current->hasType(Subtypes::TYPE_LAND)) current->tap(); - } - player->getManaPool()->init(); - } - break; - } - case 1167: //Mind Twist - { - int xCost = computeX(spell,card); - for (int i = 0; i < xCost; i++){ - game->opponent()->game->discardRandom(game->opponent()->game->hand,card); - } - break; - } - case 1172: //Pestilence - { - game->addObserver(NEW APestilence(_id, card)); - break; - } - - case 1176: //Sacrifice - { - ASacrifice * ability = NEW ASacrifice(_id, card, card->target); - game->addObserver(ability); - break; - } - case 1224: //Spell Blast - { - int x = computeX(spell,card); - Spell * starget = spell->getNextSpellTarget(); - if (starget){ - if (starget->cost->getConvertedCost() <= x) game->mLayers->stackLayer()->Fizzle(starget); - } - break; - } - case 1194: //Control Magic - { - game->addObserver(NEW AControlStealAura(_id, card, card->target)); - break; - } - case 1235: //Aspect of Wolf - { - game->addObserver(NEW AAspectOfWolf(_id, card, card->target)); - break; - } - case 1231: //Volcanic Eruption - { - int x = computeX(spell,card); - int _x = x; - MTGCardInstance * target = spell->getNextCardTarget(); - while(target && _x){ - target->destroy(); - _x--; - target = spell->getNextCardTarget(target); - } - x-=_x; - for (int i = 0; i < 2 ; i++){ - game->mLayers->stackLayer()->addDamage(card, game->players[i], x); - for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++){ - MTGCardInstance * current = game->players[i]->game->inPlay->cards[j]; - if (current->isCreature()){ - game->mLayers->stackLayer()->addDamage(card, current, x); - } - } - } - break; - } - case 1288: //EarthBind - { - game->addObserver(NEW AEarthbind(_id, card, card->target)); - break; - } - case 1344: //Eye for an Eye - { - Damage * damage = spell->getNextDamageTarget(); - if (damage){ - game->mLayers->stackLayer()->addDamage(card,damage->source->controller(),damage->damage); - } - break; - } - case 1243: //Fastbond - { - game->addObserver(NEW AFastbond(_id, card)); - break; - } - case 1238: //Cockatrice - { - game->addObserver(NEW AOldSchoolDeathtouch(_id,card)); - break; - } - case 1225: //Stasis - { - game->addObserver(NEW AStasis(_id, card)); - break; - } - case 1267: //Thicket Basilic - { - game->addObserver(NEW AOldSchoolDeathtouch(_id,card)); - break; - } - case 1227: //Toughtlace - { - if (card->target){ - card->target->setColor(Constants::MTG_COLOR_BLUE, 1); - }else{ - Spell * starget = spell->getNextSpellTarget(); - starget->source->setColor(Constants::MTG_COLOR_BLUE, 1); - } - break; - } - - //Addons Legends - case 1533: //Livingplane - { - game->addObserver(NEW AConvertLandToCreatures(id, card, "land")); - break; - } - case 1480: //Energy Tap - { - card->target->tap(); - int mana = card->target->getManaCost()->getConvertedCost(); - game->currentlyActing()->getManaPool()->add(Constants::MTG_COLOR_ARTIFACT, mana); - } - - //Addons ICE-AGE Cards - - case 2474: //Minion of Leshrac - { - game->addObserver(NEW AMinionofLeshrac( _id, card)); - break; - } - - case 2732: //Kjeldoran Frostbeast - { - game->addObserver(NEW AKjeldoranFrostbeast(_id,card)); - break; - } - - // --- addon Mirage --- - - case 3410: //Seed of Innocence - { - GameObserver * game = GameObserver::GetInstance(); - for (int i = 0; i < 2 ; i++){ - for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++){ - MTGCardInstance * current = game->players[i]->game->inPlay->cards[j]; - if (current->hasType("Artifact")){ - game->players[i]->game->putInGraveyard(current); - current->controller()->life+= current->getManaCost()->getConvertedCost(); - } - } - } - break; - } - -//-- addon 10E--- - - case 129710: //Angelic Chorus - { - game->addObserver( NEW AAngelicChorus(_id,card)); - break; - } - - case 129767: //Threaten - { - game->addObserver( NEW AInstantControlSteal(_id,card,card->target)); - break; - } - case 130373: //Lavaborn Muse - { - game->addObserver( NEW ALavaborn(_id ,card, Constants::MTG_PHASE_UPKEEP, -3,-3)); - break; - } - case 129774: // Traumatize - { - int nbcards; - Player * player = spell->getNextPlayerTarget(); - MTGLibrary * library = player->game->library; - nbcards = (library->nb_cards)/2; - for (int i = 0; i < nbcards; i++){ - if (library->nb_cards) - player->game->putInZone(library->cards[library->nb_cards-1],library, player->game->graveyard); - } - break; - } - - - case 135215: //Sylvan Basilisk - { - game->addObserver( NEW ABasilik (_id ,card)); - break; - } - case 130553:// Beacon of Immortality - { - Player * player = spell->getNextPlayerTarget(); - if (player->life < (INT_MAX / 4) ) player->life += player->life; - zones->putInZone(card,spell->from,zones->library); - zones->library->shuffle(); - break; - } - case 135262:// Beacon of Destruction & unrest - { - zones->putInZone(card,spell->from,zones->library); - zones->library->shuffle(); - break; - } - case 129750: //Sudden Impact - { - Damageable * target = spell->getNextDamageableTarget(); - Player * p = spell->getNextPlayerTarget(); - MTGHand * hand = p->game->hand; - int damage = hand->nb_cards; - game->mLayers->stackLayer()->addDamage(card, target, damage); - break; - } - case 130369: // Soulblast - { - int damage = 0; - Damageable * target = spell->getNextDamageableTarget(); - for (int j = card->controller()->game->inPlay->nb_cards-1; j >=0 ; --j){ - MTGCardInstance * current = card->controller()->game->inPlay->cards[j]; - if (current->hasType(Subtypes::TYPE_CREATURE)){ - card->controller()->game->putInGraveyard(current); - damage+= current->power; - } - } - game->mLayers->stackLayer()->addDamage(card, target, damage); - break; - } - - - case 129698: // Reminisce - { - int nbcards; - Player * player = spell->getNextPlayerTarget(); - MTGLibrary * library = player->game->library; - MTGGraveyard * graveyard = player->game->graveyard; - nbcards = (graveyard->nb_cards); - for (int i = 0; i < nbcards; i++){ - if (graveyard->nb_cards) - player->game->putInZone(graveyard->cards[graveyard->nb_cards-1],graveyard, library); - } - library->shuffle(); - break; - } - - -// --- addon Ravnica--- - - case 89114: //Psychic Drain - { - Player * player = spell->getNextPlayerTarget(); - MTGLibrary * library = player->game->library; - int x = computeX(spell,card); - for (int i = 0; i < x; i++){ - if (library->nb_cards) - player->game->putInZone(library->cards[library->nb_cards-1],library, player->game->graveyard); - } - game->currentlyActing()->life+= x; - break; - } - - default: - break; - } - - - - - /* We want to get rid of these basicAbility things. - * basicAbilities themselves are alright, but creating New object depending on them is dangerous - * The main reason is that classes that add an ability to a card do NOT create these objects, and therefore do NOT - * Work. - * For example, setting EXALTED for a creature is not enough right now... - * It shouldn't be necessary to add an object. State based abilities could do the trick - */ - - if (card->basicAbilities[Constants::EXALTED]){ - game->addObserver(NEW AExalted(_id, card)); - } - - if (card->basicAbilities[Constants::FLANKING]){ - game->addObserver(NEW AFlankerAbility(_id, card)); - } - - // Tested works the first r10 did not function because of the mistake in the array of the definition - if (card->basicAbilities[Constants::FORESTHOME]){ - game->addObserver(NEW AStrongLandLinkCreature(_id, card, "forest")); - } - if (card->basicAbilities[Constants::ISLANDHOME]){ - game->addObserver(NEW AStrongLandLinkCreature(_id, card, "island")); - } - if (card->basicAbilities[Constants::MOUNTAINHOME]){ - game->addObserver(NEW AStrongLandLinkCreature(_id, card,"moutain")); - } - if (card->basicAbilities[Constants::SWAMPHOME]){ - game->addObserver(NEW AStrongLandLinkCreature(_id, card,"swamp")); - } - if (card->basicAbilities[Constants::PLAINSHOME]){ - game->addObserver(NEW AStrongLandLinkCreature(_id, card,"plains")); - } - - if (card->hasType("instant") || card->hasType("sorcery")){ + GameObserver * game = GameObserver::GetInstance(); MTGPlayerCards * zones = card->controller()->game; - if(card->boughtback > 0){ - zones->putInZone(card,zones->stack,zones->hand); - } - else if(card->flashedback > 0){ - zones->putInZone(card,zones->stack,zones->exile); - } - else{ - zones->putInZone(card,zones->stack,zones->graveyard);} - } + int id = card->getId(); + if (card->alias) + id = card->alias; + switch (id) + { + case 1092: //Aladdin's lamp + { + AAladdinsLamp * ability = NEW AAladdinsLamp(_id, card); + game->addObserver(ability); + break; + } + case 1095: //Armageddon clock + { + AArmageddonClock * ability = NEW AArmageddonClock(_id, card); + game->addObserver(ability); + break; + } + + case 1191: //Blue Elemental Blast + { + if (card->target) + { + card->target->controller()->game->putInGraveyard(card->target); + } + else + { + Spell * starget = spell->getNextSpellTarget(); + game->mLayers->stackLayer()->Fizzle(starget); + } + break; + } + case 1282: //Chaoslace + { + if (card->target) + { + card->target->setColor(Constants::MTG_COLOR_RED, 1); + } + else + { + Spell * starget = spell->getNextSpellTarget(); + starget->source->setColor(Constants::MTG_COLOR_RED, 1); + } + break; + } + case 1335: //Circle of protection : black + { + game->addObserver(NEW ACircleOfProtection(_id, card, Constants::MTG_COLOR_BLACK)); + break; + } + case 1336: //Circle of protection : blue + { + game->addObserver(NEW ACircleOfProtection(_id, card, Constants::MTG_COLOR_BLUE)); + break; + } + case 1337: //Circle of protection : green + { + game->addObserver(NEW ACircleOfProtection(_id, card, Constants::MTG_COLOR_GREEN)); + break; + } + case 1338: //Circle of protection : red + { + game->addObserver(NEW ACircleOfProtection(_id, card, Constants::MTG_COLOR_RED)); + break; + } + case 1339: //Circle of protection : white + { + game->addObserver(NEW ACircleOfProtection(_id, card, Constants::MTG_COLOR_WHITE)); + break; + } + case 1101: //clockwork Beast + { + game->addObserver(NEW AClockworkBeast(_id, card)); + break; + } + case 1102: //Conservator + { + game->addObserver(NEW AConservator(_id, card)); + break; + } + + case 1103: //Crystal Rod + { + int cost[] = { Constants::MTG_COLOR_ARTIFACT, 1 }; + ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_BLUE, NEW ManaCost(cost, 1), 1); + game->addObserver(ability); + break; + } + case 1152: //Deathlace + { + if (card->target) + { + card->target->setColor(Constants::MTG_COLOR_BLACK, 1); + } + else + { + Spell * starget = spell->getNextSpellTarget(); + starget->source->setColor(Constants::MTG_COLOR_BLACK, 1); + } + break; + } + case 1284: //Dragon Whelp + { + game->addObserver(NEW ADragonWhelp(_id, card)); + break; + } + + case 1345: //Farmstead + { + game->addObserver(NEW AFarmstead(_id, card, card->target)); + break; + } + case 1291: //Fireball + { + int x = computeX(spell, card); + game->addObserver(NEW AFireball(_id, card, spell, x)); + break; + } + case 1112: //Howling Mine + { + game->addObserver(NEW AHowlingMine(_id, card)); + break; + } + case 1113: //Iron Star + { + int cost[] = { Constants::MTG_COLOR_ARTIFACT, 1 }; + ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_RED, NEW ManaCost(cost, 1), 1); + game->addObserver(ability); + break; + } + case 1351: // Island Sanctuary + { + game->addObserver(NEW AIslandSanctuary(_id, card)); + break; + } + case 1114: //Ivory cup + { + int cost[] = { Constants::MTG_COLOR_ARTIFACT, 1 }; + ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_WHITE, NEW ManaCost(cost, 1), 1); + game->addObserver(ability); + break; + } + case 1117: //Jandors Ring + { + game->addObserver(NEW AJandorsRing(_id, card)); + break; + } + case 1121: //Kormus Bell + { + game->addObserver(NEW AConvertLandToCreatures(id, card, "swamp")); + break; + } + case 1254: //Kudzu + { + game->addObserver(NEW AKudzu(id, card, card->target)); + break; + } + case 1257: //Lifelace + { + if (card->target) + { + card->target->setColor(Constants::MTG_COLOR_GREEN, 1); + } + else + { + Spell * starget = spell->getNextSpellTarget(); + starget->source->setColor(Constants::MTG_COLOR_GREEN, 1); + } + break; + } + + case 1259: //Living lands + { + game->addObserver(NEW AConvertLandToCreatures(id, card, "forest")); + break; + } + case 1124: //Mana Vault (the rest is softcoded!) + { + game->addObserver(NEW ARegularLifeModifierAura(_id + 2, card, card, Constants::MTG_PHASE_DRAW, -1, 1)); + break; + } + case 1215: //Power Leak + { + game->addObserver(NEW APowerLeak(_id, card, card->target)); + break; + } + case 1358: //Purelace + { + if (card->target) + { + card->target->setColor(Constants::MTG_COLOR_WHITE, 1); + } + else + { + Spell * starget = spell->getNextSpellTarget(); + starget->source->setColor(Constants::MTG_COLOR_WHITE, 1); + } + break; + } + case 1312: //Red Elemental Blast + { + if (card->target) + { + card->target->controller()->game->putInGraveyard(card->target); + } + else + { + Spell * starget = spell->getNextSpellTarget(); + game->mLayers->stackLayer()->Fizzle(starget); + } + break; + } + + case 1139: //The Rack + { + game->addObserver(NEW ALifeZoneLink(_id, card, Constants::MTG_PHASE_UPKEEP, -3)); + break; + } + + case 1140: //Throne of Bone + { + int cost[] = { Constants::MTG_COLOR_ARTIFACT, 1 }; + ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_BLACK, NEW ManaCost(cost, 1), 1); + game->addObserver(ability); + break; + } + + case 1142: //Wooden Sphere + { + int cost[] = { Constants::MTG_COLOR_ARTIFACT, 1 }; + ASpellCastLife* ability = NEW ASpellCastLife(_id, card, Constants::MTG_COLOR_GREEN, NEW ManaCost(cost, 1), 1); + game->addObserver(ability); + break; + } + case 1143: //Animate Dead + { + AAnimateDead * a = NEW AAnimateDead(_id, card, card->target); + game->addObserver(a); + card->target = ((MTGCardInstance *) a->target); + break; + } + case 1156: //Drain Life + { + Damageable * target = spell->getNextDamageableTarget(); + int x = spell->cost->getConvertedCost() - 2; //TODO Fix that !!! + X should be only black mana, that needs to be checked ! + game->mLayers->stackLayer()->addDamage(card, target, x); + if (target->life < x) + x = target->life; + game->currentlyActing()->life += x; + break; + } + case 1159: //Erg Raiders + { + AErgRaiders* ability = NEW AErgRaiders(_id, card); + game->addObserver(ability); + break; + } + case 1202: //Hurkyl's Recall + { + Player * player = spell->getNextPlayerTarget(); + if (player) + { + for (int i = 0; i < 2; i++) + { + MTGInPlay * inplay = game->players[i]->game->inPlay; + for (int j = inplay->nb_cards - 1; j >= 0; j--) + { + MTGCardInstance * card = inplay->cards[j]; + if (card->owner == player && card->hasType("artifact")) + { + player->game->putInZone(card, inplay, player->game->hand); + } + } + } + } + break; + } + case 1165: //Hypnotic Specter + { + game->addObserver(NEW AHypnoticSpecter(_id, card)); + break; + } + case 1258: //Living Artifact + { + game->addObserver(NEW ALivingArtifact(_id, card, card->target)); + break; + } + case 1209: //Mana Short + { + Player * player = spell->getNextPlayerTarget(); + if (player) + { + MTGInPlay * inplay = player->game->inPlay; + for (int i = 0; i < inplay->nb_cards; i++) + { + MTGCardInstance * current = inplay->cards[i]; + if (current->hasType(Subtypes::TYPE_LAND)) + current->tap(); + } + player->getManaPool()->init(); + } + break; + } + case 1167: //Mind Twist + { + int xCost = computeX(spell, card); + for (int i = 0; i < xCost; i++) + { + game->opponent()->game->discardRandom(game->opponent()->game->hand, card); + } + break; + } + case 1172: //Pestilence + { + game->addObserver(NEW APestilence(_id, card)); + break; + } + + case 1176: //Sacrifice + { + ASacrifice * ability = NEW ASacrifice(_id, card, card->target); + game->addObserver(ability); + break; + } + case 1224: //Spell Blast + { + int x = computeX(spell, card); + Spell * starget = spell->getNextSpellTarget(); + if (starget) + { + if (starget->cost->getConvertedCost() <= x) + game->mLayers->stackLayer()->Fizzle(starget); + } + break; + } + case 1194: //Control Magic + { + game->addObserver(NEW AControlStealAura(_id, card, card->target)); + break; + } + case 1235: //Aspect of Wolf + { + game->addObserver(NEW AAspectOfWolf(_id, card, card->target)); + break; + } + case 1231: //Volcanic Eruption + { + int x = computeX(spell, card); + int _x = x; + MTGCardInstance * target = spell->getNextCardTarget(); + while (target && _x) + { + target->destroy(); + _x--; + target = spell->getNextCardTarget(target); + } + x -= _x; + for (int i = 0; i < 2; i++) + { + game->mLayers->stackLayer()->addDamage(card, game->players[i], x); + for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++) + { + MTGCardInstance * current = game->players[i]->game->inPlay->cards[j]; + if (current->isCreature()) + { + game->mLayers->stackLayer()->addDamage(card, current, x); + } + } + } + break; + } + case 1288: //EarthBind + { + game->addObserver(NEW AEarthbind(_id, card, card->target)); + break; + } + case 1344: //Eye for an Eye + { + Damage * damage = spell->getNextDamageTarget(); + if (damage) + { + game->mLayers->stackLayer()->addDamage(card, damage->source->controller(), damage->damage); + } + break; + } + case 1243: //Fastbond + { + game->addObserver(NEW AFastbond(_id, card)); + break; + } + case 1238: //Cockatrice + { + game->addObserver(NEW AOldSchoolDeathtouch(_id, card)); + break; + } + case 1225: //Stasis + { + game->addObserver(NEW AStasis(_id, card)); + break; + } + case 1267: //Thicket Basilic + { + game->addObserver(NEW AOldSchoolDeathtouch(_id, card)); + break; + } + case 1227: //Toughtlace + { + if (card->target) + { + card->target->setColor(Constants::MTG_COLOR_BLUE, 1); + } + else + { + Spell * starget = spell->getNextSpellTarget(); + starget->source->setColor(Constants::MTG_COLOR_BLUE, 1); + } + break; + } + + //Addons Legends + case 1533: //Livingplane + { + game->addObserver(NEW AConvertLandToCreatures(id, card, "land")); + break; + } + case 1480: //Energy Tap + { + card->target->tap(); + int mana = card->target->getManaCost()->getConvertedCost(); + game->currentlyActing()->getManaPool()->add(Constants::MTG_COLOR_ARTIFACT, mana); + } + + //Addons ICE-AGE Cards + + case 2474: //Minion of Leshrac + { + game->addObserver(NEW AMinionofLeshrac(_id, card)); + break; + } + + case 2732: //Kjeldoran Frostbeast + { + game->addObserver(NEW AKjeldoranFrostbeast(_id, card)); + break; + } + + // --- addon Mirage --- + + case 3410: //Seed of Innocence + { + GameObserver * game = GameObserver::GetInstance(); + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++) + { + MTGCardInstance * current = game->players[i]->game->inPlay->cards[j]; + if (current->hasType("Artifact")) + { + game->players[i]->game->putInGraveyard(current); + current->controller()->life += current->getManaCost()->getConvertedCost(); + } + } + } + break; + } + + //-- addon 10E--- + + case 129710: //Angelic Chorus + { + game->addObserver(NEW AAngelicChorus(_id, card)); + break; + } + + case 129767: //Threaten + { + game->addObserver(NEW AInstantControlSteal(_id, card, card->target)); + break; + } + case 130373: //Lavaborn Muse + { + game->addObserver(NEW ALavaborn(_id, card, Constants::MTG_PHASE_UPKEEP, -3, -3)); + break; + } + case 129774: // Traumatize + { + int nbcards; + Player * player = spell->getNextPlayerTarget(); + MTGLibrary * library = player->game->library; + nbcards = (library->nb_cards) / 2; + for (int i = 0; i < nbcards; i++) + { + if (library->nb_cards) + player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->graveyard); + } + break; + } + + case 135215: //Sylvan Basilisk + { + game->addObserver(NEW ABasilik(_id, card)); + break; + } + case 130553:// Beacon of Immortality + { + Player * player = spell->getNextPlayerTarget(); + if (player->life < (INT_MAX / 4)) + player->life += player->life; + zones->putInZone(card, spell->from, zones->library); + zones->library->shuffle(); + break; + } + case 135262:// Beacon of Destruction & unrest + { + zones->putInZone(card, spell->from, zones->library); + zones->library->shuffle(); + break; + } + case 129750: //Sudden Impact + { + Damageable * target = spell->getNextDamageableTarget(); + Player * p = spell->getNextPlayerTarget(); + MTGHand * hand = p->game->hand; + int damage = hand->nb_cards; + game->mLayers->stackLayer()->addDamage(card, target, damage); + break; + } + case 130369: // Soulblast + { + int damage = 0; + Damageable * target = spell->getNextDamageableTarget(); + for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j) + { + MTGCardInstance * current = card->controller()->game->inPlay->cards[j]; + if (current->hasType(Subtypes::TYPE_CREATURE)) + { + card->controller()->game->putInGraveyard(current); + damage += current->power; + } + } + game->mLayers->stackLayer()->addDamage(card, target, damage); + break; + } + + case 129698: // Reminisce + { + int nbcards; + Player * player = spell->getNextPlayerTarget(); + MTGLibrary * library = player->game->library; + MTGGraveyard * graveyard = player->game->graveyard; + nbcards = (graveyard->nb_cards); + for (int i = 0; i < nbcards; i++) + { + if (graveyard->nb_cards) + player->game->putInZone(graveyard->cards[graveyard->nb_cards - 1], graveyard, library); + } + library->shuffle(); + break; + } + + // --- addon Ravnica--- + + case 89114: //Psychic Drain + { + Player * player = spell->getNextPlayerTarget(); + MTGLibrary * library = player->game->library; + int x = computeX(spell, card); + for (int i = 0; i < x; i++) + { + if (library->nb_cards) + player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->graveyard); + } + game->currentlyActing()->life += x; + break; + } + + default: + break; + } + + /* We want to get rid of these basicAbility things. + * basicAbilities themselves are alright, but creating New object depending on them is dangerous + * The main reason is that classes that add an ability to a card do NOT create these objects, and therefore do NOT + * Work. + * For example, setting EXALTED for a creature is not enough right now... + * It shouldn't be necessary to add an object. State based abilities could do the trick + */ + + if (card->basicAbilities[Constants::EXALTED]) + { + game->addObserver(NEW AExalted(_id, card)); + } + + if (card->basicAbilities[Constants::FLANKING]) + { + game->addObserver(NEW AFlankerAbility(_id, card)); + } + + // Tested works the first r10 did not function because of the mistake in the array of the definition + if (card->basicAbilities[Constants::FORESTHOME]) + { + game->addObserver(NEW AStrongLandLinkCreature(_id, card, "forest")); + } + if (card->basicAbilities[Constants::ISLANDHOME]) + { + game->addObserver(NEW AStrongLandLinkCreature(_id, card, "island")); + } + if (card->basicAbilities[Constants::MOUNTAINHOME]) + { + game->addObserver(NEW AStrongLandLinkCreature(_id, card, "moutain")); + } + if (card->basicAbilities[Constants::SWAMPHOME]) + { + game->addObserver(NEW AStrongLandLinkCreature(_id, card, "swamp")); + } + if (card->basicAbilities[Constants::PLAINSHOME]) + { + game->addObserver(NEW AStrongLandLinkCreature(_id, card, "plains")); + } + + if (card->hasType("instant") || card->hasType("sorcery")) + { + MTGPlayerCards * zones = card->controller()->game; + if (card->boughtback > 0) + { + zones->putInZone(card, zones->stack, zones->hand); + } + else if (card->flashedback > 0) + { + zones->putInZone(card, zones->stack, zones->exile); + } + else + { + zones->putInZone(card, zones->stack, zones->graveyard); + } + } } - //mehods used in parseMagicLine() //ManaRedux -> manaredux(colorless,+2) // -> manaredux(green,-2) MTGAbility * AbilityFactory::getManaReduxAbility(string s, int id, Spell *spell, MTGCardInstance *card, MTGCardInstance *target) { - int color = -1; - string manaCost; - size_t endIndex = manaCost.find(")"); - if ( s.find( Constants::kManaColorless ) != string::npos) { - manaCost = s.substr( s.find(",")+ 1, endIndex ); - color = Constants::MTG_COLOR_ARTIFACT; - } - else if (s.find( Constants::kManaGreen ) != string::npos){ - manaCost = s.substr( s.find(",")+ 1, endIndex ); - color = Constants::MTG_COLOR_GREEN; - } - else if ( s.find( Constants::kManaBlue ) != string::npos){ - manaCost = s.substr( s.find(",")+ 1, endIndex ); - color = Constants::MTG_COLOR_BLUE; - } - else if ( s.find( Constants::kManaRed ) != string::npos){ - manaCost = s.substr( s.find(",") + 1, endIndex ); - color = Constants::MTG_COLOR_RED; - } - else if ( s.find( Constants::kManaBlack ) != string::npos){ - manaCost = s.substr( s.find(",")+ 1, endIndex ); - color = Constants::MTG_COLOR_BLACK; - } - else if ( s.find( Constants::kManaWhite ) != string::npos){ - manaCost = s.substr( s.find(",")+ 1, endIndex ); - color = Constants::MTG_COLOR_WHITE; - } - else - { - DebugTrace("An error has happened in creating a Mana Redux Ability! " << s ); - return NULL; - } - // figure out the mana cost - int amount = atoi(manaCost.c_str()); - return NEW AManaRedux(id, card, target, amount, color); + int color = -1; + string manaCost; + size_t endIndex = manaCost.find(")"); + if (s.find(Constants::kManaColorless) != string::npos) + { + manaCost = s.substr(s.find(",") + 1, endIndex); + color = Constants::MTG_COLOR_ARTIFACT; + } + else if (s.find(Constants::kManaGreen) != string::npos) + { + manaCost = s.substr(s.find(",") + 1, endIndex); + color = Constants::MTG_COLOR_GREEN; + } + else if (s.find(Constants::kManaBlue) != string::npos) + { + manaCost = s.substr(s.find(",") + 1, endIndex); + color = Constants::MTG_COLOR_BLUE; + } + else if (s.find(Constants::kManaRed) != string::npos) + { + manaCost = s.substr(s.find(",") + 1, endIndex); + color = Constants::MTG_COLOR_RED; + } + else if (s.find(Constants::kManaBlack) != string::npos) + { + manaCost = s.substr(s.find(",") + 1, endIndex); + color = Constants::MTG_COLOR_BLACK; + } + else if (s.find(Constants::kManaWhite) != string::npos) + { + manaCost = s.substr(s.find(",") + 1, endIndex); + color = Constants::MTG_COLOR_WHITE; + } + else + { + DebugTrace("An error has happened in creating a Mana Redux Ability! " << s ); + return NULL; + } + // figure out the mana cost + int amount = atoi(manaCost.c_str()); + return NEW AManaRedux(id, card, target, amount, color); } - - - -MTGAbility::MTGAbility(int id, MTGCardInstance * card):ActionElement(id){ - game = GameObserver::GetInstance(); - source = card; - target = card; - aType = MTGAbility::UNKNOWN; - cost = NULL; - forceDestroy = 0; - oneShot = 0; +MTGAbility::MTGAbility(int id, MTGCardInstance * card) : + ActionElement(id) +{ + game = GameObserver::GetInstance(); + source = card; + target = card; + aType = MTGAbility::UNKNOWN; + cost = NULL; + forceDestroy = 0; + oneShot = 0; } -MTGAbility::MTGAbility(int id, MTGCardInstance * _source,Targetable * _target ):ActionElement(id){ - game = GameObserver::GetInstance(); - source = _source; - target = _target; - aType = MTGAbility::UNKNOWN; - cost = NULL; - forceDestroy = 0; - oneShot = 0; +MTGAbility::MTGAbility(int id, MTGCardInstance * _source, Targetable * _target) : + ActionElement(id) +{ + game = GameObserver::GetInstance(); + source = _source; + target = _target; + aType = MTGAbility::UNKNOWN; + cost = NULL; + forceDestroy = 0; + oneShot = 0; } -int MTGAbility::stillInUse(MTGCardInstance * card){ - if (card==source || card==target) return 1; - return 0; +int MTGAbility::stillInUse(MTGCardInstance * card) +{ + if (card == source || card == target) + return 1; + return 0; } -MTGAbility::~MTGAbility(){ - if (!isClone){ - SAFE_DELETE(cost); - } +MTGAbility::~MTGAbility() +{ + if (!isClone) + { + SAFE_DELETE(cost); + } } -int MTGAbility::addToGame(){ - GameObserver::GetInstance()->addObserver(this); - return 1; +int MTGAbility::addToGame() +{ + GameObserver::GetInstance()->addObserver(this); + return 1; } -int MTGAbility::removeFromGame(){ - GameObserver::GetInstance()->removeObserver(this); - return 1; +int MTGAbility::removeFromGame() +{ + GameObserver::GetInstance()->removeObserver(this); + return 1; } //returns 1 if this ability needs to be removed from the list of active abilities -int MTGAbility::testDestroy(){ - if (game->mLayers->stackLayer()->has(this)) return 0; - if (waitingForAnswer) return 0; - if (forceDestroy == 1) return 1; - if (forceDestroy == -1) return 0; - if (!game->isInPlay(source) ) return 1; - if (target && !game->isInPlay((MTGCardInstance *)target)) return 1; - return 0; +int MTGAbility::testDestroy() +{ + if (game->mLayers->stackLayer()->has(this)) + return 0; + if (waitingForAnswer) + return 0; + if (forceDestroy == 1) + return 1; + if (forceDestroy == -1) + return 0; + if (!game->isInPlay(source)) + return 1; + if (target && !game->isInPlay((MTGCardInstance *) target)) + return 1; + return 0; } - - -int MTGAbility::fireAbility(){ - game->mLayers->stackLayer()->addAbility(this); - return 1; +int MTGAbility::fireAbility() +{ + game->mLayers->stackLayer()->addAbility(this); + return 1; } ostream& MTGAbility::toString(ostream& out) const { - return out << "MTGAbility ::: menuText : " << menuText - << " ; game : " << game - << " ; forceDestroy : " << forceDestroy - << " ; cost : " << cost - << " ; target : " << target - << " ; aType : " << aType - << " ; source : " << source; + return out << "MTGAbility ::: menuText : " << menuText << " ; game : " << game << " ; forceDestroy : " << forceDestroy + << " ; cost : " << cost << " ; target : " << target << " ; aType : " << aType << " ; source : " << source; } -NestedAbility::NestedAbility(MTGAbility * _ability){ - ability = _ability; +NestedAbility::NestedAbility(MTGAbility * _ability) +{ + ability = _ability; } // -ActivatedAbility::ActivatedAbility(int id, MTGCardInstance * card, ManaCost * _cost, int restrictions,int tap):MTGAbility(id,card), restrictions(restrictions), needsTapping(tap){ - cost = _cost; - abilityCost = 0; +ActivatedAbility::ActivatedAbility(int id, MTGCardInstance * card, ManaCost * _cost, int restrictions, int tap) : + MTGAbility(id, card), restrictions(restrictions), needsTapping(tap) +{ + cost = _cost; + abilityCost = 0; } - -int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - Player * player = game->currentlyActing(); - int cPhase = game->getCurrentGamePhase(); - switch(restrictions) { +int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + Player * player = game->currentlyActing(); + int cPhase = game->getCurrentGamePhase(); + switch (restrictions) + { case PLAYER_TURN_ONLY: - if (player != game->currentPlayer) return 0; - break; + if (player != game->currentPlayer) + return 0; + break; case AS_SORCERY: - if (player != game->currentPlayer) return 0; - if (cPhase != Constants::MTG_PHASE_FIRSTMAIN && cPhase != Constants::MTG_PHASE_SECONDMAIN) return 0; - break; - } - if (restrictions>= MY_BEFORE_BEGIN && restrictions <= MY_AFTER_EOT){ - if (player != game->currentPlayer) return 0; - if (cPhase != restrictions - MY_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) return 0; - } + if (player != game->currentPlayer) + return 0; + if (cPhase != Constants::MTG_PHASE_FIRSTMAIN && cPhase != Constants::MTG_PHASE_SECONDMAIN) + return 0; + break; + } + if (restrictions >= MY_BEFORE_BEGIN && restrictions <= MY_AFTER_EOT) + { + if (player != game->currentPlayer) + return 0; + if (cPhase != restrictions - MY_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + return 0; + } - if (restrictions>= OPPONENT_BEFORE_BEGIN && restrictions <= OPPONENT_AFTER_EOT){ - if (player == game->currentPlayer) return 0; - if (cPhase != restrictions - OPPONENT_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) return 0; - } + if (restrictions >= OPPONENT_BEFORE_BEGIN && restrictions <= OPPONENT_AFTER_EOT) + { + if (player == game->currentPlayer) + return 0; + if (cPhase != restrictions - OPPONENT_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + return 0; + } - if (restrictions>= BEFORE_BEGIN && restrictions <= AFTER_EOT){ - if (cPhase != restrictions - BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) return 0; - } + if (restrictions >= BEFORE_BEGIN && restrictions <= AFTER_EOT) + { + if (cPhase != restrictions - BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + return 0; + } + + if (card == source && source->controller() == player && (!needsTapping || (!source->isTapped() + && !source->hasSummoningSickness()))) + { + if (!cost) + return 1; + cost->setExtraCostsAction(this, card); + if (!mana) + mana = player->getManaPool(); + if (!mana->canAfford(cost)) + return 0; + if (!cost->canPayExtra()) + return 0; + return 1; + } + return 0; +} + +int ActivatedAbility::reactToClick(MTGCardInstance * card) +{ + // if (cost) cost->setExtraCostsAction(this, card); + if (!isReactingToClick(card)) + return 0; + Player * player = game->currentlyActing(); + if (cost) + { + if (!cost->isExtraPaymentSet()) + { + game->waitForExtraPayment = cost->extraCosts; + return 0; + } + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + game->currentlyActing()->getManaPool()->pay(cost); + cost->doPayExtra(); + SAFE_DELETE(abilityCost); + abilityCost = previousManaPool->Diff(player->getManaPool()); + delete previousManaPool; + } + if (needsTapping && source->isInPlay()) + source->tap(); + fireAbility(); - if (card == source && source->controller()==player && (!needsTapping || (!source->isTapped() && !source->hasSummoningSickness()))){ - if (!cost) return 1; - cost->setExtraCostsAction(this, card); - if (!mana) mana = player->getManaPool(); - if (!mana->canAfford(cost)) return 0; - if (!cost->canPayExtra()) return 0; return 1; - } - return 0; + } -int ActivatedAbility::reactToClick(MTGCardInstance * card){ -// if (cost) cost->setExtraCostsAction(this, card); - if (!isReactingToClick(card)) return 0; - Player * player = game->currentlyActing(); - if (cost){ - if (!cost->isExtraPaymentSet()){ - game->waitForExtraPayment = cost->extraCosts; - return 0; +int ActivatedAbility::reactToTargetClick(Targetable * object) +{ + if (!isReactingToTargetClick(object)) + return 0; + Player * player = game->currentlyActing(); + if (cost) + { + if (object->typeAsTarget() == TARGET_CARD) + cost->setExtraCostsAction(this, (MTGCardInstance *) object); + if (!cost->isExtraPaymentSet()) + { + game->waitForExtraPayment = cost->extraCosts; + return 0; + } + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + game->currentlyActing()->getManaPool()->pay(cost); + cost->doPayExtra(); + SAFE_DELETE(abilityCost); + abilityCost = previousManaPool->Diff(player->getManaPool()); + delete previousManaPool; } - ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - game->currentlyActing()->getManaPool()->pay(cost); - cost->doPayExtra(); - SAFE_DELETE(abilityCost); - abilityCost = previousManaPool->Diff(player->getManaPool()); - delete previousManaPool; - } - if (needsTapping && source->isInPlay()) source->tap(); - fireAbility(); - - return 1; + if (needsTapping && source->isInPlay()) + source->tap(); + fireAbility(); + return 1; } -int ActivatedAbility::reactToTargetClick(Targetable * object){ - if (!isReactingToTargetClick(object)) return 0; - Player * player = game->currentlyActing(); - if (cost){ - if (object->typeAsTarget() == TARGET_CARD) cost->setExtraCostsAction(this, (MTGCardInstance *) object); - if (!cost->isExtraPaymentSet()){ - game->waitForExtraPayment = cost->extraCosts; - return 0; - } - ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - game->currentlyActing()->getManaPool()->pay(cost); - cost->doPayExtra(); +ActivatedAbility::~ActivatedAbility() +{ + //Ok, this will probably lead to crashes, maybe with lord abilities involving "X" costs. + // If that's the case, we need to improve the clone() method of GenericActivatedAbility and GenericTargetAbility, I think + // Erwan 2004/04/25 + //if (!isClone){ SAFE_DELETE(abilityCost); - abilityCost = previousManaPool->Diff(player->getManaPool()); - delete previousManaPool; - } - if (needsTapping && source->isInPlay()) source->tap(); - fireAbility(); - return 1; - -} - -ActivatedAbility::~ActivatedAbility(){ - //Ok, this will probably lead to crashes, maybe with lord abilities involving "X" costs. - // If that's the case, we need to improve the clone() method of GenericActivatedAbility and GenericTargetAbility, I think - // Erwan 2004/04/25 - //if (!isClone){ - SAFE_DELETE(abilityCost); - //} + //} } ostream& ActivatedAbility::toString(ostream& out) const { - out << "ActivatedAbility ::: restrictions : " << restrictions - << " ; needsTapping : " << needsTapping - << " ("; - return MTGAbility::toString(out) << ")"; + out << "ActivatedAbility ::: restrictions : " << restrictions << " ; needsTapping : " << needsTapping << " ("; + return MTGAbility::toString(out) << ")"; } - -TargetAbility::TargetAbility(int id, MTGCardInstance * card, TargetChooser * _tc,ManaCost * _cost, int _playerturnonly,int tap):ActivatedAbility(id, card,_cost,_playerturnonly, tap), NestedAbility(NULL){ - tc = _tc; +TargetAbility::TargetAbility(int id, MTGCardInstance * card, TargetChooser * _tc, ManaCost * _cost, int _playerturnonly, int tap) : + ActivatedAbility(id, card, _cost, _playerturnonly, tap), NestedAbility(NULL) +{ + tc = _tc; } -TargetAbility::TargetAbility(int id, MTGCardInstance * card,ManaCost * _cost, int _playerturnonly,int tap):ActivatedAbility(id, card,_cost,_playerturnonly, tap), NestedAbility(NULL){ - tc = NULL; +TargetAbility::TargetAbility(int id, MTGCardInstance * card, ManaCost * _cost, int _playerturnonly, int tap) : + ActivatedAbility(id, card, _cost, _playerturnonly, tap), NestedAbility(NULL) +{ + tc = NULL; } - -int TargetAbility::reactToTargetClick(Targetable * object){ - if (object->typeAsTarget() == TARGET_CARD) return reactToClick((MTGCardInstance *)object); - if (waitingForAnswer){ - if (tc->toggleTarget(object) == TARGET_OK_FULL){ - waitingForAnswer = 0; - game->mLayers->actionLayer()->setCurrentWaitingAction(NULL); - return ActivatedAbility::reactToClick(source); - } - return 1; - } - return 0; -} - - -int TargetAbility::reactToClick(MTGCardInstance * card){ - if (!waitingForAnswer) { - if (isReactingToClick(card)){ - waitingForAnswer = 1; - game->mLayers->actionLayer()->setCurrentWaitingAction(this); - tc->initTargets(); - return 1; - } - }else{ - if (card == source && (tc->targetsReadyCheck() == TARGET_OK || tc->targetsReadyCheck() == TARGET_OK_FULL)){ - waitingForAnswer = 0; - game->mLayers->actionLayer()->setCurrentWaitingAction(NULL); - return ActivatedAbility::reactToClick(source); - }else{ - if (tc->toggleTarget(card) == TARGET_OK_FULL){ - int result = ActivatedAbility::reactToClick(source); - if (result) { - waitingForAnswer = 0; - game->mLayers->actionLayer()->setCurrentWaitingAction(NULL); +int TargetAbility::reactToTargetClick(Targetable * object) +{ + if (object->typeAsTarget() == TARGET_CARD) + return reactToClick((MTGCardInstance *) object); + if (waitingForAnswer) + { + if (tc->toggleTarget(object) == TARGET_OK_FULL) + { + waitingForAnswer = 0; + game->mLayers->actionLayer()->setCurrentWaitingAction(NULL); + return ActivatedAbility::reactToClick(source); } - return result; - } - return 1; + return 1; } - } - return 0; + return 0; } -void TargetAbility::Render(){ - //TODO ? +int TargetAbility::reactToClick(MTGCardInstance * card) +{ + if (!waitingForAnswer) + { + if (isReactingToClick(card)) + { + waitingForAnswer = 1; + game->mLayers->actionLayer()->setCurrentWaitingAction(this); + tc->initTargets(); + return 1; + } + } + else + { + if (card == source && (tc->targetsReadyCheck() == TARGET_OK || tc->targetsReadyCheck() == TARGET_OK_FULL)) + { + waitingForAnswer = 0; + game->mLayers->actionLayer()->setCurrentWaitingAction(NULL); + return ActivatedAbility::reactToClick(source); + } + else + { + if (tc->toggleTarget(card) == TARGET_OK_FULL) + { + int result = ActivatedAbility::reactToClick(source); + if (result) + { + waitingForAnswer = 0; + game->mLayers->actionLayer()->setCurrentWaitingAction(NULL); + } + return result; + } + return 1; + } + } + return 0; } - -int TargetAbility::resolve(){ - Targetable * t = tc->getNextTarget(); - if (t && ability){ - ManaCost * diff = abilityCost->Diff(cost); - source->X = diff->hasX(); - delete (diff); - ability->target = t; - if (ability->oneShot) return ability->resolve(); - MTGAbility * a = ability->clone(); - return a->addToGame(); - } - return 0; +void TargetAbility::Render() +{ + //TODO ? } -const char * TargetAbility::getMenuText(){ - if (ability) return ability->getMenuText(); - return ActivatedAbility::getMenuText(); +int TargetAbility::resolve() +{ + Targetable * t = tc->getNextTarget(); + if (t && ability) + { + ManaCost * diff = abilityCost->Diff(cost); + source->X = diff->hasX(); + delete (diff); + ability->target = t; + if (ability->oneShot) + return ability->resolve(); + MTGAbility * a = ability->clone(); + return a->addToGame(); + } + return 0; } -TargetAbility::~TargetAbility(){ - if (!isClone) SAFE_DELETE(ability); +const char * TargetAbility::getMenuText() +{ + if (ability) + return ability->getMenuText(); + return ActivatedAbility::getMenuText(); +} + +TargetAbility::~TargetAbility() +{ + if (!isClone) + SAFE_DELETE(ability); } ostream& TargetAbility::toString(ostream& out) const { - out << "TargetAbility ::: ("; - return ActivatedAbility::toString(out) << ")"; + out << "TargetAbility ::: ("; + return ActivatedAbility::toString(out) << ")"; } // -TriggeredAbility::TriggeredAbility(int id, MTGCardInstance * card, Targetable * _target):MTGAbility(id,card, _target){ +TriggeredAbility::TriggeredAbility(int id, MTGCardInstance * card, Targetable * _target) : + MTGAbility(id, card, _target) +{ } - -TriggeredAbility::TriggeredAbility(int id, MTGCardInstance * card):MTGAbility(id,card){ +TriggeredAbility::TriggeredAbility(int id, MTGCardInstance * card) : + MTGAbility(id, card) +{ } -int TriggeredAbility::receiveEvent(WEvent * e){ - if (triggerOnEvent(e)){ - fireAbility(); - return 1; - } - return 0; +int TriggeredAbility::receiveEvent(WEvent * e) +{ + if (triggerOnEvent(e)) + { + fireAbility(); + return 1; + } + return 0; } -void TriggeredAbility::Update(float dt){ - if (trigger()) fireAbility(); +void TriggeredAbility::Update(float dt) +{ + if (trigger()) + fireAbility(); } ostream& TriggeredAbility::toString(ostream& out) const { - out << "TriggeredAbility ::: ("; - return MTGAbility::toString(out) << ")"; + out << "TriggeredAbility ::: ("; + return MTGAbility::toString(out) << ")"; } - // -InstantAbility::InstantAbility(int _id, MTGCardInstance * source):MTGAbility(_id, source){ - init = 0; +InstantAbility::InstantAbility(int _id, MTGCardInstance * source) : + MTGAbility(_id, source) +{ + init = 0; } -void InstantAbility::Update(float dt){ - if (!init){ - init = resolve(); - } +void InstantAbility::Update(float dt) +{ + if (!init) + { + init = resolve(); + } } -InstantAbility::InstantAbility(int _id, MTGCardInstance * source, Damageable * _target):MTGAbility(_id, source, _target){ - init = 0; +InstantAbility::InstantAbility(int _id, MTGCardInstance * source, Damageable * _target) : + MTGAbility(_id, source, _target) +{ + init = 0; } - - //Instant abilities last generally until the end of the turn -int InstantAbility::testDestroy(){ - int newPhase = game->getCurrentGamePhase(); - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT) return 1; - currentPhase = newPhase; - return 0; +int InstantAbility::testDestroy() +{ + int newPhase = game->getCurrentGamePhase(); + if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT) + return 1; + currentPhase = newPhase; + return 0; } ostream& InstantAbility::toString(ostream& out) const { - out << "InstantAbility ::: init : " << init - << " ("; - return MTGAbility::toString(out) << ")"; + out << "InstantAbility ::: init : " << init << " ("; + return MTGAbility::toString(out) << ")"; } -bool ListMaintainerAbility::canTarget(MTGGameZone * zone){ - if (tc) return tc->targetsZone(zone); - for (int i = 0; i < 2; i++){ - Player * p = game->players[i]; - if (zone == p->game->inPlay) return true; - } - return false; +bool ListMaintainerAbility::canTarget(MTGGameZone * zone) +{ + if (tc) + return tc->targetsZone(zone); + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (zone == p->game->inPlay) + return true; + } + return false; } -void ListMaintainerAbility::updateTargets(){ - //remove invalid ones - map temp; - for (map::iterator it=cards.begin(); it != cards.end(); ++it){ - MTGCardInstance * card = (*it).first; - if (!canBeInList(card)) temp[card] = true; - } +void ListMaintainerAbility::updateTargets() +{ + //remove invalid ones + map temp; + for (map::iterator it = cards.begin(); it != cards.end(); ++it) + { + MTGCardInstance * card = (*it).first; + if (!canBeInList(card)) + temp[card] = true; + } - for (map::iterator it=temp.begin(); it != temp.end(); ++it){ - MTGCardInstance * card = (*it).first; - cards.erase(card); - removed(card); - } + for (map::iterator it = temp.begin(); it != temp.end(); ++it) + { + MTGCardInstance * card = (*it).first; + cards.erase(card); + removed(card); + } - temp.clear(); + temp.clear(); - //add New valid ones - for (int i = 0; i < 2; i++){ - Player * p = game->players[i]; - MTGGameZone * zones[] = {p->game->inPlay,p->game->graveyard,p->game->hand,p->game->library}; - for (int k = 0; k < 4; k++){ - MTGGameZone * zone = zones[k]; - if (canTarget(zone)){ - for (int j = 0; j < zone->nb_cards; j++){ - if (canBeInList(zone->cards[j])){ - if(cards.find(zone->cards[j]) == cards.end()){ - temp[zone->cards[j]] = true; + //add New valid ones + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library }; + for (int k = 0; k < 4; k++) + { + MTGGameZone * zone = zones[k]; + if (canTarget(zone)) + { + for (int j = 0; j < zone->nb_cards; j++) + { + if (canBeInList(zone->cards[j])) + { + if (cards.find(zone->cards[j]) == cards.end()) + { + temp[zone->cards[j]] = true; + } + } + } } - } } - } } - } - for (map::iterator it=temp.begin(); it != temp.end(); ++it){ - MTGCardInstance * card = (*it).first; - cards[card] = true; - added(card); - } - - temp.clear(); - - for (int i = 0; i < 2; ++i){ - Player * p = game->players[i]; - if (!players[p] && canBeInList(p)){ - players[p] = true; - added(p); - }else if (players[p] && !canBeInList(p)){ - players[p] = false; - removed(p); + for (map::iterator it = temp.begin(); it != temp.end(); ++it) + { + MTGCardInstance * card = (*it).first; + cards[card] = true; + added(card); + } + + temp.clear(); + + for (int i = 0; i < 2; ++i) + { + Player * p = game->players[i]; + if (!players[p] && canBeInList(p)) + { + players[p] = true; + added(p); + } + else if (players[p] && !canBeInList(p)) + { + players[p] = false; + removed(p); + } } - } } -void ListMaintainerAbility::Update(float dt){ - updateTargets(); +void ListMaintainerAbility::Update(float dt) +{ + updateTargets(); } //Destroy the spell -> remove all targets -int ListMaintainerAbility::destroy(){ - map::iterator it = cards.begin(); +int ListMaintainerAbility::destroy() +{ + map::iterator it = cards.begin(); - while ( it!=cards.end()){ - MTGCardInstance * card = (*it).first; - cards.erase(card); - removed(card); - it = cards.begin(); - } - return 1; + while (it != cards.end()) + { + MTGCardInstance * card = (*it).first; + cards.erase(card); + removed(card); + it = cards.begin(); + } + return 1; } ostream& ListMaintainerAbility::toString(ostream& out) const { - out << "ListMaintainerAbility ::: ("; - return MTGAbility::toString(out) << ")"; + out << "ListMaintainerAbility ::: ("; + return MTGAbility::toString(out) << ")"; } - - -TriggerAtPhase::TriggerAtPhase(int id, MTGCardInstance * source, Targetable * target,int _phaseId, int who):TriggeredAbility(id, source,target),phaseId(_phaseId),who(who){ - GameObserver * g = GameObserver::GetInstance(); - if (g) { - newPhase = g->getCurrentGamePhase(); - currentPhase = newPhase; - } +TriggerAtPhase::TriggerAtPhase(int id, MTGCardInstance * source, Targetable * target, int _phaseId, int who) : + TriggeredAbility(id, source, target), phaseId(_phaseId), who(who) +{ + GameObserver * g = GameObserver::GetInstance(); + if (g) + { + newPhase = g->getCurrentGamePhase(); + currentPhase = newPhase; + } } -int TriggerAtPhase::trigger(){ - if (testDestroy()) return 0; // http://code.google.com/p/wagic/issues/detail?id=426 - GameObserver * g = GameObserver::GetInstance(); - int result = 0; - if (currentPhase != newPhase && newPhase == phaseId){ - result = 0; - switch(who){ - case 1: - if(g->currentPlayer == source->controller()) result = 1; - break; - case -1: - if(g->currentPlayer != source->controller()) result = 1; - break; - case -2: - if(source->target) { - if (g->currentPlayer == source->target->controller()) result = 1; - }else { - if(g->currentPlayer == source->controller()) result = 1; +int TriggerAtPhase::trigger() +{ + if (testDestroy()) + return 0; // http://code.google.com/p/wagic/issues/detail?id=426 + GameObserver * g = GameObserver::GetInstance(); + int result = 0; + if (currentPhase != newPhase && newPhase == phaseId) + { + result = 0; + switch (who) + { + case 1: + if (g->currentPlayer == source->controller()) + result = 1; + break; + case -1: + if (g->currentPlayer != source->controller()) + result = 1; + break; + case -2: + if (source->target) + { + if (g->currentPlayer == source->target->controller()) + result = 1; + } + else + { + if (g->currentPlayer == source->controller()) + result = 1; + } + break; + default: + result = 1; + break; } - break; - default: - result = 1; - break; } - } - return result; + return result; } -TriggerAtPhase* TriggerAtPhase::clone() const{ - TriggerAtPhase * a = NEW TriggerAtPhase(*this); +TriggerAtPhase* TriggerAtPhase::clone() const +{ + TriggerAtPhase * a = NEW TriggerAtPhase(*this); a->isClone = 1; return a; } -TriggerNextPhase::TriggerNextPhase(int id, MTGCardInstance * source, Targetable * target,int _phaseId,int who):TriggerAtPhase(id, source,target,_phaseId, who){ - destroyActivated = 0; +TriggerNextPhase::TriggerNextPhase(int id, MTGCardInstance * source, Targetable * target, int _phaseId, int who) : + TriggerAtPhase(id, source, target, _phaseId, who) +{ + destroyActivated = 0; } -int TriggerNextPhase::testDestroy(){ - //dirty hack because of http://code.google.com/p/wagic/issues/detail?id=426 - if (newPhase <= phaseId && !destroyActivated) destroyActivated = 1; - if (destroyActivated > 1 || (newPhase > phaseId && destroyActivated)){ - destroyActivated++; - return 1; - } - return 0; +int TriggerNextPhase::testDestroy() +{ + //dirty hack because of http://code.google.com/p/wagic/issues/detail?id=426 + if (newPhase <= phaseId && !destroyActivated) + destroyActivated = 1; + if (destroyActivated > 1 || (newPhase > phaseId && destroyActivated)) + { + destroyActivated++; + return 1; + } + return 0; } -TriggerNextPhase* TriggerNextPhase::clone() const{ - TriggerNextPhase * a = NEW TriggerNextPhase(*this); +TriggerNextPhase* TriggerNextPhase::clone() const +{ + TriggerNextPhase * a = NEW TriggerNextPhase(*this); a->isClone = 1; return a; } -GenericTriggeredAbility::GenericTriggeredAbility(int id, MTGCardInstance * _source, TriggeredAbility * _t, MTGAbility * a , MTGAbility * dc, Targetable * _target ): TriggeredAbility(id, _source,_target), NestedAbility(a){ - if (!target) target = source; - t = _t; - destroyCondition = dc; +GenericTriggeredAbility::GenericTriggeredAbility(int id, MTGCardInstance * _source, TriggeredAbility * _t, MTGAbility * a, + MTGAbility * dc, Targetable * _target) : + TriggeredAbility(id, _source, _target), NestedAbility(a) +{ + if (!target) + target = source; + t = _t; + destroyCondition = dc; - t->source = source; - t->target = target; - ability->source = source; - ability->target = target; - if (destroyCondition){ - destroyCondition->source = source; - destroyCondition->target = target; - } + t->source = source; + t->target = target; + ability->source = source; + ability->target = target; + if (destroyCondition) + { + destroyCondition->source = source; + destroyCondition->target = target; + } } -int GenericTriggeredAbility::trigger(){ - return t->trigger(); +int GenericTriggeredAbility::trigger() +{ + return t->trigger(); } +int GenericTriggeredAbility::triggerOnEvent(WEvent * e) +{ + if (t->triggerOnEvent(e)) + { + targets.push(getTriggerTarget(e, ability)); + return 1; + } + return 0; +} -int GenericTriggeredAbility::triggerOnEvent(WEvent * e){ - if (t->triggerOnEvent(e)) { - targets.push(getTriggerTarget(e,ability)); +Targetable * GenericTriggeredAbility::getTriggerTarget(WEvent * e, MTGAbility * a) +{ + TriggerTargetChooser * ttc = dynamic_cast (a->tc); + if (ttc) + return e->getTarget(ttc->triggerTarget); + + NestedAbility * na = dynamic_cast (a); + if (na) + return getTriggerTarget(e, na->ability); + + MultiAbility * ma = dynamic_cast (a); + if (ma) + { + for (size_t i = 0; i < ma->abilities.size(); i++) + { + return getTriggerTarget(e, ma->abilities[i]); + } + } + + return NULL; +} + +void GenericTriggeredAbility::setTriggerTargets(Targetable * ta, MTGAbility * a) +{ + TriggerTargetChooser * ttc = dynamic_cast (a->tc); + if (ttc) + { + a->target = ta; + ttc->target = ta; + } + + NestedAbility * na = dynamic_cast (a); + if (na) + setTriggerTargets(ta, na->ability); + + MultiAbility * ma = dynamic_cast (a); + if (ma) + { + for (size_t i = 0; i < ma->abilities.size(); i++) + { + setTriggerTargets(ta, ma->abilities[i]); + } + } +} + +void GenericTriggeredAbility::Update(float dt) +{ + GameObserver * g = GameObserver::GetInstance(); + int newPhase = g->getCurrentGamePhase(); + t->newPhase = newPhase; + TriggeredAbility::Update(dt); + t->currentPhase = newPhase; +} + +int GenericTriggeredAbility::resolve() +{ + if (targets.size()) + { + setTriggerTargets(targets.front(), ability); + targets.pop(); + } + if (ability->oneShot) + return ability->resolve(); + MTGAbility * clone = ability->clone(); + clone->addToGame(); return 1; - } - return 0; } -Targetable * GenericTriggeredAbility::getTriggerTarget(WEvent * e,MTGAbility * a){ - TriggerTargetChooser * ttc = dynamic_cast(a->tc); - if (ttc) - return e->getTarget(ttc->triggerTarget); - - NestedAbility * na = dynamic_cast(a); - if (na) return getTriggerTarget(e,na->ability); +int GenericTriggeredAbility::testDestroy() +{ + if (!TriggeredAbility::testDestroy()) + return 0; + if (destroyCondition) + return (destroyCondition->testDestroy()); + return t->testDestroy(); +} - MultiAbility * ma = dynamic_cast(a); - if (ma) { - for (size_t i = 0; i < ma->abilities.size(); i++) { - return getTriggerTarget(e,ma->abilities[i]); +GenericTriggeredAbility::~GenericTriggeredAbility() +{ + if (!isClone) + { + delete t; + delete ability; + SAFE_DELETE(destroyCondition); } - } - - return NULL; } -void GenericTriggeredAbility::setTriggerTargets(Targetable * ta ,MTGAbility * a){ - TriggerTargetChooser * ttc = dynamic_cast(a->tc); - if (ttc) { - a->target = ta; - ttc->target = ta; - } - - NestedAbility * na = dynamic_cast(a); - if (na) setTriggerTargets(ta,na->ability); - - MultiAbility * ma = dynamic_cast(a); - if (ma) { - for (size_t i = 0; i < ma->abilities.size(); i++) { - setTriggerTargets(ta,ma->abilities[i]); - } - } +const char * GenericTriggeredAbility::getMenuText() +{ + return ability->getMenuText(); } -void GenericTriggeredAbility::Update(float dt){ - GameObserver * g = GameObserver::GetInstance(); - int newPhase = g->getCurrentGamePhase(); - t->newPhase = newPhase; - TriggeredAbility::Update(dt); - t->currentPhase = newPhase; -} - -int GenericTriggeredAbility::resolve(){ - if (targets.size()) { - setTriggerTargets(targets.front() ,ability); - targets.pop(); - } - if (ability->oneShot) return ability->resolve(); - MTGAbility * clone = ability->clone(); - clone->addToGame(); - return 1; -} - -int GenericTriggeredAbility::testDestroy(){ - if (!TriggeredAbility::testDestroy()) return 0; - if (destroyCondition) return (destroyCondition->testDestroy()); - return t->testDestroy(); -} - -GenericTriggeredAbility::~GenericTriggeredAbility(){ - if (!isClone){ - delete t; - delete ability; - SAFE_DELETE(destroyCondition); - } -} - - const char * GenericTriggeredAbility::getMenuText(){ - return ability->getMenuText(); - } - -GenericTriggeredAbility* GenericTriggeredAbility::clone() const{ +GenericTriggeredAbility* GenericTriggeredAbility::clone() const +{ GenericTriggeredAbility * a = NEW GenericTriggeredAbility(*this); a->isClone = 1; return a; } /*Mana Producers (lands) -//These have a reactToClick function, and therefore two manaProducers on the same card conflict with each other -//That means the player has to choose one. although that is perfect for cards such as birds of paradise or badlands, -other solutions need to be provided for abilities that add mana (ex: mana flare) -*/ + //These have a reactToClick function, and therefore two manaProducers on the same card conflict with each other + //That means the player has to choose one. although that is perfect for cards such as birds of paradise or badlands, + other solutions need to be provided for abilities that add mana (ex: mana flare) + */ +AManaProducer::AManaProducer(int id, MTGCardInstance * card, Targetable * t, ManaCost * _output, ManaCost * _cost, int doTap, + int who) : + ActivatedAbilityTP(id, card, t, _cost, doTap, who) +{ -AManaProducer::AManaProducer(int id, MTGCardInstance * card, Targetable * t, ManaCost * _output, ManaCost * _cost , int doTap, int who):ActivatedAbilityTP(id, card,t,_cost,doTap,who){ + aType = MTGAbility::MANA_PRODUCER; + cost = _cost; + output = _output; - aType = MTGAbility::MANA_PRODUCER; - cost = _cost; - output = _output; - - menutext = ""; + menutext = ""; } - int AManaProducer::isReactingToClick(MTGCardInstance * _card, ManaCost * mana){ +int AManaProducer::isReactingToClick(MTGCardInstance * _card, ManaCost * mana) +{ int result = 0; - if (!mana) mana = game->currentlyActing()->getManaPool(); - if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source) && (source->hasType(Subtypes::TYPE_LAND) || !tap || !source->hasSummoningSickness()) ){ - if (!cost || mana->canAfford(cost)) - { - result = 1; - } + if (!mana) + mana = game->currentlyActing()->getManaPool(); + if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source) + && (source->hasType(Subtypes::TYPE_LAND) || !tap || !source->hasSummoningSickness())) + { + if (!cost || mana->canAfford(cost)) + { + result = 1; + } } return result; - } +} - int AManaProducer::resolve(){ +int AManaProducer::resolve() +{ Targetable * _target = getTarget(); Player * player; - if (_target){ - if (_target->typeAsTarget() == TARGET_CARD){ - player = ((MTGCardInstance *)_target)->controller(); - }else{ - player = (Player *) _target; - } - player->getManaPool()->add(output,source); - return 1; + if (_target) + { + if (_target->typeAsTarget() == TARGET_CARD) + { + player = ((MTGCardInstance *) _target)->controller(); + } + else + { + player = (Player *) _target; + } + player->getManaPool()->add(output, source); + return 1; } return 0; - } +} - int AManaProducer::reactToClick(MTGCardInstance * _card){ - if (!isReactingToClick( _card)) return 0; - if (cost){ - cost->setExtraCostsAction(this, _card); - if (!cost->isExtraPaymentSet()){ - GameObserver::GetInstance()->waitForExtraPayment = cost->extraCosts; +int AManaProducer::reactToClick(MTGCardInstance * _card) +{ + if (!isReactingToClick(_card)) return 0; - } - GameObserver::GetInstance()->currentlyActing()->getManaPool()->pay(cost); - cost->doPayExtra(); + if (cost) + { + cost->setExtraCostsAction(this, _card); + if (!cost->isExtraPaymentSet()) + { + GameObserver::GetInstance()->waitForExtraPayment = cost->extraCosts; + return 0; + } + GameObserver::GetInstance()->currentlyActing()->getManaPool()->pay(cost); + cost->doPayExtra(); + } + if (tap) + { + GameObserver *g = GameObserver::GetInstance(); + WEvent * e = NEW WEventCardTappedForMana(source, 0, 1); + g->receiveEvent(e); + source->tap(); } - if (tap){ - GameObserver *g = GameObserver::GetInstance(); - WEvent * e = NEW WEventCardTappedForMana(source, 0, 1); - g->receiveEvent(e); - source->tap(); - } - if (options[Options::SFXVOLUME].number > 0){ - JSample * sample = resources.RetrieveSample("mana.wav"); - if (sample) JSoundSystem::GetInstance()->PlaySample(sample); + if (options[Options::SFXVOLUME].number > 0) + { + JSample * sample = resources.RetrieveSample("mana.wav"); + if (sample) + JSoundSystem::GetInstance()->PlaySample(sample); } return resolve(); - } +} - - const char * AManaProducer::getMenuText(){ - if (menutext.size())return menutext.c_str(); +const char * AManaProducer::getMenuText() +{ + if (menutext.size()) + return menutext.c_str(); menutext = _("Add "); char buffer[128]; int alreadyHasOne = 0; - for (int i= 0; i < 6; i++){ - int value = output->getCost(i); - if (value){ - if (alreadyHasOne) menutext.append(","); - sprintf(buffer, "%i ", value); - menutext.append(buffer); - switch (i){ - case Constants::MTG_COLOR_RED: - menutext.append(_("red")); - break; - case Constants::MTG_COLOR_BLUE: - menutext.append(_("blue")); - break; - case Constants::MTG_COLOR_GREEN: - menutext.append(_("green")); - break; - case Constants::MTG_COLOR_WHITE: - menutext.append(_("white")); - break; - case Constants::MTG_COLOR_BLACK: - menutext.append(_("black")); - break; - default: - break; + for (int i = 0; i < 6; i++) + { + int value = output->getCost(i); + if (value) + { + if (alreadyHasOne) + menutext.append(","); + sprintf(buffer, "%i ", value); + menutext.append(buffer); + switch (i) + { + case Constants::MTG_COLOR_RED: + menutext.append(_("red")); + break; + case Constants::MTG_COLOR_BLUE: + menutext.append(_("blue")); + break; + case Constants::MTG_COLOR_GREEN: + menutext.append(_("green")); + break; + case Constants::MTG_COLOR_WHITE: + menutext.append(_("white")); + break; + case Constants::MTG_COLOR_BLACK: + menutext.append(_("black")); + break; + default: + break; + } + alreadyHasOne = 1; } - alreadyHasOne = 1; - } } menutext.append(_(" mana")); return menutext.c_str(); - } +} - - AManaProducer::~AManaProducer(){ +AManaProducer::~AManaProducer() +{ SAFE_DELETE(cost); SAFE_DELETE(output); - } +} - AManaProducer * AManaProducer::clone() const{ - AManaProducer * a = NEW AManaProducer(*this); +AManaProducer * AManaProducer::clone() const +{ + AManaProducer * a = NEW AManaProducer(*this); a->cost = NEW ManaCost(); a->output = NEW ManaCost(); a->cost->copy(cost); a->output->copy(output); a->isClone = 1; return a; - } +} +ActivatedAbilityTP::ActivatedAbilityTP(int id, MTGCardInstance * card, Targetable * _target, ManaCost * cost, int doTap, int who) : + ActivatedAbility(id, card, cost, 0, doTap), who(who) +{ + if (_target) + target = _target; +} - - ActivatedAbilityTP::ActivatedAbilityTP(int id, MTGCardInstance * card, Targetable * _target, ManaCost * cost, int doTap, int who):ActivatedAbility(id,card,cost,0,doTap),who(who){ - if (_target) target = _target; - } - - Targetable * ActivatedAbilityTP::getTarget(){ - switch(who){ - case TargetChooser::TARGET_CONTROLLER: - if (target){ - switch(target->typeAsTarget()) { +Targetable * ActivatedAbilityTP::getTarget() +{ + switch (who) + { + case TargetChooser::TARGET_CONTROLLER: + if (target) + { + switch (target->typeAsTarget()) + { case TARGET_CARD: - return ((MTGCardInstance *)target)->controller(); + return ((MTGCardInstance *) target)->controller(); case TARGET_STACKACTION: - return((Interruptible *)target)->source->controller(); + return ((Interruptible *) target)->source->controller(); default: - return (Player *)target; - } + return (Player *) target; + } } return NULL; - case TargetChooser::CONTROLLER: + case TargetChooser::CONTROLLER: return source->controller(); - case TargetChooser::OPPONENT: + case TargetChooser::OPPONENT: return source->controller()->opponent(); - case TargetChooser::OWNER: - return source->owner; - default: + case TargetChooser::OWNER: + return source->owner; + default: return target; } - return NULL; - } + return NULL; +} diff --git a/projects/mtg/src/MTGCard.cpp b/projects/mtg/src/MTGCard.cpp index b68259e01..d3bc3ab2e 100644 --- a/projects/mtg/src/MTGCard.cpp +++ b/projects/mtg/src/MTGCard.cpp @@ -13,59 +13,72 @@ using std::string; -MTGCard::MTGCard(){ - init(); +MTGCard::MTGCard() +{ + init(); } -MTGCard::MTGCard(int set_id){ - init(); - setId = set_id; +MTGCard::MTGCard(int set_id) +{ + init(); + setId = set_id; } -MTGCard::MTGCard(MTGCard * source){ +MTGCard::MTGCard(MTGCard * source) +{ - strcpy(image_name, source->image_name); - rarity = source->rarity; - mtgid = source->mtgid; - setId = source->setId; - data = source->data; + strcpy(image_name, source->image_name); + rarity = source->rarity; + mtgid = source->mtgid; + setId = source->setId; + data = source->data; } -int MTGCard::init(){ - setId = 0; - mtgid = 0; - data = NULL; - rarity = Constants::RARITY_C; - return 1; +int MTGCard::init() +{ + setId = 0; + mtgid = 0; + data = NULL; + rarity = Constants::RARITY_C; + return 1; } - -void MTGCard::setMTGId(int id){ - mtgid = id; - if (id < 0){ - sprintf(image_name, "%dt.jpg", -mtgid); - }else{ - sprintf(image_name, "%d.jpg", mtgid); - } +void MTGCard::setMTGId(int id) +{ + mtgid = id; + if (id < 0) + { + sprintf(image_name, "%dt.jpg", -mtgid); + } + else + { + sprintf(image_name, "%d.jpg", mtgid); + } } -int MTGCard::getMTGId() const { - return mtgid; +int MTGCard::getMTGId() const +{ + return mtgid; } -int MTGCard::getId() const { - return mtgid; +int MTGCard::getId() const +{ + return mtgid; } -char MTGCard::getRarity() const { - return rarity; +char MTGCard::getRarity() const +{ + return rarity; } -void MTGCard::setRarity(char _rarity){ - rarity = _rarity; +void MTGCard::setRarity(char _rarity) +{ + rarity = _rarity; } -char * MTGCard::getImageName() { - return image_name; +char * MTGCard::getImageName() +{ + return image_name; } -void MTGCard::setPrimitive(CardPrimitive * cp){ - data = cp; +void MTGCard::setPrimitive(CardPrimitive * cp) +{ + data = cp; } diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 7996754c7..61697590e 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -1,9 +1,9 @@ /*--------------------------------------------- - Card Instance - Instance of a given MTGCard in the game - Although there is only one MTGCard of each type, there can be as much Instances of it as needed in the game - -------------------------------------------- -*/ + Card Instance + Instance of a given MTGCard in the game + Although there is only one MTGCard of each type, there can be as much Instances of it as needed in the game + -------------------------------------------- + */ #include "PrecompiledHeader.h" @@ -17,350 +17,415 @@ using namespace std; MTGCardInstance MTGCardInstance::AnyCard = MTGCardInstance(); MTGCardInstance MTGCardInstance::NoCard = MTGCardInstance(); -MTGCardInstance MTGCardInstance::ExtraRules[] = {MTGCardInstance(), MTGCardInstance()}; +MTGCardInstance MTGCardInstance::ExtraRules[] = { MTGCardInstance(), MTGCardInstance() }; - - -MTGCardInstance::MTGCardInstance(): CardPrimitive(), MTGCard(), Damageable(0), view(NULL){ - initMTGCI(); +MTGCardInstance::MTGCardInstance() : + CardPrimitive(), MTGCard(), Damageable(0), view(NULL) +{ + initMTGCI(); } -MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to): CardPrimitive(card->data),MTGCard(card), Damageable(card->data->getToughness()), view(NULL){ - initMTGCI(); - model = card; - attacker = 0; - lifeOrig = life; - belongs_to = arg_belongs_to; - owner = NULL; - if (arg_belongs_to) owner = arg_belongs_to->library->owner; - lastController = owner; - defenser = NULL; - banding = NULL; - life = toughness; - preventable = 0; - flanked = 0; +MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to) : + CardPrimitive(card->data), MTGCard(card), Damageable(card->data->getToughness()), view(NULL) +{ + initMTGCI(); + model = card; + attacker = 0; + lifeOrig = life; + belongs_to = arg_belongs_to; + owner = NULL; + if (arg_belongs_to) + owner = arg_belongs_to->library->owner; + lastController = owner; + defenser = NULL; + banding = NULL; + life = toughness; + preventable = 0; + flanked = 0; } -void MTGCardInstance::copy(MTGCardInstance * card){ - MTGCard * source = card->model; - CardPrimitive * data = source->data; - for(map::const_iterator it = data->basicAbilities.begin(); it != data->basicAbilities.end(); ++it){ - int i = it->first; - basicAbilities[i] = data->basicAbilities[i]; - } - for (size_t i = 0; i< data->types.size(); i++){ - types.push_back(data->types[i]); - } - for (int i = 0; i< Constants::MTG_NB_COLORS; i++){ - colors[i] = data->colors[i]; - } - manaCost.copy(data->getManaCost()); +void MTGCardInstance::copy(MTGCardInstance * card) +{ + MTGCard * source = card->model; + CardPrimitive * data = source->data; + for (map::const_iterator it = data->basicAbilities.begin(); it != data->basicAbilities.end(); ++it) + { + int i = it->first; + basicAbilities[i] = data->basicAbilities[i]; + } + for (size_t i = 0; i < data->types.size(); i++) + { + types.push_back(data->types[i]); + } + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + colors[i] = data->colors[i]; + } + manaCost.copy(data->getManaCost()); - text = data->text; - setName(data->name); + text = data->text; + setName(data->name); - power = data->power; - toughness = data->toughness; - life = toughness; - lifeOrig = life; + power = data->power; + toughness = data->toughness; + life = toughness; + lifeOrig = life; - magicText = data->magicText; - spellTargetType = data->spellTargetType; - alias = data->alias; + magicText = data->magicText; + spellTargetType = data->spellTargetType; + alias = data->alias; - //Now this is dirty... - int backupid = mtgid; - mtgid = source->getId(); - Spell * spell = NEW Spell(this); - AbilityFactory af; - GameObserver * g = GameObserver::GetInstance(); - af.addAbilities(g->mLayers->actionLayer()->getMaxId(), spell); - delete spell; - mtgid = backupid; + //Now this is dirty... + int backupid = mtgid; + mtgid = source->getId(); + Spell * spell = NEW Spell(this); + AbilityFactory af; + GameObserver * g = GameObserver::GetInstance(); + af.addAbilities(g->mLayers->actionLayer()->getMaxId(), spell); + delete spell; + mtgid = backupid; } -MTGCardInstance::~MTGCardInstance(){ - SAFE_DELETE(counters); - SAFE_DELETE(previous); +MTGCardInstance::~MTGCardInstance() +{ + SAFE_DELETE(counters); + SAFE_DELETE(previous); } -int MTGCardInstance::init(){ - MTGCard::init(); - CardPrimitive::init(); - data = this; - X = 0; - XX = 0; - return 1; -} - -void MTGCardInstance::initMTGCI(){ - sample = ""; - model=NULL; - isToken = false; - lifeOrig = 0; - doDamageTest = 1; - belongs_to=NULL; - tapped = 0; - untapping = 0; - frozen = 0; - fresh = 0; - didattacked = 0; - didblocked = 0; - notblocked = 0; - sunburst = NULL; - equipment = NULL; - boughtback = 0; - flashedback = 0; - paymenttype = 0; - reduxamount = 0; - summoningSickness = 1; - preventable = 0; - flanked = 0; - target = NULL; - type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE; - banding = NULL; - owner = NULL; - counters = NEW Counters(this); - previousZone = NULL; - previous = NULL; - next = NULL; - lastController = NULL; - regenerateTokens = 0; - blocked = false; - currentZone = NULL; - data = this; //an MTGCardInstance point to itself for data, allows to update it without killing the underlying database item - - if(basicAbilities[Constants::CHANGELING]){//if the card is a changeling. - for(int i=Subtypes::LAST_TYPE+1;;i++){ - string s = Subtypes::subtypesList->find(i); - if(!hasSubtype(i)) - { - if(s == "") break; - if(s.find(" ") != string::npos) continue; - if(s == "Nothing" || s == "Swamp" || s == "Plains" || s == "Mountain" || s == "Forest" || s == "Island" || s == "Shrine" || s == "Basic" || s == "Colony" || s == "Desert" || s == "Dismiss" || s == "Equipment" - || s == "Everglades" || s == "Grasslands" || s == "Lair" || s == "Level" || s == "Levelup" || s == "Mine" || s == "Oasis" || s == "World" || s == "Aura") continue; - addType(i); - } - } - } - -} - - -const string MTGCardInstance::getDisplayName() const { - return getName(); -} - -void MTGCardInstance::addType(int type){ - bool before = hasType(type); - CardPrimitive::addType(type); - WEvent * e = NEW WEventCardChangeType(this,type,before,true); - GameObserver * go = GameObserver::GetInstance(); - if(go) go->receiveEvent(e); - else SAFE_DELETE(e); -} - -void MTGCardInstance::addType(char * type_text){ - setSubtype(type_text); -} - -void MTGCardInstance::setType(const char * type_text){ - setSubtype(type_text); -} - -void MTGCardInstance::setSubtype(string value){ - int id = Subtypes::subtypesList->find(value); - addType(id); -} -int MTGCardInstance::removeType(string value,int removeAll){ - int id = Subtypes::subtypesList->find(value); - return removeType(id,removeAll); -} - -int MTGCardInstance::removeType(int id, int removeAll){ - bool before = hasType(id); - int result = CardPrimitive::removeType(id,removeAll); - bool after = hasType(id); - WEvent * e = NEW WEventCardChangeType(this,id,before,after); - GameObserver * go = GameObserver::GetInstance(); - if(go) go->receiveEvent(e); - else SAFE_DELETE(e); - return result; -} - -int MTGCardInstance::isInPlay(){ - GameObserver * game = GameObserver::GetInstance(); - for (int i = 0 ; i < 2 ; i++){ - MTGGameZone * zone = game->players[i]->game->inPlay; - if (zone->hasCard(this)) return 1; - } - return 0; -} - -int MTGCardInstance::afterDamage(){ - if (!doDamageTest) return 0; - doDamageTest = 0; - if (!isCreature()) return 0; - if (life <=0 && isInPlay()){ - return destroy(); - } - return 0; -} - -int MTGCardInstance::bury(){ - Player * p = controller(); - if (basicAbilities[Constants::EXILEDEATH]){ - p->game->putInZone(this,p->game->inPlay,owner->game->exile); +int MTGCardInstance::init() +{ + MTGCard::init(); + CardPrimitive::init(); + data = this; + X = 0; + XX = 0; return 1; - } - if (!basicAbilities[Constants::INDESTRUCTIBLE]){ - p->game->putInZone(this,p->game->inPlay,owner->game->graveyard); - return 1; - } - return 0; } -int MTGCardInstance::destroy(){ - if (!triggerRegenerate()) return bury(); + +void MTGCardInstance::initMTGCI() +{ + sample = ""; + model = NULL; + isToken = false; + lifeOrig = 0; + doDamageTest = 1; + belongs_to = NULL; + tapped = 0; + untapping = 0; + frozen = 0; + fresh = 0; + didattacked = 0; + didblocked = 0; + notblocked = 0; + sunburst = NULL; + equipment = NULL; + boughtback = 0; + flashedback = 0; + paymenttype = 0; + reduxamount = 0; + summoningSickness = 1; + preventable = 0; + flanked = 0; + target = NULL; + type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE; + banding = NULL; + owner = NULL; + counters = NEW Counters(this); + previousZone = NULL; + previous = NULL; + next = NULL; + lastController = NULL; + regenerateTokens = 0; + blocked = false; + currentZone = NULL; + data = this; //an MTGCardInstance point to itself for data, allows to update it without killing the underlying database item + + if (basicAbilities[Constants::CHANGELING]) + {//if the card is a changeling. + for (int i = Subtypes::LAST_TYPE + 1;; i++) + { + string s = Subtypes::subtypesList->find(i); + if (!hasSubtype(i)) + { + if (s == "") + break; + if (s.find(" ") != string::npos) + continue; + if (s == "Nothing" || s == "Swamp" || s == "Plains" || s == "Mountain" || s == "Forest" || + s == "Island" || s == "Shrine" || s == "Basic" || s == "Colony" || s == "Desert" || + s == "Dismiss" || s == "Equipment" || s == "Everglades" || s == "Grasslands" || s == "Lair" || + s == "Level" || s == "Levelup" || s == "Mine" || s == "Oasis" || s == "World" || s == "Aura" + ) + continue; + + addType(i); + } + } + } + +} + +const string MTGCardInstance::getDisplayName() const +{ + return getName(); +} + +void MTGCardInstance::addType(int type) +{ + bool before = hasType(type); + CardPrimitive::addType(type); + WEvent * e = NEW WEventCardChangeType(this, type, before, true); + GameObserver * go = GameObserver::GetInstance(); + if (go) + go->receiveEvent(e); + else + SAFE_DELETE(e); +} + +void MTGCardInstance::addType(char * type_text) +{ + setSubtype(type_text); +} + +void MTGCardInstance::setType(const char * type_text) +{ + setSubtype(type_text); +} + +void MTGCardInstance::setSubtype(string value) +{ + int id = Subtypes::subtypesList->find(value); + addType(id); +} +int MTGCardInstance::removeType(string value, int removeAll) +{ + int id = Subtypes::subtypesList->find(value); + return removeType(id, removeAll); +} + +int MTGCardInstance::removeType(int id, int removeAll) +{ + bool before = hasType(id); + int result = CardPrimitive::removeType(id, removeAll); + bool after = hasType(id); + WEvent * e = NEW WEventCardChangeType(this, id, before, after); + GameObserver * go = GameObserver::GetInstance(); + if (go) + go->receiveEvent(e); + else + SAFE_DELETE(e); + return result; +} + +int MTGCardInstance::isInPlay() +{ + GameObserver * game = GameObserver::GetInstance(); + for (int i = 0; i < 2; i++) + { + MTGGameZone * zone = game->players[i]->game->inPlay; + if (zone->hasCard(this)) + return 1; + } return 0; } -MTGGameZone * MTGCardInstance::getCurrentZone(){ - return currentZone; +int MTGCardInstance::afterDamage() +{ + if (!doDamageTest) + return 0; + doDamageTest = 0; + if (!isCreature()) + return 0; + if (life <= 0 && isInPlay()) + { + return destroy(); + } + return 0; } -int MTGCardInstance::has(int basicAbility){ - return basicAbilities[basicAbility]; +int MTGCardInstance::bury() +{ + Player * p = controller(); + if (basicAbilities[Constants::EXILEDEATH]) + { + p->game->putInZone(this, p->game->inPlay, owner->game->exile); + return 1; + } + if (!basicAbilities[Constants::INDESTRUCTIBLE]) + { + p->game->putInZone(this, p->game->inPlay, owner->game->graveyard); + return 1; + } + return 0; +} +int MTGCardInstance::destroy() +{ + if (!triggerRegenerate()) + return bury(); + return 0; } +MTGGameZone * MTGCardInstance::getCurrentZone() +{ + return currentZone; +} + +int MTGCardInstance::has(int basicAbility) +{ + return basicAbilities[basicAbility]; +} //sets card as attacked and sends events -void MTGCardInstance::eventattacked(){ - didattacked = 1; - WEvent * e = NEW WEventCardAttacked(this); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); +void MTGCardInstance::eventattacked() +{ + didattacked = 1; + WEvent * e = NEW WEventCardAttacked(this); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); } //sets card as attacked alone and sends events -void MTGCardInstance::eventattackedAlone(){ - WEvent * e = NEW WEventCardAttackedAlone(this); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); +void MTGCardInstance::eventattackedAlone() +{ + WEvent * e = NEW WEventCardAttackedAlone(this); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); } //sets card as attacked and sends events -void MTGCardInstance::eventattackednotblocked(){ - didattacked = 1; - WEvent * e = NEW WEventCardAttackedNotBlocked(this); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); +void MTGCardInstance::eventattackednotblocked() +{ + didattacked = 1; + WEvent * e = NEW WEventCardAttackedNotBlocked(this); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); } //sets card as attacked and sends events -void MTGCardInstance::eventattackedblocked(){ - didattacked = 1; - WEvent * e = NEW WEventCardAttackedBlocked(this); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); +void MTGCardInstance::eventattackedblocked() +{ + didattacked = 1; + WEvent * e = NEW WEventCardAttackedBlocked(this); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); } //sets card as blocking and sends events -void MTGCardInstance::eventblocked(){ - didblocked = 1; - WEvent * e = NEW WEventCardBlocked(this); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); +void MTGCardInstance::eventblocked() +{ + didblocked = 1; + WEvent * e = NEW WEventCardBlocked(this); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); } - //Taps the card -void MTGCardInstance::tap(){ - if (tapped) return; - tapped = 1; - WEvent * e = NEW WEventCardTap(this, 0, 1); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); +void MTGCardInstance::tap() +{ + if (tapped) + return; + tapped = 1; + WEvent * e = NEW WEventCardTap(this, 0, 1); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); } -void MTGCardInstance::untap(){ - if (!tapped) return; - tapped = 0; - WEvent * e = NEW WEventCardTap(this, 1, 0); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); +void MTGCardInstance::untap() +{ + if (!tapped) + return; + tapped = 0; + WEvent * e = NEW WEventCardTap(this, 1, 0); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); } - -void MTGCardInstance::setUntapping(){ - untapping = 1; +void MTGCardInstance::setUntapping() +{ + untapping = 1; } -int MTGCardInstance::isUntapping(){ - return untapping; +int MTGCardInstance::isUntapping() +{ + return untapping; } //Tries to Untap the card -void MTGCardInstance::attemptUntap(){ - if (untapping){ - untap(); - untapping = 0; - } +void MTGCardInstance::attemptUntap() +{ + if (untapping) + { + untap(); + untapping = 0; + } } //Tells if the card is tapped or not -int MTGCardInstance::isTapped(){ - return tapped; +int MTGCardInstance::isTapped() +{ + return tapped; } -int MTGCardInstance::regenerate(){ - if (has(Constants::CANTREGEN)) return 0; - return ++regenerateTokens; +int MTGCardInstance::regenerate() +{ + if (has(Constants::CANTREGEN)) + return 0; + return ++regenerateTokens; } -int MTGCardInstance::triggerRegenerate(){ - if (! regenerateTokens) return 0; - if (has(Constants::CANTREGEN)) return 0; - regenerateTokens--; - tap(); - life = toughness; - initAttackersDefensers(); - if (life < 1) return 0; //regeneration didn't work (wither ?) - return 1; +int MTGCardInstance::triggerRegenerate() +{ + if (!regenerateTokens) + return 0; + if (has(Constants::CANTREGEN)) + return 0; + regenerateTokens--; + tap(); + life = toughness; + initAttackersDefensers(); + if (life < 1) + return 0; //regeneration didn't work (wither ?) + return 1; } - -int MTGCardInstance::initAttackersDefensers(){ - setAttacker(0); - setDefenser(NULL); - banding = NULL; - blockers.clear(); - blocked = false; - didattacked = 0; - didblocked = 0; - return 1; +int MTGCardInstance::initAttackersDefensers() +{ + setAttacker(0); + setDefenser(NULL); + banding = NULL; + blockers.clear(); + blocked = false; + didattacked = 0; + didblocked = 0; + return 1; } //Function to call to remove all damages, etc to a card (generally at the end of the turn) -int MTGCardInstance::cleanup(){ - initAttackersDefensers(); - life=toughness; - GameObserver * game = GameObserver::GetInstance(); - if (!game || game->currentPlayer == controller()) - { - summoningSickness = 0; - } - if (previous && !previous->stillInUse()){ - SAFE_DELETE(previous); - } - regenerateTokens = 0; - preventable = 0; - return 1; +int MTGCardInstance::cleanup() +{ + initAttackersDefensers(); + life = toughness; + GameObserver * game = GameObserver::GetInstance(); + if (!game || game->currentPlayer == controller()) + { + summoningSickness = 0; + } + if (previous && !previous->stillInUse()) + { + SAFE_DELETE(previous); + } + regenerateTokens = 0; + preventable = 0; + return 1; } -int MTGCardInstance::stillInUse(){ -GameObserver * game = GameObserver::GetInstance(); -if (game->mLayers->actionLayer()->stillInUse(this)) return 1; -if (!previous) return 0; -return previous->stillInUse(); +int MTGCardInstance::stillInUse() +{ + GameObserver * game = GameObserver::GetInstance(); + if (game->mLayers->actionLayer()->stillInUse(this)) + return 1; + if (!previous) + return 0; + return previous->stillInUse(); } /* Summoning Sickness @@ -370,401 +435,529 @@ return previous->stillInUse(); * since the start of his or her most recent turn. This rule is informally called the "summoning * sickness" rule. Ignore this rule for creatures with haste (see rule 502.5). */ -int MTGCardInstance::hasSummoningSickness(){ - if (!summoningSickness) return 0; - if (basicAbilities[Constants::HASTE]) return 0; - if (!isCreature()) return 0; - return 1; -} - -MTGCardInstance * MTGCardInstance::changeController(Player * newController){ - Player * originalOwner = controller(); - if (originalOwner == newController) return this; - MTGCardInstance * copy = originalOwner->game->putInZone(this, originalOwner->game->inPlay, newController->game->inPlay); - copy->summoningSickness = 1; - return copy; -} - -Player * MTGCardInstance::controller(){ - return lastController; -} - -int MTGCardInstance::canAttack(){ - if (tapped) return 0; - if (hasSummoningSickness()) return 0; - if (basicAbilities[Constants::DEFENSER] || basicAbilities[Constants::CANTATTACK]) return 0; - if (!isCreature()) return 0; - if (!isInPlay()) return 0; - return 1; -} - - -int MTGCardInstance::addToToughness(int value){ - toughness+=value; - life+=value; - doDamageTest = 1; - return 1; -} - -int MTGCardInstance::setToughness(int value){ - toughness=value; - life=value; - doDamageTest = 1; - return 1; -} - -int MTGCardInstance::canBlock(){ - if (tapped) return 0; - if (basicAbilities[Constants::CANTBLOCK]) return 0; - if (!isCreature()) return 0; - if (!isInPlay()) return 0; - return 1; -} - -int MTGCardInstance::canBlock(MTGCardInstance * opponent){ - if (!canBlock()) return 0; - if (!opponent) return 1; - if (!opponent->isAttacker()) return 0; - // Comprehensive rule 502.7f : If a creature with protection attacks, it can't be blocked by creatures that have the stated quality. - if (opponent->protectedAgainst(this)) return 0; - if (opponent->cantBeBlockedBy(this)) return 0; - if (opponent->basicAbilities[Constants::UNBLOCKABLE]) return 0; - if (opponent->basicAbilities[Constants::ONEBLOCKER] && opponent->blocked) return 0; - if (opponent->basicAbilities[Constants::FEAR] && !(hasType(Subtypes::TYPE_ARTIFACT) || hasColor(Constants::MTG_COLOR_BLACK))) return 0; - - //intimidate - if (opponent->basicAbilities[Constants::INTIMIDATE] && !(hasType(Subtypes::TYPE_ARTIFACT))){ - int canblock = 0; - for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i){ - if(hasColor(i) && opponent->hasColor(i)){ - canblock = 1; - break; - } - } - if (!canblock) return 0; - } - - if (opponent->basicAbilities[Constants::FLYING] && !( basicAbilities[Constants::FLYING] || basicAbilities[Constants::REACH])) return 0; - //Can block only creatures with flying if has cloud - if (basicAbilities[Constants::CLOUD] && !( opponent->basicAbilities[Constants::FLYING])) return 0; - // If opponent has shadow and a creature does not have either shadow or reachshadow it cannot be blocked - if (opponent->basicAbilities[Constants::SHADOW] && !( basicAbilities[Constants::SHADOW] || basicAbilities[Constants::REACHSHADOW])) return 0; - // If opponent does not have shadow and a creature has shadow it cannot be blocked - if (!opponent->basicAbilities[Constants::SHADOW] && basicAbilities[Constants::SHADOW]) return 0; - if (opponent->basicAbilities[Constants::HORSEMANSHIP] && !basicAbilities[Constants::HORSEMANSHIP]) return 0; - if (opponent->basicAbilities[Constants::SWAMPWALK] && controller()->game->inPlay->hasType("swamp")) return 0; - if (opponent->basicAbilities[Constants::FORESTWALK] && controller()->game->inPlay->hasType("forest")) return 0; - if (opponent->basicAbilities[Constants::ISLANDWALK] && controller()->game->inPlay->hasType("island")) return 0; - if (opponent->basicAbilities[Constants::MOUNTAINWALK] && controller()->game->inPlay->hasType("mountain")) return 0; - if (opponent->basicAbilities[Constants::PLAINSWALK] && controller()->game->inPlay->hasType("plains")) return 0; - return 1; -} - -JQuad * MTGCardInstance::getIcon(){ - return resources.RetrieveCard(this,CACHE_THUMB); -} - -MTGCardInstance * MTGCardInstance::getNextPartner(){ - MTGInPlay * inplay = controller()->game->inPlay; - MTGCardInstance * bandingPartner = inplay->getNextAttacker(banding); - while (bandingPartner){ - if (basicAbilities[Constants::BANDING] || bandingPartner->basicAbilities[Constants::BANDING]) return bandingPartner; - bandingPartner = inplay->getNextAttacker(bandingPartner); - } - return NULL; -} - -int MTGCardInstance::DangerRanking(){ - int danger; - int result; -danger = 0; -result = 0; -result += power; -result += toughness; -result += getManaCost()->getConvertedCost(); - for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ - if(basicAbilities[j]) - { - result += 1; - } - } - if(result > 1) danger += 1; - if(result > 2) danger += 1; - if(result > 4) danger += 1; - if(result > 6) danger += 1; - if(result > 10) danger += 1; - return danger; -} - -int MTGCardInstance::setAttacker(int value){ - Targetable * previousTarget = NULL; - Targetable * target = NULL; - Player * p = controller()->opponent(); - if (value) target = p; - if (attacker) previousTarget = p; - attacker = value; - WEvent * e = NEW WEventCreatureAttacker(this,previousTarget, target); - GameObserver * go = GameObserver::GetInstance(); - if(go) go->receiveEvent(e); - else SAFE_DELETE(e); - return 1; -} - -int MTGCardInstance::toggleAttacker(){ - if (!attacker){ - //if (!basicAbilities[Constants::VIGILANCE]) tap(); - setAttacker(1); +int MTGCardInstance::hasSummoningSickness() +{ + if (!summoningSickness) + return 0; + if (basicAbilities[Constants::HASTE]) + return 0; + if (!isCreature()) + return 0; return 1; - }else{ - //untap(); - setAttacker(0); - return 1; - } - return 0; } -int MTGCardInstance::isAttacker(){ - return attacker; +MTGCardInstance * MTGCardInstance::changeController(Player * newController) +{ + Player * originalOwner = controller(); + if (originalOwner == newController) + return this; + MTGCardInstance * copy = originalOwner->game->putInZone(this, originalOwner->game->inPlay, newController->game->inPlay); + copy->summoningSickness = 1; + return copy; } -MTGCardInstance * MTGCardInstance::isDefenser(){ - return defenser; +Player * MTGCardInstance::controller() +{ + return lastController; } - -int MTGCardInstance::nbOpponents(){ - int result= 0; - MTGCardInstance* opponent = getNextOpponent(); - while (opponent){ - result++; - opponent = getNextOpponent(opponent); - } - return result; +int MTGCardInstance::canAttack() +{ + if (tapped) + return 0; + if (hasSummoningSickness()) + return 0; + if (basicAbilities[Constants::DEFENSER] || basicAbilities[Constants::CANTATTACK]) + return 0; + if (!isCreature()) + return 0; + if (!isInPlay()) + return 0; + return 1; } -int MTGCardInstance::raiseBlockerRankOrder(MTGCardInstance * blocker){ - list::iterator it1 = find(blockers.begin(), blockers.end(), blocker); - list::iterator it2 = it1; - if (blockers.begin() == it2) ++it2; else --it2; - - std::iter_swap(it1,it2); - WEvent* e = NEW WEventCreatureBlockerRank(*it1,*it2,this); - GameObserver * go = GameObserver::GetInstance(); - if(go) go->receiveEvent(e); - else SAFE_DELETE(e); - //delete(e); - return 1; +int MTGCardInstance::addToToughness(int value) +{ + toughness += value; + life += value; + doDamageTest = 1; + return 1; } -int MTGCardInstance::getDefenserRank(MTGCardInstance * blocker){ - int result = 0; - for(list::iterator it1 = blockers.begin(); it1 != blockers.end(); ++it1){ - result++; - if ((*it1) == blocker) return result; - } - return 0; -}; - -int MTGCardInstance::removeBlocker(MTGCardInstance * blocker){ - blockers.remove(blocker); - if (!blockers.size()){ - blocked = false; - } - return 1; +int MTGCardInstance::setToughness(int value) +{ + toughness = value; + life = value; + doDamageTest = 1; + return 1; } -int MTGCardInstance::addBlocker(MTGCardInstance * blocker){ - blockers.push_back(blocker); - blocked = true; - return 1; +int MTGCardInstance::canBlock() +{ + if (tapped) + return 0; + if (basicAbilities[Constants::CANTBLOCK]) + return 0; + if (!isCreature()) + return 0; + if (!isInPlay()) + return 0; + return 1; +} + +int MTGCardInstance::canBlock(MTGCardInstance * opponent) +{ + if (!canBlock()) + return 0; + if (!opponent) + return 1; + if (!opponent->isAttacker()) + return 0; + // Comprehensive rule 502.7f : If a creature with protection attacks, it can't be blocked by creatures that have the stated quality. + if (opponent->protectedAgainst(this)) + return 0; + if (opponent->cantBeBlockedBy(this)) + return 0; + if (opponent->basicAbilities[Constants::UNBLOCKABLE]) + return 0; + if (opponent->basicAbilities[Constants::ONEBLOCKER] && opponent->blocked) + return 0; + if (opponent->basicAbilities[Constants::FEAR] && !(hasType(Subtypes::TYPE_ARTIFACT) || hasColor(Constants::MTG_COLOR_BLACK))) + return 0; + + //intimidate + if (opponent->basicAbilities[Constants::INTIMIDATE] && !(hasType(Subtypes::TYPE_ARTIFACT))) + { + int canblock = 0; + for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i) + { + if (hasColor(i) && opponent->hasColor(i)) + { + canblock = 1; + break; + } + } + if (!canblock) + return 0; + } + + if (opponent->basicAbilities[Constants::FLYING] && !(basicAbilities[Constants::FLYING] || basicAbilities[Constants::REACH])) + return 0; + //Can block only creatures with flying if has cloud + if (basicAbilities[Constants::CLOUD] && !(opponent->basicAbilities[Constants::FLYING])) + return 0; + // If opponent has shadow and a creature does not have either shadow or reachshadow it cannot be blocked + if (opponent->basicAbilities[Constants::SHADOW] && !(basicAbilities[Constants::SHADOW] + || basicAbilities[Constants::REACHSHADOW])) + return 0; + // If opponent does not have shadow and a creature has shadow it cannot be blocked + if (!opponent->basicAbilities[Constants::SHADOW] && basicAbilities[Constants::SHADOW]) + return 0; + if (opponent->basicAbilities[Constants::HORSEMANSHIP] && !basicAbilities[Constants::HORSEMANSHIP]) + return 0; + if (opponent->basicAbilities[Constants::SWAMPWALK] && controller()->game->inPlay->hasType("swamp")) + return 0; + if (opponent->basicAbilities[Constants::FORESTWALK] && controller()->game->inPlay->hasType("forest")) + return 0; + if (opponent->basicAbilities[Constants::ISLANDWALK] && controller()->game->inPlay->hasType("island")) + return 0; + if (opponent->basicAbilities[Constants::MOUNTAINWALK] && controller()->game->inPlay->hasType("mountain")) + return 0; + if (opponent->basicAbilities[Constants::PLAINSWALK] && controller()->game->inPlay->hasType("plains")) + return 0; + return 1; +} + +JQuad * MTGCardInstance::getIcon() +{ + return resources.RetrieveCard(this, CACHE_THUMB); +} + +MTGCardInstance * MTGCardInstance::getNextPartner() +{ + MTGInPlay * inplay = controller()->game->inPlay; + MTGCardInstance * bandingPartner = inplay->getNextAttacker(banding); + while (bandingPartner) + { + if (basicAbilities[Constants::BANDING] || bandingPartner->basicAbilities[Constants::BANDING]) + return bandingPartner; + bandingPartner = inplay->getNextAttacker(bandingPartner); + } + return NULL; +} + +int MTGCardInstance::DangerRanking() +{ + int danger; + int result; + danger = 0; + result = 0; + result += power; + result += toughness; + result += getManaCost()->getConvertedCost(); + for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++) + { + if (basicAbilities[j]) + { + result += 1; + } + } + if (result > 1) + danger += 1; + if (result > 2) + danger += 1; + if (result > 4) + danger += 1; + if (result > 6) + danger += 1; + if (result > 10) + danger += 1; + return danger; +} + +int MTGCardInstance::setAttacker(int value) +{ + Targetable * previousTarget = NULL; + Targetable * target = NULL; + Player * p = controller()->opponent(); + if (value) + target = p; + if (attacker) + previousTarget = p; + attacker = value; + WEvent * e = NEW WEventCreatureAttacker(this, previousTarget, target); + GameObserver * go = GameObserver::GetInstance(); + if (go) + go->receiveEvent(e); + else + SAFE_DELETE(e); + return 1; +} + +int MTGCardInstance::toggleAttacker() +{ + if (!attacker) + { + //if (!basicAbilities[Constants::VIGILANCE]) tap(); + setAttacker(1); + return 1; + } + else + { + //untap(); + setAttacker(0); + return 1; + } + return 0; +} + +int MTGCardInstance::isAttacker() +{ + return attacker; +} + +MTGCardInstance * MTGCardInstance::isDefenser() +{ + return defenser; +} + +int MTGCardInstance::nbOpponents() +{ + int result = 0; + MTGCardInstance* opponent = getNextOpponent(); + while (opponent) + { + result++; + opponent = getNextOpponent(opponent); + } + return result; +} + +int MTGCardInstance::raiseBlockerRankOrder(MTGCardInstance * blocker) +{ + list::iterator it1 = find(blockers.begin(), blockers.end(), blocker); + list::iterator it2 = it1; + if (blockers.begin() == it2) + ++it2; + else + --it2; + + std::iter_swap(it1, it2); + WEvent* e = NEW WEventCreatureBlockerRank(*it1, *it2, this); + GameObserver * go = GameObserver::GetInstance(); + if (go) + go->receiveEvent(e); + else + SAFE_DELETE(e); + //delete(e); + return 1; +} + +int MTGCardInstance::getDefenserRank(MTGCardInstance * blocker) +{ + int result = 0; + for (list::iterator it1 = blockers.begin(); it1 != blockers.end(); ++it1) + { + result++; + if ((*it1) == blocker) + return result; + } + return 0; +} +; + +int MTGCardInstance::removeBlocker(MTGCardInstance * blocker) +{ + blockers.remove(blocker); + if (!blockers.size()) + { + blocked = false; + } + return 1; +} + +int MTGCardInstance::addBlocker(MTGCardInstance * blocker) +{ + blockers.push_back(blocker); + blocked = true; + return 1; } //Returns opponents to this card for this turn. This * should * take into account banding -MTGCardInstance * MTGCardInstance::getNextOpponent(MTGCardInstance * previous){ - GameObserver * game = GameObserver::GetInstance(); - int foundprevious = 0; - if (!previous) foundprevious = 1; - if (attacker){ - MTGInPlay * inPlay = game->opponent()->game->inPlay; - for (int i = 0; i < inPlay->nb_cards; i ++){ - MTGCardInstance * current = inPlay->cards[i]; - if (current == previous){ - foundprevious = 1; - }else if (foundprevious){ - MTGCardInstance * defensersOpponent = current->isDefenser(); - if (defensersOpponent && (defensersOpponent == this || (banding && defensersOpponent->banding == banding))){ - return current; - } - } +MTGCardInstance * MTGCardInstance::getNextOpponent(MTGCardInstance * previous) +{ + GameObserver * game = GameObserver::GetInstance(); + int foundprevious = 0; + if (!previous) + foundprevious = 1; + if (attacker) + { + MTGInPlay * inPlay = game->opponent()->game->inPlay; + for (int i = 0; i < inPlay->nb_cards; i++) + { + MTGCardInstance * current = inPlay->cards[i]; + if (current == previous) + { + foundprevious = 1; + } + else if (foundprevious) + { + MTGCardInstance * defensersOpponent = current->isDefenser(); + if (defensersOpponent && (defensersOpponent == this || (banding && defensersOpponent->banding == banding))) + { + return current; + } + } + } } - }else if (defenser){ - MTGInPlay * inPlay = game->currentPlayer->game->inPlay; - for (int i = 0; i < inPlay->nb_cards; i ++){ - MTGCardInstance * current = inPlay->cards[i]; - if (current == previous){ - foundprevious = 1; - }else if (foundprevious){ - if (defenser == current || (current->banding && defenser->banding == current->banding)){ - return current; - } - } + else if (defenser) + { + MTGInPlay * inPlay = game->currentPlayer->game->inPlay; + for (int i = 0; i < inPlay->nb_cards; i++) + { + MTGCardInstance * current = inPlay->cards[i]; + if (current == previous) + { + foundprevious = 1; + } + else if (foundprevious) + { + if (defenser == current || (current->banding && defenser->banding == current->banding)) + { + return current; + } + } + } } - } - return NULL; + return NULL; } - - -int MTGCardInstance::setDefenser(MTGCardInstance * opponent){ - GameObserver * g = GameObserver::GetInstance(); - if (defenser) { - if (g->players[0]->game->battlefield->hasCard(defenser) || - g->players[1]->game->battlefield->hasCard(defenser) ) { - defenser->removeBlocker(this); +int MTGCardInstance::setDefenser(MTGCardInstance * opponent) +{ + GameObserver * g = GameObserver::GetInstance(); + if (defenser) + { + if (g->players[0]->game->battlefield->hasCard(defenser) || g->players[1]->game->battlefield->hasCard(defenser)) + { + defenser->removeBlocker(this); + } } - } - WEvent * e = NULL; - if (defenser != opponent) e = NEW WEventCreatureBlocker(this, defenser, opponent); - defenser = opponent; - if (defenser) defenser->addBlocker(this); - if (e) g->receiveEvent(e); - return 1; + WEvent * e = NULL; + if (defenser != opponent) + e = NEW WEventCreatureBlocker(this, defenser, opponent); + defenser = opponent; + if (defenser) + defenser->addBlocker(this); + if (e) + g->receiveEvent(e); + return 1; } -int MTGCardInstance::toggleDefenser(MTGCardInstance * opponent){ - if (canBlock()){ - if (canBlock(opponent)){ - setDefenser(opponent); - didblocked = 1; - if(opponent && opponent->controller()->isAI()){ - opponent->view->actZ += .8f; - opponent->view->actT -= .2f; - } - if(!opponent) didblocked = 0; - return 1; - } - } - return 0; -} - -int MTGCardInstance::addProtection(TargetChooser * tc){ - tc->targetter = NULL; - protections.push_back(tc); - return protections.size(); -} - -int MTGCardInstance::removeProtection(TargetChooser * tc, int erase){ - for (size_t i = 0; i < protections.size() ; i++){ - if (protections[i] == tc){ - if (erase) delete (protections[i]); - protections.erase(protections.begin()+i); - return 1; +int MTGCardInstance::toggleDefenser(MTGCardInstance * opponent) +{ + if (canBlock()) + { + if (canBlock(opponent)) + { + setDefenser(opponent); + didblocked = 1; + if (opponent && opponent->controller()->isAI()) + { + opponent->view->actZ += .8f; + opponent->view->actT -= .2f; + } + if (!opponent) + didblocked = 0; + return 1; + } } - } - return 0; + return 0; } -int MTGCardInstance::protectedAgainst(MTGCardInstance * card){ - //Basic protections - for (int i=Constants::PROTECTIONGREEN; i <= Constants::PROTECTIONWHITE; i++){ - if (basicAbilities[i] && card->hasColor( i - Constants::PROTECTIONGREEN + Constants::MTG_COLOR_GREEN )) return 1; - } - - //General protections - for (size_t i = 0; i < protections.size() ; i++){ - if (protections[i]->canTarget(card)) - return 1; - } - return 0; +int MTGCardInstance::addProtection(TargetChooser * tc) +{ + tc->targetter = NULL; + protections.push_back(tc); + return protections.size(); } - -int MTGCardInstance::addCantBeBlockedBy(TargetChooser * tc){ - cantBeBlockedBys.push_back(tc); - return cantBeBlockedBys.size(); -} - -int MTGCardInstance::removeCantBeBlockedBy(TargetChooser * tc, int erase){ - for (size_t i = 0; i < cantBeBlockedBys.size() ; i++){ - if (cantBeBlockedBys[i] == tc){ - if (erase) delete (cantBeBlockedBys[i]); - cantBeBlockedBys.erase(cantBeBlockedBys.begin()+i); - return 1; +int MTGCardInstance::removeProtection(TargetChooser * tc, int erase) +{ + for (size_t i = 0; i < protections.size(); i++) + { + if (protections[i] == tc) + { + if (erase) + delete (protections[i]); + protections.erase(protections.begin() + i); + return 1; + } } - } - return 0; + return 0; } -int MTGCardInstance::cantBeBlockedBy(MTGCardInstance * card){ - for (size_t i = 0; i < cantBeBlockedBys.size() ; i++){ - if (cantBeBlockedBys[i]->canTarget(card)) - return 1; - } - return 0; +int MTGCardInstance::protectedAgainst(MTGCardInstance * card) +{ + //Basic protections + for (int i = Constants::PROTECTIONGREEN; i <= Constants::PROTECTIONWHITE; i++) + { + if (basicAbilities[i] && card->hasColor(i - Constants::PROTECTIONGREEN + Constants::MTG_COLOR_GREEN)) + return 1; + } + + //General protections + for (size_t i = 0; i < protections.size(); i++) + { + if (protections[i]->canTarget(card)) + return 1; + } + return 0; } +int MTGCardInstance::addCantBeBlockedBy(TargetChooser * tc) +{ + cantBeBlockedBys.push_back(tc); + return cantBeBlockedBys.size(); +} +int MTGCardInstance::removeCantBeBlockedBy(TargetChooser * tc, int erase) +{ + for (size_t i = 0; i < cantBeBlockedBys.size(); i++) + { + if (cantBeBlockedBys[i] == tc) + { + if (erase) + delete (cantBeBlockedBys[i]); + cantBeBlockedBys.erase(cantBeBlockedBys.begin() + i); + return 1; + } + } + return 0; +} + +int MTGCardInstance::cantBeBlockedBy(MTGCardInstance * card) +{ + for (size_t i = 0; i < cantBeBlockedBys.size(); i++) + { + if (cantBeBlockedBys[i]->canTarget(card)) + return 1; + } + return 0; +} /* Choose a sound sample to associate to that card */ -JSample * MTGCardInstance::getSample(){ - JSample * js; +JSample * MTGCardInstance::getSample() +{ + JSample * js; - if(sample.size()) - return resources.RetrieveSample(sample); + if (sample.size()) + return resources.RetrieveSample(sample); - for (int i = types.size()-1; i>0; i--){ - string type = Subtypes::subtypesList->find(types[i]); + for (int i = types.size() - 1; i > 0; i--) + { + string type = Subtypes::subtypesList->find(types[i]); + type = type + ".wav"; + js = resources.RetrieveSample(type); + if (js) + { + sample = string(type); + return js; + } + } + + for (map::const_iterator it = basicAbilities.begin(); it != basicAbilities.end(); ++it) + { + int i = it->first; + if (!basicAbilities[i]) + continue; + string type = Constants::MTGBasicAbilities[i]; + type = type + ".wav"; + js = resources.RetrieveSample(type); + if (js) + { + sample = string(type); + return js; + } + } + + string type = Subtypes::subtypesList->find(types[0]); type = type + ".wav"; js = resources.RetrieveSample(type); - if (js){ - sample = string(type); - return js; + if (js) + { + sample = string(type); + return js; } - } - for(map::const_iterator it = basicAbilities.begin(); it != basicAbilities.end(); ++it){ - int i = it->first; - if (!basicAbilities[i]) continue; - string type = Constants::MTGBasicAbilities[i]; - type = type + ".wav"; - js = resources.RetrieveSample(type); - if (js){ - sample = string(type); - return js; - } - } - - string type = Subtypes::subtypesList->find(types[0]); - type = type + ".wav"; - js = resources.RetrieveSample(type); - if (js){ - sample = string(type); - return js; - } - - return NULL; + return NULL; } int MTGCardInstance::stepPower(CombatStep step) { - switch (step) + switch (step) { - case FIRST_STRIKE : - case END_FIRST_STRIKE : - if (has(Constants::FIRSTSTRIKE) || has(Constants::DOUBLESTRIKE)) return MAX(0, power); else return 0; - case DAMAGE : - case END_DAMAGE : - default : - if (has(Constants::FIRSTSTRIKE) && !has(Constants::DOUBLESTRIKE)) return 0; else return MAX(0, power); + case FIRST_STRIKE: + case END_FIRST_STRIKE: + if (has(Constants::FIRSTSTRIKE) || has(Constants::DOUBLESTRIKE)) + return MAX(0, power); + else + return 0; + case DAMAGE: + case END_DAMAGE: + default: + if (has(Constants::FIRSTSTRIKE) && !has(Constants::DOUBLESTRIKE)) + return 0; + else + return MAX(0, power); } } std::ostream& MTGCardInstance::toString(std::ostream& out) const { - return out << name; + return out << name; } std::ostream& operator<<(std::ostream& out, const MTGCardInstance& c) { - return c.toString(out); + return c.toString(out); } diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index c9423eac4..b30dd0982 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -10,993 +10,1211 @@ #include "MTGPack.h" #include "utils.h" - #if defined (WIN32) || defined (LINUX) #include #endif - -static inline int getGrade(int v) { - switch (v) { - case 'P': case 'p': return Constants::GRADE_SUPPORTED; - case 'R': case 'r': return Constants::GRADE_BORDERLINE; - case 'O': case 'o': return Constants::GRADE_UNOFFICIAL; - case 'A': case 'a': return Constants::GRADE_CRAPPY; - case 'S': case 's': return Constants::GRADE_UNSUPPORTED; - case 'N': case 'n': return Constants::GRADE_DANGEROUS; - } - return 0; +static inline int getGrade(int v) +{ + switch (v) + { + case 'P': + case 'p': + return Constants::GRADE_SUPPORTED; + case 'R': + case 'r': + return Constants::GRADE_BORDERLINE; + case 'O': + case 'o': + return Constants::GRADE_UNOFFICIAL; + case 'A': + case 'a': + return Constants::GRADE_CRAPPY; + case 'S': + case 's': + return Constants::GRADE_UNSUPPORTED; + case 'N': + case 'n': + return Constants::GRADE_DANGEROUS; + } + return 0; } - //MTGAllCards -int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primitive){ - if ('#' == s[0]) return 0; - size_t i = s.find_first_of('='); - if (i == string::npos || 0 == i){ - DebugTrace("MTGDECK: Bad Line:\n\t" << s); - return 0; - } +int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primitive) +{ + if ('#' == s[0]) + return 0; + size_t i = s.find_first_of('='); + if (i == string::npos || 0 == i) + { + DebugTrace("MTGDECK: Bad Line:\n\t" << s); + return 0; + } - char* key = const_cast(s.c_str()); // I know what I'm doing, let me do it - key[i] = 0; - char* val = key + i + 1; + char* key = const_cast (s.c_str()); // I know what I'm doing, let me do it + key[i] = 0; + char* val = key + i + 1; - switch (key[0]) { + switch (key[0]) + { case 'a': - if (0 == strcmp("auto", key)) { - if (!primitive) primitive = NEW CardPrimitive(); - primitive->addMagicText(val); - } else if (0 == strncmp("auto", key, 4)) { - if (!primitive) primitive = NEW CardPrimitive(); - primitive->addMagicText(val, key + 4); - } else if (0 == strcmp("alias", key)) { - if (!primitive) primitive = NEW CardPrimitive(); - primitive->alias = atoi(val); - } else if (0 == strcmp("abilities", key)) { - if (!primitive) primitive = NEW CardPrimitive(); - string value = val; - //Specific Abilities - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - while (value.size()) { - string attribute; - size_t found2 = value.find(','); - if (found2 != string::npos){ - attribute = value.substr(0, found2); - value = value.substr(found2 + 1); - } else { - attribute = value; - value = ""; - } - for (int j = Constants::NB_BASIC_ABILITIES-1; j >= 0 ; --j) { - size_t found = attribute.find(Constants::MTGBasicAbilities[j]); - if (found != string::npos){ - primitive->basicAbilities[j] = 1; - break; + if (0 == strcmp("auto", key)) + { + if (!primitive) + primitive = NEW CardPrimitive(); + primitive->addMagicText(val); + } + else if (0 == strncmp("auto", key, 4)) + { + if (!primitive) + primitive = NEW CardPrimitive(); + primitive->addMagicText(val, key + 4); + } + else if (0 == strcmp("alias", key)) + { + if (!primitive) + primitive = NEW CardPrimitive(); + primitive->alias = atoi(val); + } + else if (0 == strcmp("abilities", key)) + { + if (!primitive) + primitive = NEW CardPrimitive(); + string value = val; + //Specific Abilities + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + while (value.size()) + { + string attribute; + size_t found2 = value.find(','); + if (found2 != string::npos) + { + attribute = value.substr(0, found2); + value = value.substr(found2 + 1); + } + else + { + attribute = value; + value = ""; + } + for (int j = Constants::NB_BASIC_ABILITIES - 1; j >= 0; --j) + { + size_t found = attribute.find(Constants::MTGBasicAbilities[j]); + if (found != string::npos) + { + primitive->basicAbilities[j] = 1; + break; + } + } } - } } - } - break; + break; - case 'c': //color - if (!primitive) primitive = NEW CardPrimitive(); - { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - vector values = split(value, ','); - int removeAllOthers = 1; - for (size_t values_i = 0; values_i < values.size(); ++values_i) { - primitive->setColor(values[values_i], removeAllOthers); - removeAllOthers = 0; + case 'c': //color + if (!primitive) + primitive = NEW CardPrimitive(); + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + vector values = split(value, ','); + int removeAllOthers = 1; + for (size_t values_i = 0; values_i < values.size(); ++values_i) + { + primitive->setColor(values[values_i], removeAllOthers); + removeAllOthers = 0; + } } - } - break; + break; case 'g': //grade - if (s.size() - i - 1 > 2) currentGrade = getGrade(val[2]); - break; + if (s.size() - i - 1 > 2) + currentGrade = getGrade(val[2]); + break; case 'k': //kicker - if (!primitive) primitive = NEW CardPrimitive(); - if (ManaCost * cost = primitive->getManaCost()) - { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - cost->kicker = ManaCost::parseManaCost(value); - } - break; - case 'o': //othercost - if (!primitive) primitive = NEW CardPrimitive(); - if (ManaCost * cost = primitive->getManaCost()) - { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - cost->alternative = ManaCost::parseManaCost(value); - } - break; - case 'b': //buyback - if (!primitive) primitive = NEW CardPrimitive(); - if (ManaCost * cost = primitive->getManaCost()) - { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - cost->BuyBack = ManaCost::parseManaCost(value); - } - break; - case 'f': //flashback - if (!primitive) primitive = NEW CardPrimitive(); - if (ManaCost * cost = primitive->getManaCost()) - { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - cost->FlashBack = ManaCost::parseManaCost(value); - } - break; - - case 'i': //id - if (!card) card = NEW MTGCard(); - card->setMTGId(atoi(val)); - break; - - case 'm': //mana - if(!primitive) primitive = NEW CardPrimitive(); - { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - primitive->setManaCost(value); - } - break; - - case 'n': //name - if(!primitive) primitive = NEW CardPrimitive(); - if (0 == strcmp("Bloodrock Cyclops", val)) - cout << "val" << endl; - primitive->setName(val); - break; - - case 'p': - if ('r' == key[1]) { // primitive - if (!card) card = NEW MTGCard(); - map::iterator it = primitives.find(val); - if (it != primitives.end()) card->setPrimitive(it->second); - } else { //power - if (!primitive) primitive = NEW CardPrimitive(); - primitive->setPower(atoi(val)); - } - break; - - case 'r': //retrace/rarity - if ('e' == key[1]) { //retrace - if (!primitive) primitive = NEW CardPrimitive(); + if (!primitive) + primitive = NEW CardPrimitive(); if (ManaCost * cost = primitive->getManaCost()) { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - cost->Retrace = ManaCost::parseManaCost(value); + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + cost->kicker = ManaCost::parseManaCost(value); } - } else {//rarity - if(!card) card = NEW MTGCard(); - card->setRarity(val[0]); - } - break; + break; + case 'o': //othercost + if (!primitive) + primitive = NEW CardPrimitive(); + if (ManaCost * cost = primitive->getManaCost()) + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + cost->alternative = ManaCost::parseManaCost(value); + } + break; + case 'b': //buyback + if (!primitive) + primitive = NEW CardPrimitive(); + if (ManaCost * cost = primitive->getManaCost()) + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + cost->BuyBack = ManaCost::parseManaCost(value); + } + break; + case 'f': //flashback + if (!primitive) + primitive = NEW CardPrimitive(); + if (ManaCost * cost = primitive->getManaCost()) + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + cost->FlashBack = ManaCost::parseManaCost(value); + } + break; + + case 'i': //id + if (!card) + card = NEW MTGCard(); + card->setMTGId(atoi(val)); + break; + + case 'm': //mana + if (!primitive) + primitive = NEW CardPrimitive(); + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + primitive->setManaCost(value); + } + break; + + case 'n': //name + if (!primitive) + primitive = NEW CardPrimitive(); + if (0 == strcmp("Bloodrock Cyclops", val)) + cout << "val" << endl; + primitive->setName(val); + break; + + case 'p': + if ('r' == key[1]) + { // primitive + if (!card) + card = NEW MTGCard(); + map::iterator it = primitives.find(val); + if (it != primitives.end()) + card->setPrimitive(it->second); + } + else + { //power + if (!primitive) + primitive = NEW CardPrimitive(); + primitive->setPower(atoi(val)); + } + break; + + case 'r': //retrace/rarity + if ('e' == key[1]) + { //retrace + if (!primitive) + primitive = NEW CardPrimitive(); + if (ManaCost * cost = primitive->getManaCost()) + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + cost->Retrace = ManaCost::parseManaCost(value); + } + } + else + {//rarity + if (!card) + card = NEW MTGCard(); + card->setRarity(val[0]); + } + break; case 's': //subtype - if(!primitive) primitive = NEW CardPrimitive(); - while (true){ - char* found = strchr(val, ' '); - if (found) { - string value(val, found - val); - primitive->setSubtype(value); - val = found + 1; + if (!primitive) + primitive = NEW CardPrimitive(); + while (true) + { + char* found = strchr(val, ' '); + if (found) + { + string value(val, found - val); + primitive->setSubtype(value); + val = found + 1; + } + else + { + primitive->setSubtype(val); + break; + } } - else { - primitive->setSubtype(val); - break; - } - } - break; + break; case 't': - if (!primitive) primitive = NEW CardPrimitive(); - if (0 == strcmp("target", key)) { - string value = val; - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - primitive->spellTargetType = value; - } else if (0 == strcmp("text", key)) - primitive->setText(val); - else if (0 == strcmp("type", key)) { - while (true){ - char* found = strchr(val, ' '); - if (found) { - string value(val, found - val); - primitive->setType(value); - val = found + 1; - } - else { - primitive->setType(val); - break; - } + if (!primitive) + primitive = NEW CardPrimitive(); + if (0 == strcmp("target", key)) + { + string value = val; + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + primitive->spellTargetType = value; } - } - else if (0 == strcmp("toughness", key)) - primitive->setToughness(atoi(val)); - break; + else if (0 == strcmp("text", key)) + primitive->setText(val); + else if (0 == strcmp("type", key)) + { + while (true) + { + char* found = strchr(val, ' '); + if (found) + { + string value(val, found - val); + primitive->setType(value); + val = found + 1; + } + else + { + primitive->setType(val); + break; + } + } + } + else if (0 == strcmp("toughness", key)) + primitive->setToughness(atoi(val)); + break; default: - DebugTrace("MTGDECK Parsing Error: " << s); - break; - } + DebugTrace("MTGDECK Parsing Error: " << s); + break; + } - tempPrimitive = primitive; - tempCard = card; + tempPrimitive = primitive; + tempCard = card; - return i; + return i; } -void MTGAllCards::initCounters(){ - for (int i=0; i < Constants::MTG_NB_COLORS; i++){ - colorsCount[i] = NULL; - } +void MTGAllCards::initCounters() +{ + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + colorsCount[i] = NULL; + } } -void MTGAllCards::init(){ - tempCard = NULL; - tempPrimitive = NULL; - total_cards = 0; - initCounters(); +void MTGAllCards::init() +{ + tempCard = NULL; + tempPrimitive = NULL; + total_cards = 0; + initCounters(); } +int MTGAllCards::load(const char * config_file, const char * set_name, int autoload) +{ + conf_read_mode = 0; + const int set_id = set_name ? setlist.Add(set_name) : MTGSets::INTERNAL_SET; + MTGSetInfo *si = setlist.getInfo(set_id); + std::ifstream setFile(config_file, ios::in | ios::ate); + if (!setFile) + return total_cards; -int MTGAllCards::load(const char * config_file, const char * set_name,int autoload){ - conf_read_mode = 0; - const int set_id = set_name ? setlist.Add(set_name) : MTGSets::INTERNAL_SET; - MTGSetInfo *si = setlist.getInfo(set_id); + streampos fileSize = setFile.tellg(); + setFile.seekg(0, ios::beg); - std::ifstream setFile(config_file, ios::in | ios::ate); - if (!setFile) return total_cards; + std::string contents; + contents.resize((std::string::size_type) fileSize); + setFile.read(&contents[0], fileSize); + std::stringstream stream(contents); - streampos fileSize = setFile.tellg(); - setFile.seekg(0, ios::beg); + string s; - std::string contents; - contents.resize((std::string::size_type)fileSize); - setFile.read(&contents[0], fileSize); - std::stringstream stream(contents); - - string s; - - while (true) { - if (!std::getline(stream, s)) return total_cards; - if (!s.size()) continue; - - if (s[s.size()-1] == '\r') s.erase(s.size()-1); // Handle DOS files - switch (conf_read_mode) { - case MTGAllCards::READ_ANYTHING: - if (s[0] == '['){ - currentGrade = Constants::GRADE_SUPPORTED; // Default value - conf_read_mode = ('m' == s[1]) ? MTGAllCards::READ_METADATA : MTGAllCards::READ_CARD; // M for metadata. - } else { - //Global grade for file, to avoid reading the entire file if unnnecessary - if (s[0]=='g' && s.size() > 8) { - int fileGrade = getGrade(s[8]); - int maxGrade = options[Options::MAX_GRADE].number; - if (!maxGrade) maxGrade = Constants::GRADE_BORDERLINE; //Default setting for grade is borderline? - if (fileGrade > maxGrade) { + while (true) + { + if (!std::getline(stream, s)) return total_cards; - } + if (!s.size()) + continue; + + if (s[s.size() - 1] == '\r') + s.erase(s.size() - 1); // Handle DOS files + switch (conf_read_mode) + { + case MTGAllCards::READ_ANYTHING: + if (s[0] == '[') + { + currentGrade = Constants::GRADE_SUPPORTED; // Default value + conf_read_mode = ('m' == s[1]) ? MTGAllCards::READ_METADATA : MTGAllCards::READ_CARD; // M for metadata. + } + else + { + //Global grade for file, to avoid reading the entire file if unnnecessary + if (s[0] == 'g' && s.size() > 8) + { + int fileGrade = getGrade(s[8]); + int maxGrade = options[Options::MAX_GRADE].number; + if (!maxGrade) + maxGrade = Constants::GRADE_BORDERLINE; //Default setting for grade is borderline? + if (fileGrade > maxGrade) + { + return total_cards; + } + } + } + continue; + case MTGAllCards::READ_METADATA: + if (s[0] == '[' && s[1] == '/') + conf_read_mode = MTGAllCards::READ_ANYTHING; + else if (si) + si->processConfLine(s); + continue; + case MTGAllCards::READ_CARD: + if (s[0] == '[' && s[1] == '/') + { + conf_read_mode = MTGAllCards::READ_ANYTHING; + if (tempPrimitive) + tempPrimitive = addPrimitive(tempPrimitive, tempCard); + if (tempCard) + { + if (tempPrimitive) + tempCard->setPrimitive(tempPrimitive); + addCardToCollection(tempCard, set_id); + } + tempCard = NULL; + tempPrimitive = NULL; + } + else + { + processConfLine(s, tempCard, tempPrimitive); + } + continue; } - } - continue; - case MTGAllCards::READ_METADATA: - if (s[0] == '[' && s[1] == '/') conf_read_mode = MTGAllCards::READ_ANYTHING; - else if (si) si->processConfLine(s); - continue; - case MTGAllCards::READ_CARD: - if (s[0] == '[' && s[1] == '/') { - conf_read_mode = MTGAllCards::READ_ANYTHING; - if (tempPrimitive) tempPrimitive = addPrimitive(tempPrimitive, tempCard); - if (tempCard) { - if (tempPrimitive) tempCard->setPrimitive(tempPrimitive); - addCardToCollection(tempCard, set_id); + } + + return total_cards; +} + +MTGAllCards::MTGAllCards() +{ + init(); +} + +MTGAllCards::~MTGAllCards() +{ + //Why don't we call destroyAllCards from here ??? +} + +void MTGAllCards::destroyAllCards() +{ + + for (map::iterator it = collection.begin(); it != collection.end(); it++) + delete (it->second); + collection.clear(); + ids.clear(); + + for (map::iterator it = primitives.begin(); it != primitives.end(); it++) + delete (it->second); + primitives.clear(); + +} + +MTGAllCards::MTGAllCards(const char * config_file, const char * set_name) +{ + init(); + load(config_file, set_name, 0); +} + +int MTGAllCards::randomCardId() +{ + int id = (rand() % ids.size()); + return ids[id]; +} + +int MTGAllCards::countBySet(int setId) +{ + int result = 0; + map::iterator it; + + for (it = collection.begin(); it != collection.end(); it++) + { + MTGCard * c = it->second; + if (c->setId == setId) + { + result++; } - tempCard = NULL; - tempPrimitive = NULL; - } else { - processConfLine(s, tempCard, tempPrimitive); - } - continue; } - } - - return total_cards; -} - -MTGAllCards::MTGAllCards(){ - init(); -} - -MTGAllCards::~MTGAllCards(){ - //Why don't we call destroyAllCards from here ??? -} - -void MTGAllCards::destroyAllCards(){ - - - for (map::iterator it = collection.begin(); it!=collection.end(); it++) delete(it->second); - collection.clear(); - ids.clear(); - - for (map::iterator it = primitives.begin(); it!=primitives.end(); it++) delete(it->second); - primitives.clear(); - -} - -MTGAllCards::MTGAllCards(const char * config_file, const char * set_name){ - init(); - load(config_file,set_name, 0); -} - - - -int MTGAllCards::randomCardId(){ - int id = (rand() % ids.size()); - return ids[id]; -} - - - -int MTGAllCards::countBySet(int setId){ - int result = 0; - map::iterator it; - - for (it = collection.begin(); it!=collection.end(); it++){ - MTGCard * c = it->second; - if( c->setId == setId){ - result++; - } - } - return result; + return result; } //TODO more efficient way ? -int MTGAllCards::countByType(const char * _type){ - int result = 0; - map::iterator it; - for (it = collection.begin(); it!=collection.end(); it++){ - MTGCard * c = it->second; - if(c->data->hasType(_type)){ - result++; +int MTGAllCards::countByType(const char * _type) +{ + int result = 0; + map::iterator it; + for (it = collection.begin(); it != collection.end(); it++) + { + MTGCard * c = it->second; + if (c->data->hasType(_type)) + { + result++; + } } - } - return result; + return result; } +int MTGAllCards::countByColor(int color) +{ + if (colorsCount[color] == 0) + { + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + colorsCount[i] = 0; + } + map::iterator it; + for (it = collection.begin(); it != collection.end(); it++) + { + MTGCard * c = it->second; + int j = c->data->getColor(); -int MTGAllCards::countByColor(int color){ - if (colorsCount[color] == 0){ - for (int i=0; i< Constants::MTG_NB_COLORS; i++){ - colorsCount[i] = 0; + colorsCount[j]++; + } } - map::iterator it; - for (it = collection.begin(); it!=collection.end(); it++){ - MTGCard * c = it->second; - int j = c->data->getColor(); - - colorsCount[j]++; - } - } - return colorsCount[color]; + return colorsCount[color]; } -int MTGAllCards::totalCards(){ - return (total_cards); +int MTGAllCards::totalCards() +{ + return (total_cards); } -bool MTGAllCards::addCardToCollection(MTGCard * card, int setId){ - card->setId = setId; - int newId = card->getId(); - if (collection.find(newId) != collection.end()){ +bool MTGAllCards::addCardToCollection(MTGCard * card, int setId) +{ + card->setId = setId; + int newId = card->getId(); + if (collection.find(newId) != collection.end()) + { #if defined (_DEBUG) - string cardName = card->data ? card->data->name : card->getImageName(); - string setName = setId != -1 ? setlist.getInfo(setId)->getName() : ""; - DebugTrace("warning, card id collision! : " << newId << " -> " << cardName << "(" << setName << ")"); + string cardName = card->data ? card->data->name : card->getImageName(); + string setName = setId != -1 ? setlist.getInfo(setId)->getName() : ""; + DebugTrace("warning, card id collision! : " << newId << " -> " << cardName << "(" << setName << ")"); #endif - SAFE_DELETE(card); - return false; - } + SAFE_DELETE(card); + return false; + } - //Don't add cards that don't have a primitive - if (!card->data){ - SAFE_DELETE(card); - return false; - } - ids.push_back(newId); + //Don't add cards that don't have a primitive + if (!card->data) + { + SAFE_DELETE(card); + return false; + } + ids.push_back(newId); - collection[newId] = card; //Push card into collection. - MTGSetInfo * si = setlist.getInfo(setId); - if (si) si->count(card); //Count card in set info - ++total_cards; - return true; + collection[newId] = card; //Push card into collection. + MTGSetInfo * si = setlist.getInfo(setId); + if (si) + si->count(card); //Count card in set info + ++total_cards; + return true; } -CardPrimitive * MTGAllCards::addPrimitive(CardPrimitive * primitive, MTGCard * card){ - int maxGrade = options[Options::MAX_GRADE].number; - if (!maxGrade) maxGrade = Constants::GRADE_BORDERLINE; //Default setting for grade is borderline? - if (currentGrade > maxGrade) { - SAFE_DELETE(primitive); +CardPrimitive * MTGAllCards::addPrimitive(CardPrimitive * primitive, MTGCard * card) +{ + int maxGrade = options[Options::MAX_GRADE].number; + if (!maxGrade) + maxGrade = Constants::GRADE_BORDERLINE; //Default setting for grade is borderline? + if (currentGrade > maxGrade) + { + SAFE_DELETE(primitive); + return NULL; + } + string key; + if (card) + { + std::stringstream ss; + ss << card->getId(); + ss >> key; + } + else + key = primitive->name; + if (primitives.find(key) != primitives.end()) + { + //ERROR + //Todo move the deletion somewhere else ? +DebugTrace ("MTGDECK: primitives conflict: "<< key); + SAFE_DELETE(primitive); + return NULL; + } + //translate cards text + Translator * t = Translator::GetInstance(); + map::iterator it = t->tempValues.find(primitive->name); + if (it != t->tempValues.end()) + { + primitive->setText(it->second); + } + + //Legacy: + //For the Deck editor, we need Lands and Artifact to be colors... + if (primitive->hasType(Subtypes::TYPE_LAND)) primitive->setColor(Constants::MTG_COLOR_LAND); + if (primitive->hasType(Subtypes::TYPE_ARTIFACT)) primitive->setColor(Constants::MTG_COLOR_ARTIFACT); + + primitives[key] = primitive; + return primitive; +} + +MTGCard * MTGAllCards::getCardById(int id) +{ + map::iterator it = collection.find(id); + if (it != collection.end()) + { + return (it->second); + } + return 0; +} + +MTGCard * MTGAllCards::_(int index) +{ + if (index >= total_cards) + return NULL; + return getCardById(ids[index]); +} + +MTGCard * MTGAllCards::getCardByName(string name) +{ + if (!name.size()) + return NULL; + if (name[0] == '#') + return NULL; + + int cardnb = atoi(name.c_str()); + if (cardnb) + { + return getCardById(cardnb); + } + + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + int setId = -1; + size_t found = name.find(" ("); + if (found != string::npos) + { + size_t end = name.find(")"); + string setName = name.substr(found + 2, end - found - 2); + trim(setName); + name = name.substr(0, found); + trim(name); + setId = setlist[setName]; + } + map::iterator it; + for (it = collection.begin(); it != collection.end(); it++) + { + MTGCard * c = it->second; + if (setId != -1 && setId != c->setId) + continue; + string cardName = c->data->name; + std::transform(cardName.begin(), cardName.end(), cardName.begin(), ::tolower); + if (cardName.compare(name) == 0) + return c; + + } return NULL; - } - string key; - if (card) { - std::stringstream ss; - ss << card->getId(); - ss >> key; - } - else key = primitive->name; - if (primitives.find(key) != primitives.end()){ - //ERROR - //Todo move the deletion somewhere else ? - DebugTrace("MTGDECK: primitives conflict: "<< key); - SAFE_DELETE(primitive); - return NULL; - } - //translate cards text - Translator * t = Translator::GetInstance(); - map::iterator it = t->tempValues.find(primitive->name); - if (it != t->tempValues.end()) { - primitive->setText(it->second); - } - - //Legacy: - //For the Deck editor, we need Lands and Artifact to be colors... - if (primitive->hasType(Subtypes::TYPE_LAND)) primitive->setColor(Constants::MTG_COLOR_LAND); - if (primitive->hasType(Subtypes::TYPE_ARTIFACT)) primitive->setColor(Constants::MTG_COLOR_ARTIFACT); - - primitives[key] = primitive; - return primitive; -} - - -MTGCard * MTGAllCards::getCardById(int id){ - map::iterator it = collection.find(id); - if ( it != collection.end()){ - return (it->second); - } - return 0; -} - -MTGCard * MTGAllCards::_(int index){ - if (index >= total_cards) return NULL; - return getCardById(ids[index]); -} - -MTGCard * MTGAllCards::getCardByName(string name){ - if (!name.size()) return NULL; - if (name[0] == '#') return NULL; - - int cardnb = atoi(name.c_str()); - if (cardnb){ - return getCardById(cardnb); - } - - std::transform(name.begin(), name.end(), name.begin(),::tolower ); - int setId = -1; - size_t found = name.find(" ("); - if (found != string::npos){ - size_t end = name.find(")"); - string setName = name.substr(found+2,end-found-2); - trim(setName); - name = name.substr(0,found); - trim(name); - setId = setlist[setName]; - } - map::iterator it; - for (it = collection.begin(); it!=collection.end(); it++){ - MTGCard * c = it->second; - if (setId!=-1 && setId != c->setId) continue; - string cardName = c->data->name; - std::transform(cardName.begin(), cardName.end(), cardName.begin(),::tolower ); - if (cardName.compare(name) == 0) return c; - - } - return NULL; } //MTGDeck -MTGDeck::MTGDeck(MTGAllCards * _allcards){ - total_cards = 0; - database = _allcards; - filename =""; - meta_name = ""; +MTGDeck::MTGDeck(MTGAllCards * _allcards) +{ + total_cards = 0; + database = _allcards; + filename = ""; + meta_name = ""; } -int MTGDeck::totalPrice(){ - int total = 0; - PriceList * pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(),GameApp::collection); - map::iterator it; - for ( it=cards.begin() ; it != cards.end(); it++ ){ - int nb = it->second; - if (nb) total += pricelist->getPrice(it->first); - } - SAFE_DELETE(pricelist); - return total; -} -MTGDeck::MTGDeck(const char * config_file, MTGAllCards * _allcards, int meta_only){ - total_cards = 0; - database = _allcards; - filename = config_file; - size_t slash = filename.find_last_of("/"); - size_t dot = filename.find("."); - meta_name = filename.substr(slash+1,dot-slash-1); - std::ifstream file(config_file); - std::string s; - - if(file){ - while(std::getline(file,s)){ - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - if (s[0] == '#'){ - size_t found = s.find("NAME:"); - if ( found != string::npos){ - meta_name = s.substr(found+5); - continue; - } - found = s.find("DESC:"); - if ( found != string::npos){ - if (meta_desc.size()) meta_desc.append("\n"); - meta_desc.append(s.substr(found+5)); - continue; - } - continue; - } - if (meta_only) break; - int cardnb = atoi(s.c_str()); - if (cardnb){ - add(cardnb); - }else{ - int nb = 1; - size_t found = s.find(" *"); - if (found != string::npos){ - nb = atoi(s.substr(found+2).c_str()); - s = s.substr(0,found); - } - MTGCard * card = database->getCardByName(s); - if (card){ - for (int i = 0; i < nb; i++){ - add(card); - } - } else { - DebugTrace("could not find Card matching name: " << s); - } - } - } - file.close(); - }else{ - //TODO Error management - } - - -} - -int MTGDeck::totalCards(){ - return total_cards; -} - -MTGCard * MTGDeck::getCardById(int mtgId){ - return database->getCardById(mtgId); -} - - -int MTGDeck::addRandomCards(int howmany, int * setIds, int nbSets, int rarity, const char * _subtype, int * colors, int nbcolors){ - if(howmany <= 0) - return 1; - - int unallowedColors[Constants::MTG_NB_COLORS+1]; - for (int i=0; i < Constants::MTG_NB_COLORS; ++i){ - if (nbcolors) unallowedColors[i] = 1; - else unallowedColors[i] = 0; - } - for (int i=0; i < nbcolors; ++i){ - unallowedColors[colors[i]] = 0; - } - - int collectionTotal = database->totalCards(); - if (!collectionTotal) return 0; - - char subtype[4096]; - if (_subtype) - sprintf(subtype, "%s", _subtype); - - - vector subcollection; - int subtotal = 0; - for (int i = 0; i < collectionTotal; i++){ - MTGCard * card = database->_(i); - int r = card->getRarity(); - if (r != Constants::RARITY_T && (rarity == -1 || r==rarity) && // remove tokens - card->setId != MTGSets::INTERNAL_SET && //remove cards that are defined in primitives. Those are workarounds (usually tokens) and should only be used internally - (!_subtype || card->data->hasSubtype(subtype)) - ){ - int ok = 0; - - if (!nbSets) ok = 1; - for (int j=0; j < nbSets; ++j){ - if (card->setId == setIds[j]){ - ok = 1; - break; - } - } - - if (ok){ - for (int j=0; j < Constants::MTG_NB_COLORS; ++j){ - if (unallowedColors[j] && card->data->hasColor(j)){ - ok = 0; - break; - } - } - } - - if (ok){ - subcollection.push_back(card->getId()); - subtotal++; - } - } - } - if (subtotal == 0){ - if (rarity == Constants::RARITY_M) return addRandomCards(howmany, setIds, nbSets, Constants::RARITY_R, _subtype, colors, nbcolors); - return 0; - } - for (int i = 0; i < howmany; i++){ - int id = (rand() % subtotal); - add(subcollection[id]); - } - return 1; -} - -int MTGDeck::add(MTGDeck * deck){ - map::iterator it; - for (it = deck->cards.begin(); it!=deck->cards.end(); it++){ - for (int i = 0; i < it->second; i++){ - add(it->first); - } - } - return deck->totalCards(); -} - -int MTGDeck::add(int cardid){ - if (!database->getCardById(cardid)) return 0; - if(cards.find(cardid) == cards.end()){ - cards[cardid] = 1; - }else{ - cards[cardid]++; - } - ++total_cards; - //initCounters(); - return total_cards; -} - -int MTGDeck::add(MTGCard * card){ - if (!card) return 0; - return (add(card->getId())); -} - -int MTGDeck::complete() { - /* (PSY) adds cards to the deck/collection. Makes sure that the deck - or collection has at least 4 of every implemented card. Does not - change the number of cards of which already 4 or more are present. */ - int id, n; - bool StypeIsNothing; - size_t databaseSize = database->ids.size(); - for (size_t it = 0 ; it < databaseSize ; it++) { - id = database->ids[it]; - StypeIsNothing = false; - if(database->getCardById(id)->data->hasType("nothing")) - { - StypeIsNothing = true; - } - if(!StypeIsNothing == true) - { - if(cards.find(id) == cards.end()){ - cards[id] = 4; - total_cards += 4; - } else { - n = cards[id]; - if (n < 4) { - total_cards += 4 - n; - cards[id] = 4; - } - } - } - } - return 1; -} - -int MTGDeck::removeAll(){ - total_cards = 0; - cards.clear(); - //initCounters(); - return 1; -} - -int MTGDeck::remove(int cardid){ - if(cards.find(cardid) == cards.end() || cards[cardid] == 0) return 0; - cards[cardid]--; - total_cards--; - //initCounters(); - return 1; -} - - -int MTGDeck::remove(MTGCard * card){ - if (!card) return 0; - return (remove(card->getId())); -} - -int MTGDeck::save() { - return save( filename, false, meta_name, meta_desc ); -} - -int MTGDeck::save(string destFileName, bool useExpandedDescriptions, string &deckTitle, string &deckDesc ){ - string tmp = destFileName; - tmp.append(".tmp"); //not thread safe - std::ofstream file(tmp.c_str()); - char writer[512]; - if (file){ - DebugTrace("Saving Deck: " << deckTitle << " to " << destFileName ); - if (meta_name.size()){ - file << "#NAME:" << deckTitle << '\n'; - } - - if (meta_desc.size()){ - size_t found = 0; - string desc= deckDesc; - found = desc.find_first_of("\n"); - while(found != string::npos){ - file << "#DESC:" << desc.substr(0,found+1); - desc=desc.substr(found+1); - found = desc.find_first_of("\n"); - } - file << "#DESC:" << desc << "\n"; - } - - if ( useExpandedDescriptions ) +int MTGDeck::totalPrice() +{ + int total = 0; + PriceList * pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(), GameApp::collection); + map::iterator it; + for (it = cards.begin(); it != cards.end(); it++) { - map::iterator it; - for (it = cards.begin(); it!=cards.end(); it++) - { - int nbCards = it->second; - MTGCard *card = this->getCardById( it->first ); - if ( card == NULL ) + int nb = it->second; + if (nb) + total += pricelist->getPrice(it->first); + } + SAFE_DELETE(pricelist); + return total; +} +MTGDeck::MTGDeck(const char * config_file, MTGAllCards * _allcards, int meta_only) +{ + total_cards = 0; + database = _allcards; + filename = config_file; + size_t slash = filename.find_last_of("/"); + size_t dot = filename.find("."); + meta_name = filename.substr(slash + 1, dot - slash - 1); + std::ifstream file(config_file); + std::string s; + + if (file) + { + while (std::getline(file, s)) { - continue; + if (!s.size()) + continue; + if (s[s.size() - 1] == '\r') + s.erase(s.size() - 1); //Handle DOS files + if (s[0] == '#') + { + size_t found = s.find("NAME:"); + if (found != string::npos) + { + meta_name = s.substr(found + 5); + continue; + } + found = s.find("DESC:"); + if (found != string::npos) + { + if (meta_desc.size()) + meta_desc.append("\n"); + meta_desc.append(s.substr(found + 5)); + continue; + } + continue; + } + if (meta_only) + break; + int cardnb = atoi(s.c_str()); + if (cardnb) + { + add(cardnb); + } + else + { + int nb = 1; + size_t found = s.find(" *"); + if (found != string::npos) + { + nb = atoi(s.substr(found + 2).c_str()); + s = s.substr(0, found); + } + MTGCard * card = database->getCardByName(s); + if (card) + { + for (int i = 0; i < nb; i++) + { + add(card); + } + } + else + { + DebugTrace("could not find Card matching name: " << s); + } + } } - MTGSetInfo *setInfo = setlist.getInfo( card->setId ); - string setName = setInfo->id; - string cardName = card->data->getName(); - file<< cardName << "\t " << "(" << setName << ") *" << nbCards << endl; - setInfo = NULL; - } + file.close(); } else { - map::iterator it; - for (it = cards.begin(); it!=cards.end(); it++){ - sprintf(writer,"%i\n", it->first); - for (int j = 0; jsecond; j++){ - file<invalidate(destFileName); - return 1; +} + +int MTGDeck::totalCards() +{ + return total_cards; +} + +MTGCard * MTGDeck::getCardById(int mtgId) +{ + return database->getCardById(mtgId); +} + +int MTGDeck::addRandomCards(int howmany, int * setIds, int nbSets, int rarity, const char * _subtype, int * colors, int nbcolors) +{ + if (howmany <= 0) + return 1; + + int unallowedColors[Constants::MTG_NB_COLORS + 1]; + for (int i = 0; i < Constants::MTG_NB_COLORS; ++i) + { + if (nbcolors) + unallowedColors[i] = 1; + else + unallowedColors[i] = 0; + } + for (int i = 0; i < nbcolors; ++i) + { + unallowedColors[colors[i]] = 0; + } + + int collectionTotal = database->totalCards(); + if (!collectionTotal) + return 0; + + char subtype[4096]; + if (_subtype) + sprintf(subtype, "%s", _subtype); + + vector subcollection; + int subtotal = 0; + for (int i = 0; i < collectionTotal; i++) + { + MTGCard * card = database->_(i); + int r = card->getRarity(); + if (r != Constants::RARITY_T && (rarity == -1 || r == rarity) && // remove tokens + card->setId != MTGSets::INTERNAL_SET && //remove cards that are defined in primitives. Those are workarounds (usually tokens) and should only be used internally + (!_subtype || card->data->hasSubtype(subtype))) + { + int ok = 0; + + if (!nbSets) + ok = 1; + for (int j = 0; j < nbSets; ++j) + { + if (card->setId == setIds[j]) + { + ok = 1; + break; + } + } + + if (ok) + { + for (int j = 0; j < Constants::MTG_NB_COLORS; ++j) + { + if (unallowedColors[j] && card->data->hasColor(j)) + { + ok = 0; + break; + } + } + } + + if (ok) + { + subcollection.push_back(card->getId()); + subtotal++; + } + } + } + if (subtotal == 0) + { + if (rarity == Constants::RARITY_M) + return addRandomCards(howmany, setIds, nbSets, Constants::RARITY_R, _subtype, colors, nbcolors); + return 0; + } + for (int i = 0; i < howmany; i++) + { + int id = (rand() % subtotal); + add(subcollection[id]); + } + return 1; +} + +int MTGDeck::add(MTGDeck * deck) +{ + map::iterator it; + for (it = deck->cards.begin(); it != deck->cards.end(); it++) + { + for (int i = 0; i < it->second; i++) + { + add(it->first); + } + } + return deck->totalCards(); +} + +int MTGDeck::add(int cardid) +{ + if (!database->getCardById(cardid)) + return 0; + if (cards.find(cardid) == cards.end()) + { + cards[cardid] = 1; + } + else + { + cards[cardid]++; + } + ++total_cards; + //initCounters(); + return total_cards; +} + +int MTGDeck::add(MTGCard * card) +{ + if (!card) + return 0; + return (add(card->getId())); +} + +int MTGDeck::complete() +{ + /* (PSY) adds cards to the deck/collection. Makes sure that the deck + or collection has at least 4 of every implemented card. Does not + change the number of cards of which already 4 or more are present. */ + int id, n; + bool StypeIsNothing; + size_t databaseSize = database->ids.size(); + for (size_t it = 0; it < databaseSize; it++) + { + id = database->ids[it]; + StypeIsNothing = false; + if (database->getCardById(id)->data->hasType("nothing")) + { + StypeIsNothing = true; + } + if (!StypeIsNothing == true) + { + if (cards.find(id) == cards.end()) + { + cards[id] = 4; + total_cards += 4; + } + else + { + n = cards[id]; + if (n < 4) + { + total_cards += 4 - n; + cards[id] = 4; + } + } + } + } + return 1; +} + +int MTGDeck::removeAll() +{ + total_cards = 0; + cards.clear(); + //initCounters(); + return 1; +} + +int MTGDeck::remove(int cardid) +{ + if (cards.find(cardid) == cards.end() || cards[cardid] == 0) + return 0; + cards[cardid]--; + total_cards--; + //initCounters(); + return 1; +} + +int MTGDeck::remove(MTGCard * card) +{ + if (!card) + return 0; + return (remove(card->getId())); +} + +int MTGDeck::save() +{ + return save(filename, false, meta_name, meta_desc); +} + +int MTGDeck::save(string destFileName, bool useExpandedDescriptions, string &deckTitle, string &deckDesc) +{ + string tmp = destFileName; + tmp.append(".tmp"); //not thread safe + std::ofstream file(tmp.c_str()); + char writer[512]; + if (file) + { + DebugTrace("Saving Deck: " << deckTitle << " to " << destFileName ); + if (meta_name.size()) + { + file << "#NAME:" << deckTitle << '\n'; + } + + if (meta_desc.size()) + { + size_t found = 0; + string desc = deckDesc; + found = desc.find_first_of("\n"); + while (found != string::npos) + { + file << "#DESC:" << desc.substr(0, found + 1); + desc = desc.substr(found + 1); + found = desc.find_first_of("\n"); + } + file << "#DESC:" << desc << "\n"; + } + + if (useExpandedDescriptions) + { + map::iterator it; + for (it = cards.begin(); it != cards.end(); it++) + { + int nbCards = it->second; + MTGCard *card = this->getCardById(it->first); + if (card == NULL) + { + continue; + } + MTGSetInfo *setInfo = setlist.getInfo(card->setId); + string setName = setInfo->id; + string cardName = card->data->getName(); + file << cardName << "\t " << "(" << setName << ") *" << nbCards << endl; + setInfo = NULL; + } + } + else + { + map::iterator it; + for (it = cards.begin(); it != cards.end(); it++) + { + sprintf(writer, "%i\n", it->first); + for (int j = 0; j < it->second; j++) + { + file << writer; + } + } + } + file.close(); + std::remove(destFileName.c_str()); + rename(tmp.c_str(), destFileName.c_str()); + } + DeckMetaDataList::decksMetaData->invalidate(destFileName); + return 1; } //MTGSets MTGSets setlist; //Our global. -MTGSets::MTGSets(){ +MTGSets::MTGSets() +{ } -MTGSets::~MTGSets(){ - for (size_t i = 0; i < setinfo.size(); ++i){ - delete (setinfo[i]); - } +MTGSets::~MTGSets() +{ + for (size_t i = 0; i < setinfo.size(); ++i) + { + delete (setinfo[i]); + } } -MTGSetInfo* MTGSets::getInfo(int setID){ - if(setID < 0 || setID >= (int) setinfo.size()) +MTGSetInfo* MTGSets::getInfo(int setID) +{ + if (setID < 0 || setID >= (int) setinfo.size()) + return NULL; + + return setinfo[setID]; +} + +MTGSetInfo* MTGSets::randomSet(int blockId, int atleast) +{ + char * unlocked = (char *) calloc(size(), sizeof(char)); + int attempts = 50; + //Figure out which sets are available. + for (int i = 0; i < size(); i++) + { + unlocked[i] = options[Options::optionSet(i)].number; + } + //No luck randomly. Now iterate from a random location. + int a = 0, iter = 0; + while (iter < 3) + { + a = rand() % size(); + for (int i = a; i < size(); i++) + { + if (unlocked[i] && (blockId == -1 || setinfo[i]->block == blockId) && (atleast == -1 || setinfo[i]->totalCards() + >= atleast)) + { + free(unlocked); + return setinfo[i]; + } + } + for (int i = 0; i < a; i++) + { + if (unlocked[i] && (blockId == -1 || setinfo[i]->block == blockId) && (atleast == -1 || setinfo[i]->totalCards() + >= atleast)) + { + free(unlocked); + return setinfo[i]; + } + } + blockId = -1; + iter++; + if (iter == 2) + atleast = -1; + } + free(unlocked); return NULL; - - return setinfo[setID]; -} - -MTGSetInfo* MTGSets::randomSet(int blockId, int atleast){ - char * unlocked = (char *)calloc(size(),sizeof(char)); - int attempts = 50; - //Figure out which sets are available. - for (int i = 0; i < size(); i++){ - unlocked[i] = options[Options::optionSet(i)].number; - } - //No luck randomly. Now iterate from a random location. - int a = 0, iter = 0; - while(iter < 3){ - a = rand()%size(); - for(int i=a;iblock == blockId) - && (atleast == -1 || setinfo[i]->totalCards() >= atleast)){ - free(unlocked); - return setinfo[i]; - } - } - for(int i=0;iblock == blockId) - && (atleast == -1 || setinfo[i]->totalCards() >= atleast)){ - free(unlocked); - return setinfo[i]; - } - } - blockId = -1; - iter++; - if(iter == 2) - atleast = -1; - } - free(unlocked); - return NULL; } int blockSize(int blockId); -int MTGSets::Add(const char * name){ - int setid = findSet(name); - if(setid != -1) - return setid; +int MTGSets::Add(const char * name) +{ + int setid = findSet(name); + if (setid != -1) + return setid; - MTGSetInfo* s = NEW MTGSetInfo(name); - setinfo.push_back(s); - setid = (int) setinfo.size(); + MTGSetInfo* s = NEW MTGSetInfo(name); + setinfo.push_back(s); + setid = (int) setinfo.size(); - return setid - 1; + return setid - 1; } -int MTGSets::findSet(string name){ - std::transform(name.begin(), name.end(), name.begin(),::tolower ); +int MTGSets::findSet(string name) +{ + std::transform(name.begin(), name.end(), name.begin(), ::tolower); - for (int i = 0; i < (int) setinfo.size(); i++){ - MTGSetInfo* s = setinfo[i]; - if(!s) continue; - string set = s->id; - std::transform(set.begin(), set.end(), set.begin(),::tolower); - if (set.compare(name) == 0) return i; - } - return -1; -} - -int MTGSets::findBlock(string s){ - if(!s.size()) + for (int i = 0; i < (int) setinfo.size(); i++) + { + MTGSetInfo* s = setinfo[i]; + if (!s) + continue; + string set = s->id; + std::transform(set.begin(), set.end(), set.begin(), ::tolower); + if (set.compare(name) == 0) + return i; + } return -1; - - string comp = s; - std::transform(comp.begin(), comp.end(), comp.begin(),::tolower); - for(int i=0;i<(int)blocks.size();i++){ - string b = blocks[i]; - std::transform(b.begin(), b.end(), b.begin(),::tolower); - if(b.compare(comp) == 0) return i; - } - - blocks.push_back(s); - return ((int) blocks.size()) -1; } -int MTGSets::operator[](string id){ - return findSet(id); -} -string MTGSets::operator[](int id){ - if(id < 0 || id >= (int) setinfo.size()) - return ""; +int MTGSets::findBlock(string s) +{ + if (!s.size()) + return -1; - MTGSetInfo * si = setinfo[id]; - if(!si) - return ""; + string comp = s; + std::transform(comp.begin(), comp.end(), comp.begin(), ::tolower); + for (int i = 0; i < (int) blocks.size(); i++) + { + string b = blocks[i]; + std::transform(b.begin(), b.end(), b.begin(), ::tolower); + if (b.compare(comp) == 0) + return i; + } - return si->id; + blocks.push_back(s); + return ((int) blocks.size()) - 1; } -int MTGSets::getSetNum(MTGSetInfo*i){ - int it; - for(it=0;it= (int) setinfo.size()) + return ""; + + MTGSetInfo * si = setinfo[id]; + if (!si) + return ""; + + return si->id; +} +int MTGSets::getSetNum(MTGSetInfo*i) +{ + int it; + for (it = 0; it < size(); it++) + { + if (setinfo[it] == i) + return it; + } + return -1; +} +int MTGSets::size() +{ + return (int) setinfo.size(); } //MTGSetInfo -MTGSetInfo::~MTGSetInfo(){ - SAFE_DELETE(mPack); -} -MTGSetInfo::MTGSetInfo(string _id) { - string whitespaces (" \t\f\v\n\r"); - id = _id; - block = -1; - year = -1; - - for(int i=0;iisValid()){ +MTGSetInfo::~MTGSetInfo() +{ SAFE_DELETE(mPack); - } - bZipped = false; - bThemeZipped = false; +} +MTGSetInfo::MTGSetInfo(string _id) +{ + string whitespaces(" \t\f\v\n\r"); + id = _id; + block = -1; + year = -1; + + for (int i = 0; i < MTGSetInfo::MAX_COUNT; i++) + counts[i] = 0; + + char myFilename[4096]; + sprintf(myFilename, JGE_GET_RES("sets/%s/booster.txt").c_str(), id.c_str()); + mPack = NEW MTGPack(myFilename); + if (!mPack->isValid()) + { + SAFE_DELETE(mPack); + } + bZipped = false; + bThemeZipped = false; } -void MTGSetInfo::count(MTGCard*c){ - if(!c) - return; +void MTGSetInfo::count(MTGCard*c) +{ + if (!c) + return; - switch(c->getRarity()){ + switch (c->getRarity()) + { case Constants::RARITY_M: - counts[MTGSetInfo::MYTHIC]++; - break; + counts[MTGSetInfo::MYTHIC]++; + break; case Constants::RARITY_R: - counts[MTGSetInfo::RARE]++; - break; + counts[MTGSetInfo::RARE]++; + break; case Constants::RARITY_U: - counts[MTGSetInfo::UNCOMMON]++; - break; + counts[MTGSetInfo::UNCOMMON]++; + break; case Constants::RARITY_C: - counts[MTGSetInfo::COMMON]++; - break; + counts[MTGSetInfo::COMMON]++; + break; default: case Constants::RARITY_L: - counts[MTGSetInfo::LAND]++; - break; - } + counts[MTGSetInfo::LAND]++; + break; + } - counts[MTGSetInfo::TOTAL_CARDS]++; + counts[MTGSetInfo::TOTAL_CARDS]++; } -int MTGSetInfo::totalCards(){ - return counts[MTGSetInfo::TOTAL_CARDS]; +int MTGSetInfo::totalCards() +{ + return counts[MTGSetInfo::TOTAL_CARDS]; } -string MTGSetInfo::getName(){ - if(name.size()) - return name; //Pretty name is translated when rendering. - return id; //Ugly name as well. +string MTGSetInfo::getName() +{ + if (name.size()) + return name; //Pretty name is translated when rendering. + return id; //Ugly name as well. } -string MTGSetInfo::getBlock(){ - if(block < 0 || block >= (int) setlist.blocks.size()) - return "None"; +string MTGSetInfo::getBlock() +{ + if (block < 0 || block >= (int) setlist.blocks.size()) + return "None"; - return setlist.blocks[block]; + return setlist.blocks[block]; } -void MTGSetInfo::processConfLine(string line){ - size_t i = line.find_first_of("="); - if (i == string::npos) - return; +void MTGSetInfo::processConfLine(string line) +{ + size_t i = line.find_first_of("="); + if (i == string::npos) + return; - string key = line.substr(0,i); - std::transform(key.begin(),key.end(),key.begin(),::tolower); - string value = line.substr(i+1); + string key = line.substr(0, i); + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + string value = line.substr(i + 1); - if(key.compare("name") == 0) - name = value; - else if(key.compare("author") == 0) - author = value; - else if(key.compare("block") == 0) - block = setlist.findBlock(value.c_str()); - else if(key.compare("year") == 0) - year = atoi(value.c_str()); + if (key.compare("name") == 0) + name = value; + else if (key.compare("author") == 0) + author = value; + else if (key.compare("block") == 0) + block = setlist.findBlock(value.c_str()); + else if (key.compare("year") == 0) + year = atoi(value.c_str()); } diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index f2261b993..40bbf7f5c 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -27,90 +27,90 @@ const string Constants::kKickerKeyword = "kicker"; const char* Constants::MTGBasicAbilities[] = { -"trample", -"forestwalk", -"islandwalk", -"mountainwalk", -"swampwalk", -"plainswalk", -"flying", -"first strike", -"double strike", -"fear", -"flash", -"haste", -"lifelink", -"reach", -"shroud", -"vigilance", -"defender", -"banding", -"protection from green", -"protection from blue", -"protection from red", -"protection from black", -"protection from white", -"unblockable", -"wither", -"persist", -"retrace", -"exalted", -"nofizzle", -"shadow", -"reachshadow", -"foresthome", -"islandhome", -"mountainhome", -"swamphome", -"plainshome", -"cloud", -"cantattack", -"mustattack", -"cantblock", -"doesnotuntap", -"opponentshroud", -"indestructible", -"intimidate", -"deathtouch", -"horsemanship", -"cantregen", -"oneblocker", -"infect", -"poisontoxic", -"poisontwotoxic", -"poisonthreetoxic", -"phantom",//prevents damage and remove 1 +1/+1 counter -"wilting",//source takes damage in the form of -1/-1 counters. -"vigor",//instead of taking damage the source gains +1/+1 counters -"changeling",//this card is every creature type at all times -"absorb",//timeshifted sliver ability. if damage would be dealt to card, prevent 1 of that damage. -"treason", -"unearth", -"cantlose", -"cantlifelose", -"cantmilllose", -"cantcreaturecast", -"cantspellcast", -"onlyonecast", -"storm", -"bothcantcast", -"bothnocreature", -"oneboth", -"affinityartifacts", -"affinityplains", -"affinityforests", -"affinityislands", -"affinitymountains", -"affinityswamps", -"affinitygreencreatures", -"cantwin", -"nomaxhand", -"leyline", -"playershroud", -"controllershroud", -"sunburst", -"flanking", -"exiledeath", + "trample", + "forestwalk", + "islandwalk", + "mountainwalk", + "swampwalk", + "plainswalk", + "flying", + "first strike", + "double strike", + "fear", + "flash", + "haste", + "lifelink", + "reach", + "shroud", + "vigilance", + "defender", + "banding", + "protection from green", + "protection from blue", + "protection from red", + "protection from black", + "protection from white", + "unblockable", + "wither", + "persist", + "retrace", + "exalted", + "nofizzle", + "shadow", + "reachshadow", + "foresthome", + "islandhome", + "mountainhome", + "swamphome", + "plainshome", + "cloud", + "cantattack", + "mustattack", + "cantblock", + "doesnotuntap", + "opponentshroud", + "indestructible", + "intimidate", + "deathtouch", + "horsemanship", + "cantregen", + "oneblocker", + "infect", + "poisontoxic", + "poisontwotoxic", + "poisonthreetoxic", + "phantom",//prevents damage and remove 1 +1/+1 counter + "wilting",//source takes damage in the form of -1/-1 counters. + "vigor",//instead of taking damage the source gains +1/+1 counters + "changeling",//this card is every creature type at all times + "absorb",//timeshifted sliver ability. if damage would be dealt to card, prevent 1 of that damage. + "treason", + "unearth", + "cantlose", + "cantlifelose", + "cantmilllose", + "cantcreaturecast", + "cantspellcast", + "onlyonecast", + "storm", + "bothcantcast", + "bothnocreature", + "oneboth", + "affinityartifacts", + "affinityplains", + "affinityforests", + "affinityislands", + "affinitymountains", + "affinityswamps", + "affinitygreencreatures", + "cantwin", + "nomaxhand", + "leyline", + "playershroud", + "controllershroud", + "sunburst", + "flanking", + "exiledeath", }; diff --git a/projects/mtg/src/MTGGamePhase.cpp b/projects/mtg/src/MTGGamePhase.cpp index aa79026ba..c9d994a1c 100644 --- a/projects/mtg/src/MTGGamePhase.cpp +++ b/projects/mtg/src/MTGGamePhase.cpp @@ -2,56 +2,63 @@ #include "MTGGamePhase.h" - -MTGGamePhase::MTGGamePhase(int id):ActionElement(id){ - animation = 0; - currentState = -1; - mFont= resources.GetWFont(Fonts::MAIN_FONT); - mFont->SetBase(0); // using 2nd font -} - - -void MTGGamePhase::Update(float dt){ - - int newState = GameObserver::GetInstance()->getCurrentGamePhase(); - if (newState != currentState){ - activeState = ACTIVE; - animation = 4; - currentState = newState; - } - - - if (animation > 0){ - animation -- ; - }else{ - activeState = INACTIVE; +MTGGamePhase::MTGGamePhase(int id) : + ActionElement(id) +{ animation = 0; + currentState = -1; + mFont = resources.GetWFont(Fonts::MAIN_FONT); + mFont->SetBase(0); // using 2nd font +} - } +void MTGGamePhase::Update(float dt) +{ + + int newState = GameObserver::GetInstance()->getCurrentGamePhase(); + if (newState != currentState) + { + activeState = ACTIVE; + animation = 4; + currentState = newState; + } + + if (animation > 0) + { + animation--; + } + else + { + activeState = INACTIVE; + animation = 0; + + } } -bool MTGGamePhase::CheckUserInput(JButton key){ - GameObserver * game = GameObserver::GetInstance(); - if (activeState == INACTIVE){ - JButton trigger = (options[Options::REVERSETRIGGERS].number ? JGE_BTN_NEXT : JGE_BTN_PREV); - if ((trigger == key) && game->currentActionPlayer == game->currentlyActing()) - { - activeState = ACTIVE; - game->userRequestNextGamePhase(); - return true; - } - } - return false; +bool MTGGamePhase::CheckUserInput(JButton key) +{ + GameObserver * game = GameObserver::GetInstance(); + if (activeState == INACTIVE) + { + JButton trigger = (options[Options::REVERSETRIGGERS].number ? JGE_BTN_NEXT : JGE_BTN_PREV); + if ((trigger == key) && game->currentActionPlayer == game->currentlyActing()) + { + activeState = ACTIVE; + game->userRequestNextGamePhase(); + return true; + } + } + return false; } - MTGGamePhase * MTGGamePhase::clone() const{ - MTGGamePhase * a = NEW MTGGamePhase(*this); +MTGGamePhase * MTGGamePhase::clone() const +{ + MTGGamePhase * a = NEW MTGGamePhase(*this); a->isClone = 1; return a; - } +} ostream& MTGGamePhase::toString(ostream& out) const { - return out << "MTGGamePhase ::: animation " << animation << " ; currentState : " << currentState; + return out << "MTGGamePhase ::: animation " << animation << " ; currentState : " << currentState; } diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 1279c7d1d..d8e96798f 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -14,726 +14,840 @@ //Players Game //------------------------------ -MTGPlayerCards::MTGPlayerCards(int * idList, int idListSize){ - init(); - int i; - for (i=0;igetCardById(idList[i]); - if (card){ - MTGCardInstance * newCard = NEW MTGCardInstance(card, this); - library->addCard(newCard); +MTGPlayerCards::MTGPlayerCards(int * idList, int idListSize) +{ + init(); + int i; + for (i = 0; i < idListSize; i++) + { + MTGCard * card = GameApp::collection->getCardById(idList[i]); + if (card) + { + MTGCardInstance * newCard = NEW MTGCardInstance(card, this); + library->addCard(newCard); + } } - } } -MTGPlayerCards::MTGPlayerCards(MTGDeck * deck){ - init(); - initDeck(deck); +MTGPlayerCards::MTGPlayerCards(MTGDeck * deck) +{ + init(); + initDeck(deck); } - -void MTGPlayerCards::initDeck(MTGDeck * deck){ - resetLibrary(); - map::iterator it; - for (it = deck->cards.begin(); it!=deck->cards.end(); it++){ - MTGCard * card = deck->getCardById(it->first); - if (card){ - for (int i = 0; i < it->second; i++){ - MTGCardInstance * newCard = NEW MTGCardInstance(card, this); - library->addCard(newCard); - } +void MTGPlayerCards::initDeck(MTGDeck * deck) +{ + resetLibrary(); + map::iterator it; + for (it = deck->cards.begin(); it != deck->cards.end(); it++) + { + MTGCard * card = deck->getCardById(it->first); + if (card) + { + for (int i = 0; i < it->second; i++) + { + MTGCardInstance * newCard = NEW MTGCardInstance(card, this); + library->addCard(newCard); + } + } } - } } -MTGPlayerCards::~MTGPlayerCards(){ - SAFE_DELETE(library); - SAFE_DELETE(graveyard); - SAFE_DELETE(hand); - SAFE_DELETE(inPlay); - SAFE_DELETE(stack); - SAFE_DELETE(removedFromGame); - SAFE_DELETE(garbage); - SAFE_DELETE(temp); +MTGPlayerCards::~MTGPlayerCards() +{ + SAFE_DELETE(library); + SAFE_DELETE(graveyard); + SAFE_DELETE(hand); + SAFE_DELETE(inPlay); + SAFE_DELETE(stack); + SAFE_DELETE(removedFromGame); + SAFE_DELETE(garbage); + SAFE_DELETE(temp); } -void MTGPlayerCards::setOwner(Player * player){ - library->setOwner(player); - graveyard->setOwner(player); - hand->setOwner(player); - inPlay->setOwner(player); - removedFromGame->setOwner(player); - stack->setOwner(player); - garbage->setOwner(player); - temp->setOwner(player); +void MTGPlayerCards::setOwner(Player * player) +{ + library->setOwner(player); + graveyard->setOwner(player); + hand->setOwner(player); + inPlay->setOwner(player); + removedFromGame->setOwner(player); + stack->setOwner(player); + garbage->setOwner(player); + temp->setOwner(player); } -void MTGPlayerCards::initGame(int shuffle, int draw){ - if (shuffle) library->shuffle(); - if (draw){ - for (int i=0;i<7;i++){ - drawFromLibrary(); +void MTGPlayerCards::initGame(int shuffle, int draw) +{ + if (shuffle) + library->shuffle(); + if (draw) + { + for (int i = 0; i < 7; i++) + { + drawFromLibrary(); + } } - } } -void MTGPlayerCards::OptimizedHand(int amount,int lands,int creatures,int othercards){ -//give the Ai hand adventage to insure a challanging match. - GameObserver * game = game->GetInstance(); - game->currentPlayerId = game->currentPlayerId; - game->currentPlayer = game->currentPlayer; +void MTGPlayerCards::OptimizedHand(int amount, int lands, int creatures, int othercards) +{ + //give the Ai hand adventage to insure a challanging match. + GameObserver * game = game->GetInstance(); + game->currentPlayerId = game->currentPlayerId; + game->currentPlayer = game->currentPlayer; - if (!game->players[0]->isAI() && game->players[1]->isAI()){ - Player * p = game->players[1]; - MTGCardInstance * card = NULL; - MTGGameZone * z = p->game->library; - MTGGameZone * e = p->game->temp; - int optimizedland = 0; - int optimizedothercards = 0; - int optimizedcreatures = 0; - for (int j = 0; jnb_cards; j++){ - MTGCardInstance * _card = z->cards[j]; -//------------- - if (_card->hasType("Land") && optimizedland < lands){ - card = _card; - if (card){ - p->game->putInZone(card, p->game->library, p->game->hand); - optimizedland += 1; - } - } -//----------------first try to optimize a few cards that cost 2 or less. - if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedothercards < othercards && !_card->hasType("Land") && !_card->hasType("Creature")){ - card = _card; - if (card){ - p->game->putInZone(card, p->game->library, p->game->hand); - optimizedothercards += 1; - } - } - if(_card->getManaCost()->getConvertedCost() <= 2 && optimizedcreatures < creatures && _card->hasType("Creature")){ - card = _card; - if (card){ - p->game->putInZone(card, p->game->library, p->game->hand); - optimizedcreatures += 1; - } - } - } -//--------------incase none of them cost 2 or less(which makes for a really poorly crafted Ai deck), try for 3 or less at this point we're accepting anything but lands under 3 mana--- - for (int k = 0; k < z->nb_cards; k++){ - MTGCardInstance * _card = z->cards[k]; + if (!game->players[0]->isAI() && game->players[1]->isAI()) + { + Player * p = game->players[1]; + MTGCardInstance * card = NULL; + MTGGameZone * z = p->game->library; + MTGGameZone * e = p->game->temp; + int optimizedland = 0; + int optimizedothercards = 0; + int optimizedcreatures = 0; + for (int j = 0; j < z->nb_cards; j++) + { + MTGCardInstance * _card = z->cards[j]; + //------------- + if (_card->hasType("Land") && optimizedland < lands) + { + card = _card; + if (card) + { + p->game->putInZone(card, p->game->library, p->game->hand); + optimizedland += 1; + } + } + //----------------first try to optimize a few cards that cost 2 or less. + if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedothercards < othercards && !_card->hasType("Land") + && !_card->hasType("Creature")) + { + card = _card; + if (card) + { + p->game->putInZone(card, p->game->library, p->game->hand); + optimizedothercards += 1; + } + } + if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedcreatures < creatures && _card->hasType("Creature")) + { + card = _card; + if (card) + { + p->game->putInZone(card, p->game->library, p->game->hand); + optimizedcreatures += 1; + } + } + } + //--------------incase none of them cost 2 or less(which makes for a really poorly crafted Ai deck), try for 3 or less at this point we're accepting anything but lands under 3 mana--- + for (int k = 0; k < z->nb_cards; k++) + { + MTGCardInstance * _card = z->cards[k]; - if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedothercards < othercards && (!_card->hasType("Land") || _card->hasType("Creature"))) - { - card = _card; - if (card) - { - p->game->putInZone(card, p->game->library, p->game->hand); - optimizedothercards += 1; - } - } - if(_card->getManaCost()->getConvertedCost() <= 3 && optimizedcreatures < creatures && (_card->hasType("Creature") || !_card->hasType("Land"))) - { - card = _card; - if (card) - { - p->game->putInZone(card, p->game->library, p->game->hand); - optimizedcreatures += 1; - } - } - } -//--------------add up remaining. only 7 cards are optimized, the remaining cards (if rules change amount) are just drawn. - int leftover = 0; - leftover = amount; - leftover -= optimizedland; - leftover -= optimizedcreatures; - leftover -= optimizedothercards; - for(int i = leftover; i > 0;i--) - { - p->game->drawFromLibrary(); - } + if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedothercards < othercards && (!_card->hasType("Land") + || _card->hasType("Creature"))) + { + card = _card; + if (card) + { + p->game->putInZone(card, p->game->library, p->game->hand); + optimizedothercards += 1; + } + } + if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedcreatures < creatures && (_card->hasType("Creature") + || !_card->hasType("Land"))) + { + card = _card; + if (card) + { + p->game->putInZone(card, p->game->library, p->game->hand); + optimizedcreatures += 1; + } + } + } + //--------------add up remaining. only 7 cards are optimized, the remaining cards (if rules change amount) are just drawn. + int leftover = 0; + leftover = amount; + leftover -= optimizedland; + leftover -= optimizedcreatures; + leftover -= optimizedothercards; + for (int i = leftover; i > 0; i--) + { + p->game->drawFromLibrary(); + } - } -//---------------------------- + } + //---------------------------- } -void MTGPlayerCards::drawFromLibrary(){ - if (!library->nb_cards) { - int cantlosers = 0; +void MTGPlayerCards::drawFromLibrary() +{ + if (!library->nb_cards) + { + int cantlosers = 0; MTGGameZone * z = library->owner->game->inPlay; int nbcards = z->nb_cards; - for (int i = 0; i < nbcards; ++i){ - MTGCardInstance * c = z->cards[i]; - if (c->has(Constants::CANTLOSE) || c->has(Constants::CANTMILLLOSE)){ - cantlosers++; - } - } - MTGGameZone * k = library->owner->opponent()->game->inPlay; - int onbcards = k->nb_cards; - for (int m = 0; m < onbcards; ++m){ - MTGCardInstance * e = k->cards[m]; - if (e->has(Constants::CANTWIN)){ - cantlosers++; - } - } - if(cantlosers < 1){ - GameObserver::GetInstance()->gameOver = library->owner;} - return; - } - MTGCardInstance * toMove = library->cards[library->nb_cards-1]; - library->lastCardDrawn = toMove; - putInZone(toMove, library, hand); -} - -void MTGPlayerCards::resetLibrary(){ - SAFE_DELETE(library); - library = NEW MTGLibrary(); -} - -void MTGPlayerCards::init(){ - library = NEW MTGLibrary(); - graveyard = NEW MTGGraveyard(); - hand = NEW MTGHand(); - inPlay = NEW MTGInPlay(); - battlefield=inPlay; - - stack = NEW MTGStack(); - removedFromGame = NEW MTGRemovedFromGame(); - exile = removedFromGame; - garbage = NEW MTGGameZone(); - temp = NEW MTGGameZone(); -} - - -void MTGPlayerCards::showHand(){ - hand->debugPrint(); -} - -MTGCardInstance * MTGPlayerCards::putInGraveyard(MTGCardInstance * card){ - MTGCardInstance * copy = NULL; - MTGGraveyard * grave = card->owner->game->graveyard; - if (inPlay->hasCard(card)){ - copy = putInZone(card,inPlay, grave); - }else if (stack->hasCard(card)){ - copy = putInZone(card,stack, grave); - }else{ - copy = putInZone(card,hand, grave); - } - return copy; - -} - -MTGCardInstance * MTGPlayerCards::putInExile(MTGCardInstance * card){ - MTGCardInstance * copy = NULL; - MTGRemovedFromGame * exile = card->owner->game->exile; - if (inPlay->hasCard(card)){ - copy = putInZone(card,inPlay, exile); - }else if (stack->hasCard(card)){ - copy = putInZone(card,stack, exile); - }else if(graveyard->hasCard(card)){ - copy = putInZone(card,graveyard, exile); - }else{ - copy = putInZone(card,hand, exile); - } - return copy; -} -MTGCardInstance * MTGPlayerCards::putInLibrary(MTGCardInstance * card){ - MTGCardInstance * copy = NULL; - MTGLibrary * library = card->owner->game->library; - MTGHand * hand = card->owner->game->hand; - if (inPlay->hasCard(card)){ - copy = putInZone(card,inPlay, library); - }else if (stack->hasCard(card)){ - copy = putInZone(card,stack, library); - }else if(graveyard->hasCard(card)){ - copy = putInZone(card,graveyard, library); - }else{ - copy = putInZone(card,hand, library); - } - return copy; -} - -MTGCardInstance * MTGPlayerCards::putInHand(MTGCardInstance * card){ - MTGCardInstance * copy = NULL; - MTGHand * hand = card->owner->game->hand; - if (inPlay->hasCard(card)){ - copy = putInZone(card,inPlay, hand); - }else if (stack->hasCard(card)){ - copy = putInZone(card,stack, hand); - }else if(graveyard->hasCard(card)){ - copy = putInZone(card,graveyard, hand); - }else{ - copy = putInZone(card,hand, hand); - } - return copy; -} - -MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to){ - MTGCardInstance * copy = NULL; - GameObserver *g = GameObserver::GetInstance(); - if (!from || !to) return card; //Error check - - int doCopy = 1; - //When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object - if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && - (from == g->players[0]->game->inPlay || from == g->players[1]->game->inPlay)){ - doCopy = 0; - } - - if ((copy = from->removeCard(card,doCopy))){ - if (options[Options::SFXVOLUME].number > 0){ - if (to == g->players[0]->game->graveyard || to == g->players[1]->game->graveyard){ - if (card->isCreature()){ - JSample * sample = resources.RetrieveSample("graveyard.wav"); - if (sample) JSoundSystem::GetInstance()->PlaySample(sample); + for (int i = 0; i < nbcards; ++i) + { + MTGCardInstance * c = z->cards[i]; + if (c->has(Constants::CANTLOSE) || c->has(Constants::CANTMILLLOSE)) + { + cantlosers++; + } } - } + MTGGameZone * k = library->owner->opponent()->game->inPlay; + int onbcards = k->nb_cards; + for (int m = 0; m < onbcards; ++m) + { + MTGCardInstance * e = k->cards[m]; + if (e->has(Constants::CANTWIN)) + { + cantlosers++; + } + } + if (cantlosers < 1) + { + GameObserver::GetInstance()->gameOver = library->owner; + } + return; } + MTGCardInstance * toMove = library->cards[library->nb_cards - 1]; + library->lastCardDrawn = toMove; + putInZone(toMove, library, hand); +} - MTGCardInstance * ret = copy; +void MTGPlayerCards::resetLibrary() +{ + SAFE_DELETE(library); + library = NEW MTGLibrary(); +} - - to->addCard(copy); +void MTGPlayerCards::init() +{ + library = NEW MTGLibrary(); + graveyard = NEW MTGGraveyard(); + hand = NEW MTGHand(); + inPlay = NEW MTGInPlay(); + battlefield = inPlay; - - //The "Temp" zone are purely for code purposes, and we don't want the abilities engine to - //Trigger when cards move in this zone - // Additionally, when they mve "from" this zone, - // we trick the engine into believing that they moved from the zone the card was previously in - // See http://code.google.com/p/wagic/issues/detail?id=335 + stack = NEW MTGStack(); + removedFromGame = NEW MTGRemovedFromGame(); + exile = removedFromGame; + garbage = NEW MTGGameZone(); + temp = NEW MTGGameZone(); +} + +void MTGPlayerCards::showHand() +{ + hand->debugPrint(); +} + +MTGCardInstance * MTGPlayerCards::putInGraveyard(MTGCardInstance * card) +{ + MTGCardInstance * copy = NULL; + MTGGraveyard * grave = card->owner->game->graveyard; + if (inPlay->hasCard(card)) { - if (to == g->players[0]->game->temp || to == g->players[1]->game->temp){ - //don't send event when moving to temp - return ret; - } + copy = putInZone(card, inPlay, grave); + } + else if (stack->hasCard(card)) + { + copy = putInZone(card, stack, grave); + } + else + { + copy = putInZone(card, hand, grave); + } + return copy; - if (from == g->players[0]->game->temp || from == g->players[1]->game->temp){ - //remove temporary stuff - MTGCardInstance * previous = copy->previous; - MTGCardInstance * previous2 = previous->previous; - from = previous->previousZone; - copy->previous = previous2; - if (previous2) previous2->next = copy; - previous->previous = NULL; - previous->next = NULL; - SAFE_DELETE(previous); - } +} + +MTGCardInstance * MTGPlayerCards::putInExile(MTGCardInstance * card) +{ + MTGCardInstance * copy = NULL; + MTGRemovedFromGame * exile = card->owner->game->exile; + if (inPlay->hasCard(card)) + { + copy = putInZone(card, inPlay, exile); + } + else if (stack->hasCard(card)) + { + copy = putInZone(card, stack, exile); + } + else if (graveyard->hasCard(card)) + { + copy = putInZone(card, graveyard, exile); + } + else + { + copy = putInZone(card, hand, exile); + } + return copy; +} +MTGCardInstance * MTGPlayerCards::putInLibrary(MTGCardInstance * card) +{ + MTGCardInstance * copy = NULL; + MTGLibrary * library = card->owner->game->library; + MTGHand * hand = card->owner->game->hand; + if (inPlay->hasCard(card)) + { + copy = putInZone(card, inPlay, library); + } + else if (stack->hasCard(card)) + { + copy = putInZone(card, stack, library); + } + else if (graveyard->hasCard(card)) + { + copy = putInZone(card, graveyard, library); + } + else + { + copy = putInZone(card, hand, library); + } + return copy; +} + +MTGCardInstance * MTGPlayerCards::putInHand(MTGCardInstance * card) +{ + MTGCardInstance * copy = NULL; + MTGHand * hand = card->owner->game->hand; + if (inPlay->hasCard(card)) + { + copy = putInZone(card, inPlay, hand); + } + else if (stack->hasCard(card)) + { + copy = putInZone(card, stack, hand); + } + else if (graveyard->hasCard(card)) + { + copy = putInZone(card, graveyard, hand); + } + else + { + copy = putInZone(card, hand, hand); + } + return copy; +} + +MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to) +{ + MTGCardInstance * copy = NULL; + GameObserver *g = GameObserver::GetInstance(); + if (!from || !to) + return card; //Error check + + int doCopy = 1; + //When a card is moved from inPlay to inPlay (controller change, for example), it is still the same object + if ((to == g->players[0]->game->inPlay || to == g->players[1]->game->inPlay) && (from == g->players[0]->game->inPlay || from + == g->players[1]->game->inPlay)) + { + doCopy = 0; } - GameObserver *g = GameObserver::GetInstance(); - WEvent * e = NEW WEventZoneChange(copy, from, to); - g->receiveEvent(e); + if ((copy = from->removeCard(card, doCopy))) + { + if (options[Options::SFXVOLUME].number > 0) + { + if (to == g->players[0]->game->graveyard || to == g->players[1]->game->graveyard) + { + if (card->isCreature()) + { + JSample * sample = resources.RetrieveSample("graveyard.wav"); + if (sample) + JSoundSystem::GetInstance()->PlaySample(sample); + } + } + } - return ret; - } - return card; //Error + MTGCardInstance * ret = copy; + + to->addCard(copy); + + //The "Temp" zone are purely for code purposes, and we don't want the abilities engine to + //Trigger when cards move in this zone + // Additionally, when they mve "from" this zone, + // we trick the engine into believing that they moved from the zone the card was previously in + // See http://code.google.com/p/wagic/issues/detail?id=335 + { + if (to == g->players[0]->game->temp || to == g->players[1]->game->temp) + { + //don't send event when moving to temp + return ret; + } + + if (from == g->players[0]->game->temp || from == g->players[1]->game->temp) + { + //remove temporary stuff + MTGCardInstance * previous = copy->previous; + MTGCardInstance * previous2 = previous->previous; + from = previous->previousZone; + copy->previous = previous2; + if (previous2) + previous2->next = copy; + previous->previous = NULL; + previous->next = NULL; + SAFE_DELETE(previous); + } + } + + GameObserver *g = GameObserver::GetInstance(); + WEvent * e = NEW WEventZoneChange(copy, from, to); + g->receiveEvent(e); + + return ret; + } + return card; //Error } -void MTGPlayerCards::discardRandom(MTGGameZone * from,MTGCardInstance * source){ - if (!from->nb_cards) - return; - int r = WRand() % (from->nb_cards); - WEvent * e = NEW WEventCardDiscard(from->cards[r]); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); - putInZone(from->cards[r],from, graveyard); +void MTGPlayerCards::discardRandom(MTGGameZone * from, MTGCardInstance * source) +{ + if (!from->nb_cards) + return; + int r = WRand() % (from->nb_cards); + WEvent * e = NEW WEventCardDiscard(from->cards[r]); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); + putInZone(from->cards[r], from, graveyard); } -int MTGPlayerCards::isInPlay(MTGCardInstance * card){ - if (inPlay->hasCard(card)){ - return 1; - } - return 0; +int MTGPlayerCards::isInPlay(MTGCardInstance * card) +{ + if (inPlay->hasCard(card)) + { + return 1; + } + return 0; } //-------------------------------------- // Zones specific code //-------------------------------------- -MTGGameZone::MTGGameZone() : nb_cards(0), lastCardDrawn(NULL), needShuffle(false) { +MTGGameZone::MTGGameZone() : + nb_cards(0), lastCardDrawn(NULL), needShuffle(false) +{ } -MTGGameZone::~MTGGameZone(){ - for (int i=0; iowner = player; - cards[i]->lastController = player; - } - owner = player; -} - -MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card, int createCopy){ - assert(nb_cards < 10000); - int i; - cardsMap.erase(card); - for (i=0; i<(nb_cards); i++) { - if (cards[i] == card){ - card->currentZone = NULL; - nb_cards--; - cards.erase(cards.begin()+i); - MTGCardInstance * copy = card; - //if (card->isToken) //TODO better than this ? - // return card; - //card->lastController = card->controller(); - if (createCopy) { - copy = NEW MTGCardInstance(card->model,card->owner->game); - copy->previous = card; - copy->view = card->view; - copy->isToken = card->isToken; - copy->X = card->X; - - //stupid bug with tokens... - if (card->model == card) - copy->model = copy; - if (card->data == card) - copy->data = copy; - - card->next = copy; - } - copy->previousZone = this; - return copy; +MTGGameZone::~MTGGameZone() +{ + for (int i = 0; i < nb_cards; i++) + { + SAFE_DELETE( cards[i] ); } - } - return NULL; - + cards.clear(); + cardsMap.clear(); + owner = NULL; } -MTGCardInstance * MTGGameZone::hasCard(MTGCardInstance * card){ - if (card->currentZone == this) return card; - return NULL; - -} - -int MTGGameZone::countByType(const char * value){ - int result = 0 ; - for (int i=0; i<(nb_cards); i++) { - if (cards[i]->hasType(value)){ - result++; +void MTGGameZone::setOwner(Player * player) +{ + for (int i = 0; i < nb_cards; i++) + { + cards[i]->owner = player; + cards[i]->lastController = player; } - } - return result; - + owner = player; } -MTGCardInstance * MTGGameZone::findByName(string name){ - for (int i=0; i<(nb_cards); i++) { - if (cards[i]->name == name){ - return cards[i]; +MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card, int createCopy) +{ + assert(nb_cards < 10000); + int i; + cardsMap.erase(card); + for (i = 0; i < (nb_cards); i++) + { + if (cards[i] == card) + { + card->currentZone = NULL; + nb_cards--; + cards.erase(cards.begin() + i); + MTGCardInstance * copy = card; + //if (card->isToken) //TODO better than this ? + // return card; + //card->lastController = card->controller(); + if (createCopy) + { + copy = NEW MTGCardInstance(card->model, card->owner->game); + copy->previous = card; + copy->view = card->view; + copy->isToken = card->isToken; + copy->X = card->X; + + //stupid bug with tokens... + if (card->model == card) + copy->model = copy; + if (card->data == card) + copy->data = copy; + + card->next = copy; + } + copy->previousZone = this; + return copy; + } } - } - return NULL; + return NULL; + } -int MTGGameZone::hasType(const char * value){ - for (int i=0; i<(nb_cards); i++) { - if (cards[i]->hasType(value)){ - return 1; +MTGCardInstance * MTGGameZone::hasCard(MTGCardInstance * card) +{ + if (card->currentZone == this) + return card; + return NULL; + +} + +int MTGGameZone::countByType(const char * value) +{ + int result = 0; + for (int i = 0; i < (nb_cards); i++) + { + if (cards[i]->hasType(value)) + { + result++; + } } - } - return 0; + return result; + } -int MTGGameZone::hasAbility(int ability){ - for (int i=0; i<(nb_cards); i++) { - if (cards[i]->basicAbilities[ability]){ - return 1; +MTGCardInstance * MTGGameZone::findByName(string name) +{ + for (int i = 0; i < (nb_cards); i++) + { + if (cards[i]->name == name) + { + return cards[i]; + } } - } - return 0; + return NULL; } - -void MTGGameZone::cleanupPhase(){ - for (int i=0; i<(nb_cards); i++) - (cards[i])->cleanup(); +int MTGGameZone::hasType(const char * value) +{ + for (int i = 0; i < (nb_cards); i++) + { + if (cards[i]->hasType(value)) + { + return 1; + } + } + return 0; } -void MTGGameZone::shuffle(){ - int i; - for (i=0; i<(nb_cards); i++) { - int r = i + (WRand() % (nb_cards-i)); // Random remaining position. - MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp; - } +int MTGGameZone::hasAbility(int ability) +{ + for (int i = 0; i < (nb_cards); i++) + { + if (cards[i]->basicAbilities[ability]) + { + return 1; + } + } + return 0; } +void MTGGameZone::cleanupPhase() +{ + for (int i = 0; i < (nb_cards); i++) + (cards[i])->cleanup(); +} +void MTGGameZone::shuffle() +{ + int i; + for (i = 0; i < (nb_cards); i++) + { + int r = i + (WRand() % (nb_cards - i)); // Random remaining position. + MTGCardInstance * temp = cards[i]; + cards[i] = cards[r]; + cards[r] = temp; + } +} -void MTGGameZone::addCard(MTGCardInstance * card){ - if (!card) return; - cards.push_back(card); - nb_cards++; - cardsMap[card] = 1; - card->lastController = this->owner; - card->currentZone = this; +void MTGGameZone::addCard(MTGCardInstance * card) +{ + if (!card) + return; + cards.push_back(card); + nb_cards++; + cardsMap[card] = 1; + card->lastController = this->owner; + card->currentZone = this; } - -void MTGGameZone::debugPrint(){ - for (int i = 0; i < nb_cards; i++) - std::cerr << cards[i]->getName() << endl; +void MTGGameZone::debugPrint() +{ + for (int i = 0; i < nb_cards; i++) + std::cerr << cards[i]->getName() << endl; } - - - - //------------------------------ -MTGCardInstance * MTGInPlay::getNextAttacker(MTGCardInstance * previous){ - int foundprevious = 0; - if (previous == NULL){ - foundprevious = 1; - } - for (int i = 0; i < nb_cards; i ++){ - MTGCardInstance * current = cards[i]; - if (current == previous){ - foundprevious = 1; - }else if (foundprevious && current->isAttacker()){ - return current; +MTGCardInstance * MTGInPlay::getNextAttacker(MTGCardInstance * previous) +{ + int foundprevious = 0; + if (previous == NULL) + { + foundprevious = 1; } - } - return NULL; + for (int i = 0; i < nb_cards; i++) + { + MTGCardInstance * current = cards[i]; + if (current == previous) + { + foundprevious = 1; + } + else if (foundprevious && current->isAttacker()) + { + return current; + } + } + return NULL; } -void MTGInPlay::untapAll(){ - int i; - for (i = 0; i < nb_cards; i ++){ - MTGCardInstance * card = cards[i]; - card->setUntapping(); - if (!card->basicAbilities[Constants::DOESNOTUNTAP]){ - if(card->frozen < 1) {card->attemptUntap();} - if(card->frozen >= 1) {card->frozen = 0;} +void MTGInPlay::untapAll() +{ + int i; + for (i = 0; i < nb_cards; i++) + { + MTGCardInstance * card = cards[i]; + card->setUntapping(); + if (!card->basicAbilities[Constants::DOESNOTUNTAP]) + { + if (card->frozen < 1) + { + card->attemptUntap(); + } + if (card->frozen >= 1) + { + card->frozen = 0; + } - } - } + } + } } - //-------------------------- -void MTGLibrary::shuffleTopToBottom(int nbcards){ - if (nbcards>nb_cards) nbcards = nb_cards; - if (nbcards < 0) return; - MTGCardInstance * _cards[MTG_MAX_PLAYER_CARDS]; - for (int i= nb_cards-nbcards; i<(nb_cards); i++) { - int r = i + (WRand() % (nbcards-i)); // Random remaining position. - MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp; - } - for (int i= 0; i < nbcards; i++){ - _cards[i] = cards[nb_cards - 1 - i]; - } - for (int i = nbcards; i < nb_cards; i++){ - _cards[i] = cards[i - nb_cards]; - } - for (int i=0 ; i < nb_cards; i++){ - cards[i] = _cards[i]; - } -} - - -MTGGameZone * MTGGameZone::intToZone(int zoneId, MTGCardInstance * source,MTGCardInstance * target){ - Player *p, *p2; - GameObserver * g = GameObserver::GetInstance(); - if (!source) p = g->currentlyActing(); - else p = source->controller(); - if (!target){ - p2 = p; - target = source;//hack ? - } - else p2 = target->controller(); - - switch(zoneId){ - case MY_GRAVEYARD: return p->game->graveyard; - case OPPONENT_GRAVEYARD: return p->opponent()->game->graveyard; - case TARGET_OWNER_GRAVEYARD : return target->owner->game->graveyard; - case TARGET_CONTROLLER_GRAVEYARD: return p2->game->graveyard; - case GRAVEYARD : return target->owner->game->graveyard; - case OWNER_GRAVEYARD : return target->owner->game->graveyard; - - case MY_BATTLEFIELD : return p->game->inPlay; - case OPPONENT_BATTLEFIELD : return p->opponent()->game->inPlay; - case TARGET_OWNER_BATTLEFIELD : return target->owner->game->inPlay; - case TARGET_CONTROLLER_BATTLEFIELD : return p2->game->inPlay; - case BATTLEFIELD : return p->game->inPlay; - case OWNER_BATTLEFIELD : return target->owner->game->inPlay; - - case MY_HAND : return p->game->hand; - case OPPONENT_HAND : return p->opponent()->game->hand; - case TARGET_OWNER_HAND : return target->owner->game->hand; - case TARGET_CONTROLLER_HAND : return p2->game->hand; - case HAND : return target->owner->game->hand; - case OWNER_HAND : return target->owner->game->hand; - - case MY_EXILE : return p->game->removedFromGame; - case OPPONENT_EXILE : return p->opponent()->game->removedFromGame; - case TARGET_OWNER_EXILE : return target->owner->game->removedFromGame; - case TARGET_CONTROLLER_EXILE : return p2->game->removedFromGame; - case EXILE : return target->owner->game->removedFromGame; - case OWNER_EXILE : return target->owner->game->removedFromGame; - - case MY_LIBRARY : return p->game->library; - case OPPONENT_LIBRARY : return p->opponent()->game->library; - case TARGET_OWNER_LIBRARY : return target->owner->game->library; - case TARGET_CONTROLLER_LIBRARY : return p2->game->library; - case LIBRARY : return p->game->library; - case OWNER_LIBRARY: return target->owner->game->library; - - case MY_STACK : return p->game->stack; - case OPPONENT_STACK : return p->opponent()->game->stack; - case TARGET_OWNER_STACK : return target->owner->game->stack; - case TARGET_CONTROLLER_STACK : return p2->game->stack; - case STACK : return p->game->stack; - case OWNER_STACK: return target->owner->game->stack; - default: - return NULL; - } -} - -int MTGGameZone::zoneStringToId(string zoneName){ - const char * strings[] = { - "mygraveyard", - "opponentgraveyard", - "targetownergraveyard", - "targetcontrollergraveyard", - "ownergraveyard", - "graveyard", - - "myinplay", - "opponentinplay", - "targetownerinplay", - "targetcontrollerinplay", - "ownerinplay", - "inplay", - - "mybattlefield", - "opponentbattlefield", - "targetownerbattlefield", - "targetcontrollerbattlefield", - "ownerbattlefield", - "battlefield", - - "myhand", - "opponenthand", - "targetownerhand", - "targetcontrollerhand", - "ownerhand", - "hand", - - "mylibrary", - "opponentlibrary", - "targetownerlibrary", - "targetcontrollerlibrary", - "ownerlibrary", - "library", - - "myremovedfromgame", - "opponentremovedfromgame", - "targetownerremovedfromgame", - "targetcontrollerremovedfromgame", - "ownerremovedfromgame", - "removedfromgame", - - "myexile", - "opponentexile", - "targetownerexile", - "targetcontrollerexile", - "ownerexile", - "exile", - - "mystack", - "opponentstack", - "targetownerstack", - "targetcontrollerstack", - "ownerstack", - "stack", - - }; - - int values[] = { - MY_GRAVEYARD, - OPPONENT_GRAVEYARD, - TARGET_OWNER_GRAVEYARD , - TARGET_CONTROLLER_GRAVEYARD, - OWNER_GRAVEYARD , - GRAVEYARD, - - MY_BATTLEFIELD, - OPPONENT_BATTLEFIELD, - TARGET_OWNER_BATTLEFIELD , - TARGET_CONTROLLER_BATTLEFIELD, - OWNER_BATTLEFIELD , - BATTLEFIELD, - - MY_BATTLEFIELD, - OPPONENT_BATTLEFIELD, - TARGET_OWNER_BATTLEFIELD , - TARGET_CONTROLLER_BATTLEFIELD, - OWNER_BATTLEFIELD , - BATTLEFIELD, - - MY_HAND, - OPPONENT_HAND, - TARGET_OWNER_HAND , - TARGET_CONTROLLER_HAND, - OWNER_HAND , - HAND, - - MY_LIBRARY, - OPPONENT_LIBRARY, - TARGET_OWNER_LIBRARY , - TARGET_CONTROLLER_LIBRARY, - OWNER_LIBRARY , - LIBRARY, - - MY_EXILE, - OPPONENT_EXILE, - TARGET_OWNER_EXILE , - TARGET_CONTROLLER_EXILE, - OWNER_EXILE , - EXILE, - - MY_EXILE, - OPPONENT_EXILE, - TARGET_OWNER_EXILE , - TARGET_CONTROLLER_EXILE, - OWNER_EXILE , - EXILE, - - MY_STACK, - OPPONENT_STACK, - TARGET_OWNER_STACK , - TARGET_CONTROLLER_STACK, - OWNER_STACK , - STACK, - }; - - int max = sizeof(values) / sizeof*(values); - - for (int i = 0; i < max; ++i){ - if(zoneName.compare(strings[i]) == 0){ - return values[i]; +void MTGLibrary::shuffleTopToBottom(int nbcards) +{ + if (nbcards > nb_cards) + nbcards = nb_cards; + if (nbcards < 0) + return; + MTGCardInstance * _cards[MTG_MAX_PLAYER_CARDS]; + for (int i = nb_cards - nbcards; i < (nb_cards); i++) + { + int r = i + (WRand() % (nbcards - i)); // Random remaining position. + MTGCardInstance * temp = cards[i]; + cards[i] = cards[r]; + cards[r] = temp; + } + for (int i = 0; i < nbcards; i++) + { + _cards[i] = cards[nb_cards - 1 - i]; + } + for (int i = nbcards; i < nb_cards; i++) + { + _cards[i] = cards[i - nb_cards]; + } + for (int i = 0; i < nb_cards; i++) + { + cards[i] = _cards[i]; } - } - return 0; } -MTGGameZone * MTGGameZone::stringToZone(string zoneName, MTGCardInstance * source,MTGCardInstance * target){ - return intToZone(zoneStringToId(zoneName), source,target); +MTGGameZone * MTGGameZone::intToZone(int zoneId, MTGCardInstance * source, MTGCardInstance * target) +{ + Player *p, *p2; + GameObserver * g = GameObserver::GetInstance(); + if (!source) + p = g->currentlyActing(); + else + p = source->controller(); + if (!target) + { + p2 = p; + target = source;//hack ? + } + else + p2 = target->controller(); + + switch (zoneId) + { + case MY_GRAVEYARD: + return p->game->graveyard; + case OPPONENT_GRAVEYARD: + return p->opponent()->game->graveyard; + case TARGET_OWNER_GRAVEYARD: + return target->owner->game->graveyard; + case TARGET_CONTROLLER_GRAVEYARD: + return p2->game->graveyard; + case GRAVEYARD: + return target->owner->game->graveyard; + case OWNER_GRAVEYARD: + return target->owner->game->graveyard; + + case MY_BATTLEFIELD: + return p->game->inPlay; + case OPPONENT_BATTLEFIELD: + return p->opponent()->game->inPlay; + case TARGET_OWNER_BATTLEFIELD: + return target->owner->game->inPlay; + case TARGET_CONTROLLER_BATTLEFIELD: + return p2->game->inPlay; + case BATTLEFIELD: + return p->game->inPlay; + case OWNER_BATTLEFIELD: + return target->owner->game->inPlay; + + case MY_HAND: + return p->game->hand; + case OPPONENT_HAND: + return p->opponent()->game->hand; + case TARGET_OWNER_HAND: + return target->owner->game->hand; + case TARGET_CONTROLLER_HAND: + return p2->game->hand; + case HAND: + return target->owner->game->hand; + case OWNER_HAND: + return target->owner->game->hand; + + case MY_EXILE: + return p->game->removedFromGame; + case OPPONENT_EXILE: + return p->opponent()->game->removedFromGame; + case TARGET_OWNER_EXILE: + return target->owner->game->removedFromGame; + case TARGET_CONTROLLER_EXILE: + return p2->game->removedFromGame; + case EXILE: + return target->owner->game->removedFromGame; + case OWNER_EXILE: + return target->owner->game->removedFromGame; + + case MY_LIBRARY: + return p->game->library; + case OPPONENT_LIBRARY: + return p->opponent()->game->library; + case TARGET_OWNER_LIBRARY: + return target->owner->game->library; + case TARGET_CONTROLLER_LIBRARY: + return p2->game->library; + case LIBRARY: + return p->game->library; + case OWNER_LIBRARY: + return target->owner->game->library; + + case MY_STACK: + return p->game->stack; + case OPPONENT_STACK: + return p->opponent()->game->stack; + case TARGET_OWNER_STACK: + return target->owner->game->stack; + case TARGET_CONTROLLER_STACK: + return p2->game->stack; + case STACK: + return p->game->stack; + case OWNER_STACK: + return target->owner->game->stack; + default: + return NULL; + } } -ostream& MTGGameZone::toString(ostream& out) const { return out << "Unknown zone"; } -ostream& MTGLibrary::toString(ostream& out) const { return out << "Library " << *owner; } -ostream& MTGGraveyard::toString(ostream& out) const { return out << "Graveyard " << *owner; } -ostream& MTGHand::toString(ostream& out) const { return out << "Hand " << *owner; } -ostream& MTGRemovedFromGame::toString(ostream& out) const { return out << "RemovedFromGame " << *owner; } -ostream& MTGStack::toString(ostream& out) const { return out << "Stack " << *owner; } -ostream& MTGInPlay::toString(ostream& out) const { return out << "InPlay " << *owner; } +int MTGGameZone::zoneStringToId(string zoneName) +{ + const char * strings[] = { "mygraveyard", "opponentgraveyard", "targetownergraveyard", "targetcontrollergraveyard", + "ownergraveyard", "graveyard", + + "myinplay", "opponentinplay", "targetownerinplay", "targetcontrollerinplay", "ownerinplay", "inplay", + + "mybattlefield", "opponentbattlefield", "targetownerbattlefield", "targetcontrollerbattlefield", + "ownerbattlefield", "battlefield", + + "myhand", "opponenthand", "targetownerhand", "targetcontrollerhand", "ownerhand", "hand", + + "mylibrary", "opponentlibrary", "targetownerlibrary", "targetcontrollerlibrary", "ownerlibrary", "library", + + "myremovedfromgame", "opponentremovedfromgame", "targetownerremovedfromgame", + "targetcontrollerremovedfromgame", "ownerremovedfromgame", "removedfromgame", + + "myexile", "opponentexile", "targetownerexile", "targetcontrollerexile", "ownerexile", "exile", + + "mystack", "opponentstack", "targetownerstack", "targetcontrollerstack", "ownerstack", "stack", + + }; + + int values[] = { MY_GRAVEYARD, OPPONENT_GRAVEYARD, TARGET_OWNER_GRAVEYARD, TARGET_CONTROLLER_GRAVEYARD, OWNER_GRAVEYARD, + GRAVEYARD, + + MY_BATTLEFIELD, OPPONENT_BATTLEFIELD, TARGET_OWNER_BATTLEFIELD, TARGET_CONTROLLER_BATTLEFIELD, + OWNER_BATTLEFIELD, BATTLEFIELD, + + MY_BATTLEFIELD, OPPONENT_BATTLEFIELD, TARGET_OWNER_BATTLEFIELD, TARGET_CONTROLLER_BATTLEFIELD, + OWNER_BATTLEFIELD, BATTLEFIELD, + + MY_HAND, OPPONENT_HAND, TARGET_OWNER_HAND, TARGET_CONTROLLER_HAND, OWNER_HAND, HAND, + + MY_LIBRARY, OPPONENT_LIBRARY, TARGET_OWNER_LIBRARY, TARGET_CONTROLLER_LIBRARY, OWNER_LIBRARY, LIBRARY, + + MY_EXILE, OPPONENT_EXILE, TARGET_OWNER_EXILE, TARGET_CONTROLLER_EXILE, OWNER_EXILE, EXILE, + + MY_EXILE, OPPONENT_EXILE, TARGET_OWNER_EXILE, TARGET_CONTROLLER_EXILE, OWNER_EXILE, EXILE, + + MY_STACK, OPPONENT_STACK, TARGET_OWNER_STACK, TARGET_CONTROLLER_STACK, OWNER_STACK, STACK, }; + + int max = sizeof(values) / sizeof *(values); + + for (int i = 0; i < max; ++i) + { + if (zoneName.compare(strings[i]) == 0) + { + return values[i]; + } + } + return 0; +} + +MTGGameZone * MTGGameZone::stringToZone(string zoneName, MTGCardInstance * source, MTGCardInstance * target) +{ + return intToZone(zoneStringToId(zoneName), source, target); +} + +ostream& MTGGameZone::toString(ostream& out) const +{ + return out << "Unknown zone"; +} +ostream& MTGLibrary::toString(ostream& out) const +{ + return out << "Library " << *owner; +} +ostream& MTGGraveyard::toString(ostream& out) const +{ + return out << "Graveyard " << *owner; +} +ostream& MTGHand::toString(ostream& out) const +{ + return out << "Hand " << *owner; +} +ostream& MTGRemovedFromGame::toString(ostream& out) const +{ + return out << "RemovedFromGame " << *owner; +} +ostream& MTGStack::toString(ostream& out) const +{ + return out << "Stack " << *owner; +} +ostream& MTGInPlay::toString(ostream& out) const +{ + return out << "InPlay " << *owner; +} ostream& operator<<(ostream& out, const MTGGameZone& z) { - return z.toString(out); + return z.toString(out); } diff --git a/projects/mtg/src/MTGPack.cpp b/projects/mtg/src/MTGPack.cpp index 0cd1d4dd9..26138f5aa 100644 --- a/projects/mtg/src/MTGPack.cpp +++ b/projects/mtg/src/MTGPack.cpp @@ -13,296 +13,385 @@ MTGPack MTGPacks::defaultBooster; -int MTGPackEntryRandom::addCard(WSrcCards *pool, MTGDeck *to){ - int fails = 0; - if(!pool) return 1; - WCFilterFactory * ff = WCFilterFactory::GetInstance(); - WCardFilter * oldf = pool->unhookFilters(); - pool->addFilter(ff->Construct(filter)); - fails = pool->addRandomCards(to,copies); - pool->clearFilters(); - pool->addFilter(oldf); - return fails; +int MTGPackEntryRandom::addCard(WSrcCards *pool, MTGDeck *to) +{ + int fails = 0; + if (!pool) + return 1; + WCFilterFactory * ff = WCFilterFactory::GetInstance(); + WCardFilter * oldf = pool->unhookFilters(); + pool->addFilter(ff->Construct(filter)); + fails = pool->addRandomCards(to, copies); + pool->clearFilters(); + pool->addFilter(oldf); + return fails; } -int MTGPackEntrySpecific::addCard(WSrcCards *pool, MTGDeck *to){ - int fails = 0; - //Ignores pool entirely. - MTGAllCards * ac = GameApp::collection; - - if(!card) return copies; - for(int i=0;iadd(card); - return 0; +int MTGPackEntrySpecific::addCard(WSrcCards *pool, MTGDeck *to) +{ + int fails = 0; + //Ignores pool entirely. + MTGAllCards * ac = GameApp::collection; + + if (!card) + return copies; + for (int i = 0; i < copies; i++) + to->add(card); + return 0; } -int MTGPackSlot::add(WSrcCards * ocean, MTGDeck *to, int carryover){ - if(!entries.size()) return copies; - int fails = 0; - int amt = copies + carryover; - WSrcCards * myPool = NULL; - if(pool.size()) myPool = MTGPack::getPool(pool); - if(!myPool) myPool = ocean; - for(int i=0;iaddCard(myPool,to)) - pos++; - if(pos == entries.size()) - fails++; - } - if(myPool != ocean) - SAFE_DELETE(myPool); - return fails; -} - -WSrcCards * MTGPack::getPool(string poolstr){ - WSrcCards * mySrc = NULL; - size_t s = poolstr.find("all"); - WCFilterFactory * ff = WCFilterFactory::GetInstance(); - - if(s == string::npos){ //Default to just unlocked cards - mySrc = NEW WSrcUnlockedCards(); - s = poolstr.find("unlocked"); - string sub = poolstr; - if(s != string::npos) sub = poolstr.substr(s+8); - if(sub.size()){ - mySrc->addFilter(ff->Construct(sub)); - mySrc->bakeFilters(); +int MTGPackSlot::add(WSrcCards * ocean, MTGDeck *to, int carryover) +{ + if (!entries.size()) + return copies; + int fails = 0; + int amt = copies + carryover; + WSrcCards * myPool = NULL; + if (pool.size()) + myPool = MTGPack::getPool(pool); + if (!myPool) + myPool = ocean; + for (int i = 0; i < amt; i++) + { + size_t pos = rand() % entries.size(); + while (pos < entries.size() && entries[pos]->addCard(myPool, to)) + pos++; + if (pos == entries.size()) + fails++; } - } - else{ //Use everything. - mySrc = NEW WSrcCards(); - string sub = poolstr.substr(s+3); - if(sub.size()){ - mySrc->addFilter(ff->Construct(sub)); - mySrc->loadMatches(GameApp::collection); - mySrc->bakeFilters(); - }else - mySrc->loadMatches(GameApp::collection); - } - mySrc->Shuffle(); - return mySrc; + if (myPool != ocean) + SAFE_DELETE(myPool); + return fails; } -void MTGPackSlot::addEntry(MTGPackEntry*item){ - if(item) - entries.push_back(item); -} -int MTGPack::assemblePack(MTGDeck *to){ - int carryover = 0; - WSrcCards * p = getPool(pool); - if(!p) return -1; - p->Shuffle(); - - for(size_t i=0;iadd(p,to,carryover); - if(carryover > 0) - carryover = carryover; //This means we're failing. - } - SAFE_DELETE(p); - return carryover; -} -void MTGPack::countCards(){ - minCards = 0; - maxCards = 0; - for(size_t i=0;ientries.size();y++){ - int test = ps->entries[y]->copies * ps->copies; - if(test > top) top = test; - if(test < bot) bot = test; +WSrcCards * MTGPack::getPool(string poolstr) +{ + WSrcCards * mySrc = NULL; + size_t s = poolstr.find("all"); + WCFilterFactory * ff = WCFilterFactory::GetInstance(); + + if (s == string::npos) + { //Default to just unlocked cards + mySrc = NEW WSrcUnlockedCards(); + s = poolstr.find("unlocked"); + string sub = poolstr; + if (s != string::npos) + sub = poolstr.substr(s + 8); + if (sub.size()) + { + mySrc->addFilter(ff->Construct(sub)); + mySrc->bakeFilters(); + } } - maxCards += top; - minCards += bot; - } -} -void MTGPack::load(string filename){ - //TODO Placeholder until XML format available. - TiXmlDocument packfile(filename.c_str()); - if(!packfile.LoadFile()) - return; - TiXmlHandle hDoc(&packfile); - TiXmlElement * pPack; - pPack = hDoc.FirstChildElement().Element(); - if(!pPack ){ - - return; - } - //root should be "pack" - string tag = pPack->Value(); - std::transform(tag.begin(),tag.end(),tag.begin(),::tolower); - if(tag != "pack") - return; - //After validating, handle actual loading. - TiXmlElement * pSlot; - const char * holder = NULL; - holder = pPack->Attribute("price"); - if(holder) price = atoi(holder); else price = Constants::PRICE_BOOSTER; - holder = pPack->Attribute("pool"); - if(holder) pool = holder; else pool = ""; - holder = pPack->Attribute("type"); - if(holder){ - type = holder; - }else type = "Booster"; - holder = pPack->Attribute("name"); - if(holder) name = holder; else name = "Special"; - holder = pPack->Attribute("requires"); - if(holder) check = holder; - holder = pPack->Attribute("sort"); - if(holder) sort = holder; else sort = ""; - std::transform(sort.begin(),sort.end(),sort.begin(),::tolower); - - for (pSlot=pPack->FirstChildElement();pSlot!=NULL;pSlot=pSlot->NextSiblingElement()){ - TiXmlElement * pEntry; - //Load slot. - tag = pSlot->Value(); - std::transform(tag.begin(),tag.end(),tag.begin(),::tolower); - if(tag != "slot") continue; - MTGPackSlot * s = NEW MTGPackSlot(); - slotss.push_back(s); - holder = pSlot->Attribute("copies"); - if(holder) s->copies = atoi(holder); - else s->copies = 1; - holder = pSlot->Attribute("pool"); - if(holder) s->pool = holder; - - for(pEntry = pSlot->FirstChildElement();pEntry!=NULL;pEntry=pEntry->NextSiblingElement()){ - tag = pEntry->Value(); - std::transform(tag.begin(),tag.end(),tag.begin(),::tolower); - if(tag == "card"){ //Load specific card - MTGPackEntrySpecific * es = NEW MTGPackEntrySpecific(); - holder = pEntry->Attribute("copies"); - if(holder) es->copies = atoi(holder); - else es->copies = 1; - es->card = GameApp::collection->getCardByName(pEntry->Value()); - s->addEntry(es); - }else if(tag == "random_card"){ //Load random card - MTGPackEntryRandom * er = NEW MTGPackEntryRandom(); - holder = pEntry->Attribute("copies"); - if(holder) er->copies = atoi(holder); - else er->copies = 1; - const char * text = pEntry->GetText(); - if(text) er->filter = text; - s->addEntry(er); - }else if(tag == "nothing"){ - MTGPackEntryNothing * nt = NEW MTGPackEntryNothing(); - s->addEntry(nt); - } - } - } - bValid = true; - countCards(); - return; -} -MTGPackSlot::~MTGPackSlot(){ - for(size_t t=0;td_name); - if(mDit->d_name[0] == '.') continue; - if(!strcmp(mDit->d_name,"default_booster.txt")) continue; - MTGPack * p = NEW MTGPack(myFilename); - if(!p->isValid()){ - SAFE_DELETE(p); - continue; - } - packs.push_back(p); - } - closedir(mDip); -} -string MTGPack::getName(){ - string n = _(name); - string t = _(type); - char buf[1024]; - if(minCards != maxCards) - sprintf(buf,"%s %s (%i-%i cards)",n.c_str(),t.c_str(),minCards,maxCards); - else - sprintf(buf,"%s %s (%i cards)",n.c_str(),t.c_str(),maxCards); - return buf; -} - -bool MTGPack::meetsRequirements(){ - bool unlocked = true; - WCFilterFactory * ff = WCFilterFactory::GetInstance(); - WSrcCards * myC = getPool(pool); - if(!myC || myC->Size() < maxCards) unlocked = false; //Top pool lacks cards. - SAFE_DELETE(myC); - if(!check.size() || !unlocked) return unlocked; - myC = NEW WSrcUnlockedCards(); //Requirements are independent of pool; - WCardFilter * cf = ff->Construct(check); - unlocked = !myC->isEmptySet(cf); //Quick check for empty set status. - SAFE_DELETE(cf); //delete requirement filter - SAFE_DELETE(myC); //delete pool. - return unlocked; -} - -bool MTGPack::isUnlocked(){ - if(unlockStatus == 0){ - if(meetsRequirements()) - unlockStatus = 1; else - unlockStatus = -1; - } - return (unlockStatus > 0); -} - -MTGPack * MTGPacks::getDefault(){ - if(!defaultBooster.isValid()){ - defaultBooster.load(JGE_GET_RES("packs/default_booster.txt")); - defaultBooster.unlockStatus = 1; - if(!defaultBooster.isValid()){ - MTGPackSlot * ps = NEW MTGPackSlot(); ps->copies = 1; - ps->addEntry(NEW MTGPackEntryRandom("rarity:mythic;")); - for(int i=0;i<7;i++) - ps->addEntry(NEW MTGPackEntryRandom("rarity:rare;")); - defaultBooster.slotss.push_back(ps); - ps = NEW MTGPackSlot(); ps->copies = 3; - ps->addEntry(NEW MTGPackEntryRandom("rarity:uncommon;")); - defaultBooster.slotss.push_back(ps); - ps = NEW MTGPackSlot(); ps->copies = 1; - ps->addEntry(NEW MTGPackEntryRandom("rarity:land;&type:basic;")); - defaultBooster.slotss.push_back(ps); - ps = NEW MTGPackSlot(); ps->copies = 10; - ps->addEntry(NEW MTGPackEntryRandom("rarity:common;")); - defaultBooster.slotss.push_back(ps); - defaultBooster.bValid = true; - defaultBooster.unlockStatus = 1; + { //Use everything. + mySrc = NEW WSrcCards(); + string sub = poolstr.substr(s + 3); + if (sub.size()) + { + mySrc->addFilter(ff->Construct(sub)); + mySrc->loadMatches(GameApp::collection); + mySrc->bakeFilters(); + } + else + mySrc->loadMatches(GameApp::collection); } - } - return &defaultBooster; + mySrc->Shuffle(); + return mySrc; } -void MTGPacks::refreshUnlocked(){ - for(size_t t=0;tunlockStatus < 0) - packs[t]->unlockStatus = 0; - } +void MTGPackSlot::addEntry(MTGPackEntry*item) +{ + if (item) + entries.push_back(item); +} +int MTGPack::assemblePack(MTGDeck *to) +{ + int carryover = 0; + WSrcCards * p = getPool(pool); + if (!p) + return -1; + p->Shuffle(); + + for (size_t i = 0; i < slotss.size(); i++) + { + carryover = slotss[i]->add(p, to, carryover); + if (carryover > 0) + carryover = carryover; //This means we're failing. + } + SAFE_DELETE(p); + return carryover; +} +void MTGPack::countCards() +{ + minCards = 0; + maxCards = 0; + for (size_t i = 0; i < slotss.size(); i++) + { + MTGPackSlot * ps = slotss[i]; + int top = 0; + int bot = 999999999; + for (size_t y = 0; y < ps->entries.size(); y++) + { + int test = ps->entries[y]->copies * ps->copies; + if (test > top) + top = test; + if (test < bot) + bot = test; + } + maxCards += top; + minCards += bot; + } +} +void MTGPack::load(string filename) +{ + //TODO Placeholder until XML format available. + TiXmlDocument packfile(filename.c_str()); + if (!packfile.LoadFile()) + return; + TiXmlHandle hDoc(&packfile); + TiXmlElement * pPack; + pPack = hDoc.FirstChildElement().Element(); + if (!pPack) + { + + return; + } + //root should be "pack" + string tag = pPack->Value(); + std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); + if (tag != "pack") + return; + //After validating, handle actual loading. + TiXmlElement * pSlot; + const char * holder = NULL; + holder = pPack->Attribute("price"); + if (holder) + price = atoi(holder); + else + price = Constants::PRICE_BOOSTER; + holder = pPack->Attribute("pool"); + if (holder) + pool = holder; + else + pool = ""; + holder = pPack->Attribute("type"); + if (holder) + { + type = holder; + } + else + type = "Booster"; + holder = pPack->Attribute("name"); + if (holder) + name = holder; + else + name = "Special"; + holder = pPack->Attribute("requires"); + if (holder) + check = holder; + holder = pPack->Attribute("sort"); + if (holder) + sort = holder; + else + sort = ""; + std::transform(sort.begin(), sort.end(), sort.begin(), ::tolower); + + for (pSlot = pPack->FirstChildElement(); pSlot != NULL; pSlot = pSlot->NextSiblingElement()) + { + TiXmlElement * pEntry; + //Load slot. + tag = pSlot->Value(); + std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); + if (tag != "slot") + continue; + MTGPackSlot * s = NEW MTGPackSlot(); + slotss.push_back(s); + holder = pSlot->Attribute("copies"); + if (holder) + s->copies = atoi(holder); + else + s->copies = 1; + holder = pSlot->Attribute("pool"); + if (holder) + s->pool = holder; + + for (pEntry = pSlot->FirstChildElement(); pEntry != NULL; pEntry = pEntry->NextSiblingElement()) + { + tag = pEntry->Value(); + std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); + if (tag == "card") + { //Load specific card + MTGPackEntrySpecific * es = NEW MTGPackEntrySpecific(); + holder = pEntry->Attribute("copies"); + if (holder) + es->copies = atoi(holder); + else + es->copies = 1; + es->card = GameApp::collection->getCardByName(pEntry->Value()); + s->addEntry(es); + } + else if (tag == "random_card") + { //Load random card + MTGPackEntryRandom * er = NEW MTGPackEntryRandom(); + holder = pEntry->Attribute("copies"); + if (holder) + er->copies = atoi(holder); + else + er->copies = 1; + const char * text = pEntry->GetText(); + if (text) + er->filter = text; + s->addEntry(er); + } + else if (tag == "nothing") + { + MTGPackEntryNothing * nt = NEW MTGPackEntryNothing(); + s->addEntry(nt); + } + } + } + bValid = true; + countCards(); + return; +} +MTGPackSlot::~MTGPackSlot() +{ + for (size_t t = 0; t < entries.size(); t++) + { + SAFE_DELETE(entries[t]); + } + entries.clear(); +} +MTGPack::~MTGPack() +{ + for (size_t t = 0; t < slotss.size(); t++) + { + SAFE_DELETE(slotss[t]); + } + slotss.clear(); +} +MTGPacks::~MTGPacks() +{ + for (size_t t = 0; t < packs.size(); t++) + { + SAFE_DELETE(packs[t]); + } + packs.clear(); +} +MTGPack * MTGPacks::randomPack(int key) +{ + if (!key) + key = rand(); + size_t s = packs.size(); + if (!s) + return NULL; + return packs[key % s]; +} +void MTGPacks::loadAll() +{ + DIR *mDip = opendir(JGE_GET_RES("packs/").c_str()); + struct dirent *mDit; + if (!mDip) + return; + + while ((mDit = readdir(mDip))) + { + char myFilename[4096]; + sprintf(myFilename, JGE_GET_RES("packs/%s").c_str(), mDit->d_name); + if (mDit->d_name[0] == '.') + continue; + if (!strcmp(mDit->d_name, "default_booster.txt")) + continue; + MTGPack * p = NEW MTGPack(myFilename); + if (!p->isValid()) + { + SAFE_DELETE(p); + continue; + } + packs.push_back(p); + } + closedir(mDip); +} +string MTGPack::getName() +{ + string n = _(name); + string t = _(type); + char buf[1024]; + if (minCards != maxCards) + sprintf(buf, "%s %s (%i-%i cards)", n.c_str(), t.c_str(), minCards, maxCards); + else + sprintf(buf, "%s %s (%i cards)", n.c_str(), t.c_str(), maxCards); + return buf; +} + +bool MTGPack::meetsRequirements() +{ + bool unlocked = true; + WCFilterFactory * ff = WCFilterFactory::GetInstance(); + WSrcCards * myC = getPool(pool); + if (!myC || myC->Size() < maxCards) + unlocked = false; //Top pool lacks cards. + SAFE_DELETE(myC); + if (!check.size() || !unlocked) + return unlocked; + myC = NEW WSrcUnlockedCards(); //Requirements are independent of pool; + WCardFilter * cf = ff->Construct(check); + unlocked = !myC->isEmptySet(cf); //Quick check for empty set status. + SAFE_DELETE(cf); //delete requirement filter + SAFE_DELETE(myC); //delete pool. + return unlocked; +} + +bool MTGPack::isUnlocked() +{ + if (unlockStatus == 0) + { + if (meetsRequirements()) + unlockStatus = 1; + else + unlockStatus = -1; + } + return (unlockStatus > 0); +} + +MTGPack * MTGPacks::getDefault() +{ + if (!defaultBooster.isValid()) + { + defaultBooster.load(JGE_GET_RES("packs/default_booster.txt")); + defaultBooster.unlockStatus = 1; + if (!defaultBooster.isValid()) + { + MTGPackSlot * ps = NEW MTGPackSlot(); + ps->copies = 1; + ps->addEntry(NEW MTGPackEntryRandom("rarity:mythic;")); + for (int i = 0; i < 7; i++) + ps->addEntry(NEW MTGPackEntryRandom("rarity:rare;")); + defaultBooster.slotss.push_back(ps); + ps = NEW MTGPackSlot(); + ps->copies = 3; + ps->addEntry(NEW MTGPackEntryRandom("rarity:uncommon;")); + defaultBooster.slotss.push_back(ps); + ps = NEW MTGPackSlot(); + ps->copies = 1; + ps->addEntry(NEW MTGPackEntryRandom("rarity:land;&type:basic;")); + defaultBooster.slotss.push_back(ps); + ps = NEW MTGPackSlot(); + ps->copies = 10; + ps->addEntry(NEW MTGPackEntryRandom("rarity:common;")); + defaultBooster.slotss.push_back(ps); + defaultBooster.bValid = true; + defaultBooster.unlockStatus = 1; + } + } + return &defaultBooster; +} + +void MTGPacks::refreshUnlocked() +{ + for (size_t t = 0; t < packs.size(); t++) + { + if (packs[t]->unlockStatus < 0) + packs[t]->unlockStatus = 0; + } } diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index bb897a7cf..f2d7a34a1 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -6,151 +6,216 @@ #include "Subtypes.h" #include "GameOptions.h" - - -MTGPutInPlayRule::MTGPutInPlayRule(int _id):MTGAbility(_id, NULL){ - aType=MTGAbility::PUT_INTO_PLAY; +MTGPutInPlayRule::MTGPutInPlayRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::PUT_INTO_PLAY; } -int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - int cardsinhand = game->players[0]->game->hand->nb_cards; - Player * player = game->currentlyActing(); - Player * currentPlayer = game->currentPlayer; - if (!player->game->hand->hasCard(card)) return 0; - if ((game->turn < 1) && (cardsinhand != 0) && (card->basicAbilities[Constants::LEYLINE]) - && game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN - && game->players[0]->game->graveyard->nb_cards == 0 - && game->players[0]->game->exile->nb_cards == 0){ - Player * p = game->currentPlayer; - if (card->basicAbilities[Constants::LEYLINE]){ - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); - Spell * spell = NEW Spell(copy); - spell->resolve(); - delete spell;} - return 1;} - if (card->hasType("land")){ - if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)){ - return 1; - } - }else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))){ - ManaCost * playerMana = player->getManaPool(); - ManaCost * cost = card->getManaCost(); - ManaCost * alternative = card->getManaCost()->alternative; - ManaCost * BuyBack = card->getManaCost()->BuyBack; +int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + int cardsinhand = game->players[0]->game->hand->nb_cards; + Player * player = game->currentlyActing(); + Player * currentPlayer = game->currentPlayer; + if (!player->game->hand->hasCard(card)) + return 0; + if ((game->turn < 1) && (cardsinhand != 0) && (card->basicAbilities[Constants::LEYLINE]) && game->currentGamePhase + == Constants::MTG_PHASE_FIRSTMAIN && game->players[0]->game->graveyard->nb_cards == 0 + && game->players[0]->game->exile->nb_cards == 0) + { + Player * p = game->currentPlayer; + if (card->basicAbilities[Constants::LEYLINE]) + { + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); + Spell * spell = NEW Spell(copy); + spell->resolve(); + delete spell; + } + return 1; + } + if (card->hasType("land")) + { + if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase + == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) + { + return 1; + } + } + else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting + && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase + == Constants::MTG_PHASE_SECONDMAIN))) + { + ManaCost * playerMana = player->getManaPool(); + ManaCost * cost = card->getManaCost(); + ManaCost * alternative = card->getManaCost()->alternative; + ManaCost * BuyBack = card->getManaCost()->BuyBack; #ifdef WIN32 - cost->Dump(); + cost->Dump(); #endif - if(player->castrestrictedspell > 0 && !card->hasType("land")){ return 0;} - if(player->onlyonecast > 0 && player->castcount >= 1){return 0;} - if(player->nospellinstant > 0){return 0;} - if(player->onlyoneinstant > 0){ if(player->castcount >= 1){return 0;}} - if(player->nocreatureinstant > 0 && card->hasType("creature")){return 0;} - if(player->castrestrictedcreature > 0 && card->hasType("creature")){return 0;} + if (player->castrestrictedspell > 0 && !card->hasType("land")) + { + return 0; + } + if (player->onlyonecast > 0 && player->castcount >= 1) + { + return 0; + } + if (player->nospellinstant > 0) + { + return 0; + } + if (player->onlyoneinstant > 0) + { + if (player->castcount >= 1) + { + return 0; + } + } + if (player->nocreatureinstant > 0 && card->hasType("creature")) + { + return 0; + } + if (player->castrestrictedcreature > 0 && card->hasType("creature")) + { + return 0; + } - //cost of card. - if (playerMana->canAfford(cost)){ -//------- - if(card->has(Constants::SUNBURST)){ - for(int i = 1; i != 6;i++) - { - if(player->getManaPool()->hasColor(i)){ - if(card->getManaCost()->hasColor(i) > 0){//do nothing if the card already has this color. - }else{ - if(card->sunburst < card->getManaCost()->getConvertedCost()){ - card->getManaCost()->add(i,1); - card->getManaCost()->remove(0,1); - card->sunburst += 1; - } - } - } -//------- - } - } - return 1;//play if you can afford too. - } - } - return 0;//dont play if you cant afford it. + //cost of card. + if (playerMana->canAfford(cost)) + { + //------- + if (card->has(Constants::SUNBURST)) + { + for (int i = 1; i != 6; i++) + { + if (player->getManaPool()->hasColor(i)) + { + if (card->getManaCost()->hasColor(i) > 0) + {//do nothing if the card already has this color. + } + else + { + if (card->sunburst < card->getManaCost()->getConvertedCost()) + { + card->getManaCost()->add(i, 1); + card->getManaCost()->remove(0, 1); + card->sunburst += 1; + } + } + } + //------- + } + } + return 1;//play if you can afford too. + } + } + return 0;//dont play if you cant afford it. } -int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ - if (!isReactingToClick(card)) return 0; - Player * player = game->currentlyActing(); - ManaCost * cost = card->getManaCost(); - ManaCost * playerMana = player->getManaPool(); - //this handles extra cost payments at the moment a card is played. - if (cost->isExtraPaymentSet()){ - if (!game->targetListIsSet(card)){ - return 0; - } - }else{ - cost->setExtraCostsAction(this, card); - game->waitForExtraPayment = cost->extraCosts; - return 0; - } +int MTGPutInPlayRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; + Player * player = game->currentlyActing(); + ManaCost * cost = card->getManaCost(); + ManaCost * playerMana = player->getManaPool(); + //this handles extra cost payments at the moment a card is played. - ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - int payResult = player->getManaPool()->pay(card->getManaCost()); - card->getManaCost()->doPayExtra(); - ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); + if (cost->isExtraPaymentSet()) + { + if (!game->targetListIsSet(card)) + { + return 0; + } + } + else + { + cost->setExtraCostsAction(this, card); + game->waitForExtraPayment = cost->extraCosts; + return 0; + } - delete previousManaPool; - if (card->hasType("land")){ - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); - Spell * spell = NEW Spell(copy); - spell->resolve(); - delete spellCost; - delete spell; - player->canPutLandsIntoPlay--; - }else{ - Spell * spell = NULL; - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); - if (game->targetChooser){ - spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); - game->targetChooser = NULL; - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} - }else{ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} - } + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + int payResult = player->getManaPool()->pay(card->getManaCost()); + card->getManaCost()->doPayExtra(); + ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); - if(card->has(Constants::STORM)){ - int storm = player->castedspellsthisturn; - ManaCost * spellCost = player->getManaPool(); - for(int i = storm; i > 1; i--){ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); + delete previousManaPool; + if (card->hasType("land")) + { + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); + Spell * spell = NEW Spell(copy); + spell->resolve(); + delete spellCost; + delete spell; + player->canPutLandsIntoPlay--; + } + else + { + Spell * spell = NULL; + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); + if (game->targetChooser) + { + spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, payResult, 0); + game->targetChooser = NULL; + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; + } + } + else + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0); + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; + } + } - } - }//end of storm - if(!card->has(Constants::STORM)){ - copy->X = spell->computeX(copy); - copy->XX = spell->computeXX(copy); - } - } + if (card->has(Constants::STORM)) + { + int storm = player->castedspellsthisturn; + ManaCost * spellCost = player->getManaPool(); + for (int i = storm; i > 1; i--) + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); - return 1; + } + }//end of storm + if (!card->has(Constants::STORM)) + { + copy->X = spell->computeX(copy); + copy->XX = spell->computeXX(copy); + } + } + + return 1; } //The Put into play rule is never destroyed -int MTGPutInPlayRule::testDestroy(){ - return 0; +int MTGPutInPlayRule::testDestroy() +{ + return 0; } ostream& MTGPutInPlayRule::toString(ostream& out) const { - out << "MTGPutInPlayRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGPutInPlayRule ::: ("; + return MTGAbility::toString(out) << ")"; } -MTGPutInPlayRule * MTGPutInPlayRule::clone() const{ - MTGPutInPlayRule * a = NEW MTGPutInPlayRule(*this); - a->isClone = 1; - return a; +MTGPutInPlayRule * MTGPutInPlayRule::clone() const +{ + MTGPutInPlayRule * a = NEW MTGPutInPlayRule(*this); + a->isClone = 1; + return a; } + //cast from anywhere possible with this?? //Alternative cost rules @@ -160,769 +225,1046 @@ MTGPutInPlayRule * MTGPutInPlayRule::clone() const{ //------------------------------------------------------------------------- //------------------------------------------------------------------------- -MTGAlternativeCostRule::MTGAlternativeCostRule(int _id):MTGAbility(_id, NULL){ - aType=MTGAbility::ALTERNATIVE_COST; +MTGAlternativeCostRule::MTGAlternativeCostRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::ALTERNATIVE_COST; } -int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - int cardsinhand = game->players[0]->game->hand->nb_cards; - Player * player = game->currentlyActing(); - Player * currentPlayer = game->currentPlayer; - if (!player->game->hand->hasCard(card)) return 0; - if (!card->getManaCost()->alternative) return 0; - if (card->hasType("land")){ - if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)){ - return 1; - } - }else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))){ - ManaCost * playerMana = player->getManaPool(); - ManaCost * cost = card->getManaCost(); - ManaCost * alternative = card->getManaCost()->alternative; +int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + int cardsinhand = game->players[0]->game->hand->nb_cards; + Player * player = game->currentlyActing(); + Player * currentPlayer = game->currentPlayer; + if (!player->game->hand->hasCard(card)) + return 0; + if (!card->getManaCost()->alternative) + return 0; + if (card->hasType("land")) + { + if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase + == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) + { + return 1; + } + } + else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting + && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase + == Constants::MTG_PHASE_SECONDMAIN))) + { + ManaCost * playerMana = player->getManaPool(); + ManaCost * cost = card->getManaCost(); + ManaCost * alternative = card->getManaCost()->alternative; #ifdef WIN32 - cost->Dump(); + cost->Dump(); #endif - if(player->castrestrictedspell > 0 && !card->hasType("land")){ return 0;} - if(player->onlyonecast > 0 && player->castcount >= 1){return 0;} - if(player->nospellinstant > 0){return 0;} - if(player->onlyoneinstant > 0){ if(player->castcount >= 1){return 0;}} - if(player->nocreatureinstant > 0 && card->hasType("creature")){return 0;} - if(player->castrestrictedcreature > 0 && card->hasType("creature")){return 0;} - //cost of card. - if(alternative && playerMana->canAfford(alternative)){ - return 1; - } - } - return 0;//dont play if you cant afford it. + if (player->castrestrictedspell > 0 && !card->hasType("land")) + { + return 0; + } + if (player->onlyonecast > 0 && player->castcount >= 1) + { + return 0; + } + if (player->nospellinstant > 0) + { + return 0; + } + if (player->onlyoneinstant > 0) + { + if (player->castcount >= 1) + { + return 0; + } + } + if (player->nocreatureinstant > 0 && card->hasType("creature")) + { + return 0; + } + if (player->castrestrictedcreature > 0 && card->hasType("creature")) + { + return 0; + } + //cost of card. + if (alternative && playerMana->canAfford(alternative)) + { + return 1; + } + } + return 0;//dont play if you cant afford it. } -int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card){ - if (!isReactingToClick(card)) return 0; - Player * player = game->currentlyActing(); - ManaCost * cost = card->getManaCost(); - ManaCost * alternative = card->getManaCost()->alternative; - ManaCost * playerMana = player->getManaPool(); - //this handles extra cost payments at the moment a card is played. - if(playerMana->canAfford(alternative)){ - if (cost->alternative->isExtraPaymentSet()){ - card->paymenttype = 1; - if (!game->targetListIsSet(card)){ - return 0; - } - }else{ - cost->alternative->setExtraCostsAction(this, card); - game->waitForExtraPayment = cost->alternative->extraCosts; - card->paymenttype = 1; - return 0; - } - } - //------------------------------------------------------------------------ - ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - int payResult = player->getManaPool()->pay(card->getManaCost()->alternative); - card->getManaCost()->alternative->doPayExtra(); - payResult = ManaCost::MANA_PAID_WITH_ALTERNATIVE; - //if alternative has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the alternative cost. - if(alternative){ - card->getManaCost()->alternative->doPayExtra(); - } - //--------------------------------------------------------------------------- - ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); - delete previousManaPool; - if (card->hasType("land")){ - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); - Spell * spell = NEW Spell(copy); - spell->resolve(); - delete spellCost; - delete spell; - player->canPutLandsIntoPlay--; - payResult = ManaCost::MANA_PAID_WITH_ALTERNATIVE; - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - }else{ - Spell * spell = NULL; - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); - if (game->targetChooser){ - spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); - game->targetChooser = NULL; - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} - }else{ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; - } - } - if(card->has(Constants::STORM)){ - int storm = player->castedspellsthisturn; - ManaCost * spellCost = player->getManaPool(); - for(int i = storm; i > 1; i--){ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - } - }//end of storm - if(!card->has(Constants::STORM)){ - copy->X = spell->computeX(copy); - copy->XX = spell->computeXX(copy); - } - } - return 1; +int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; + Player * player = game->currentlyActing(); + ManaCost * cost = card->getManaCost(); + ManaCost * alternative = card->getManaCost()->alternative; + ManaCost * playerMana = player->getManaPool(); + //this handles extra cost payments at the moment a card is played. + if (playerMana->canAfford(alternative)) + { + if (cost->alternative->isExtraPaymentSet()) + { + card->paymenttype = 1; + if (!game->targetListIsSet(card)) + { + return 0; + } + } + else + { + cost->alternative->setExtraCostsAction(this, card); + game->waitForExtraPayment = cost->alternative->extraCosts; + card->paymenttype = 1; + return 0; + } + } + //------------------------------------------------------------------------ + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + int payResult = player->getManaPool()->pay(card->getManaCost()->alternative); + card->getManaCost()->alternative->doPayExtra(); + payResult = ManaCost::MANA_PAID_WITH_ALTERNATIVE; + //if alternative has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the alternative cost. + if (alternative) + { + card->getManaCost()->alternative->doPayExtra(); + } + //--------------------------------------------------------------------------- + ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); + delete previousManaPool; + if (card->hasType("land")) + { + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); + Spell * spell = NEW Spell(copy); + spell->resolve(); + delete spellCost; + delete spell; + player->canPutLandsIntoPlay--; + payResult = ManaCost::MANA_PAID_WITH_ALTERNATIVE; + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + else + { + Spell * spell = NULL; + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); + if (game->targetChooser) + { + spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, payResult, 0); + game->targetChooser = NULL; + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; + } + } + else + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0); + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; + } + } + if (card->has(Constants::STORM)) + { + int storm = player->castedspellsthisturn; + ManaCost * spellCost = player->getManaPool(); + for (int i = storm; i > 1; i--) + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + }//end of storm + if (!card->has(Constants::STORM)) + { + copy->X = spell->computeX(copy); + copy->XX = spell->computeXX(copy); + } + } + + return 1; } //The Put into play rule is never destroyed -int MTGAlternativeCostRule::testDestroy(){ - return 0; +int MTGAlternativeCostRule::testDestroy() +{ + return 0; } ostream& MTGAlternativeCostRule::toString(ostream& out) const { - out << "MTGAlternativeCostRule ::: ("; - return MTGAbility::toString(out) << ")"; -} -MTGAlternativeCostRule * MTGAlternativeCostRule::clone() const{ - MTGAlternativeCostRule * a = NEW MTGAlternativeCostRule(*this); - a->isClone = 1; - return a; + out << "MTGAlternativeCostRule ::: ("; + return MTGAbility::toString(out) << ")"; } +MTGAlternativeCostRule * MTGAlternativeCostRule::clone() const +{ + MTGAlternativeCostRule * a = NEW MTGAlternativeCostRule(*this); + a->isClone = 1; + return a; + //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //buyback follows its own resolving rules -MTGBuyBackRule::MTGBuyBackRule(int _id):MTGAbility(_id, NULL){ - aType=MTGAbility::BUYBACK_COST; +MTGBuyBackRule::MTGBuyBackRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::BUYBACK_COST; } -int MTGBuyBackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - int cardsinhand = game->players[0]->game->hand->nb_cards; - Player * player = game->currentlyActing(); - Player * currentPlayer = game->currentPlayer; - if (!player->game->hand->hasCard(card)) return 0; - if (!card->getManaCost()->BuyBack) return 0; - if (card->hasType("land")){ - if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)){ - return 1; - } - }else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))){ - ManaCost * playerMana = player->getManaPool(); - ManaCost * cost = card->getManaCost(); - ManaCost * BuyBack = card->getManaCost()->BuyBack; +int MTGBuyBackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + int cardsinhand = game->players[0]->game->hand->nb_cards; + Player * player = game->currentlyActing(); + Player * currentPlayer = game->currentPlayer; + if (!player->game->hand->hasCard(card)) + return 0; + if (!card->getManaCost()->BuyBack) + return 0; + if (card->hasType("land")) + { + if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase + == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) + { + return 1; + } + } + else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting + && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase + == Constants::MTG_PHASE_SECONDMAIN))) + { + ManaCost * playerMana = player->getManaPool(); + ManaCost * cost = card->getManaCost(); + ManaCost * BuyBack = card->getManaCost()->BuyBack; #ifdef WIN32 - cost->Dump(); + cost->Dump(); #endif - if(player->castrestrictedspell > 0 && !card->hasType("land")){ return 0;} - if(player->onlyonecast > 0 && player->castcount >= 1){return 0;} - if(player->nospellinstant > 0){return 0;} - if(player->onlyoneinstant > 0){ if(player->castcount >= 1){return 0;}} - if(player->nocreatureinstant > 0 && card->hasType("creature")){return 0;} - if(player->castrestrictedcreature > 0 && card->hasType("creature")){return 0;} - //cost of card. - if(BuyBack && playerMana->canAfford(BuyBack)){ - return 1; - } - } - return 0;//dont play if you cant afford it. + if (player->castrestrictedspell > 0 && !card->hasType("land")) + { + return 0; + } + if (player->onlyonecast > 0 && player->castcount >= 1) + { + return 0; + } + if (player->nospellinstant > 0) + { + return 0; + } + if (player->onlyoneinstant > 0) + { + if (player->castcount >= 1) + { + return 0; + } + } + if (player->nocreatureinstant > 0 && card->hasType("creature")) + { + return 0; + } + if (player->castrestrictedcreature > 0 && card->hasType("creature")) + { + return 0; + } + //cost of card. + if (BuyBack && playerMana->canAfford(BuyBack)) + { + return 1; + } + } + return 0;//dont play if you cant afford it. } -int MTGBuyBackRule::reactToClick(MTGCardInstance * card){ - if (!isReactingToClick(card)) return 0; - Player * player = game->currentlyActing(); - ManaCost * cost = card->getManaCost(); - ManaCost * BuyBack = card->getManaCost()->BuyBack; - ManaCost * playerMana = player->getManaPool(); - //this handles extra cost payments at the moment a card is played. - if(playerMana->canAfford(BuyBack)){ - if (cost->BuyBack->isExtraPaymentSet()){ - card->paymenttype = 2; - if (!game->targetListIsSet(card)){ - return 0; - } - }else{ - cost->BuyBack->setExtraCostsAction(this, card); - game->waitForExtraPayment = cost->BuyBack->extraCosts; - card->paymenttype = 2; - return 0; - } - } - //------------------------------------------------------------------------ - ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - int payResult = player->getManaPool()->pay(card->getManaCost()->BuyBack); - card->getManaCost()->doPayExtra(); - payResult = ManaCost::MANA_PAID_WITH_BUYBACK; - //if BuyBack has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the BuyBack cost. - if(BuyBack){ - card->getManaCost()->BuyBack->doPayExtra(); - } - //--------------------------------------------------------------------------- - ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); - card->boughtback = 1; - delete previousManaPool; - if (card->hasType("land")){ - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); - Spell * spell = NEW Spell(copy); - copy->boughtback = 1; - spell->resolve(); - delete spellCost; - delete spell; - player->canPutLandsIntoPlay--; - payResult = ManaCost::MANA_PAID_WITH_BUYBACK; - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - }else{ - Spell * spell = NULL; - card->boughtback = 1; - MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); - copy->boughtback = 1; - if (game->targetChooser){ - spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); - game->targetChooser = NULL; - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} - }else{ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; - } - } - if(card->has(Constants::STORM)){ - int storm = player->castedspellsthisturn; - ManaCost * spellCost = player->getManaPool(); - for(int i = storm; i > 1; i--){ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - } - }//end of storm - if(!card->has(Constants::STORM)){ - copy->X = spell->computeX(copy); - copy->XX = spell->computeXX(copy); - } - } +int MTGBuyBackRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; + Player * player = game->currentlyActing(); + ManaCost * cost = card->getManaCost(); + ManaCost * BuyBack = card->getManaCost()->BuyBack; + ManaCost * playerMana = player->getManaPool(); + //this handles extra cost payments at the moment a card is played. + if (playerMana->canAfford(BuyBack)) + { + if (cost->BuyBack->isExtraPaymentSet()) + { + card->paymenttype = 2; + if (!game->targetListIsSet(card)) + { + return 0; + } + } + else + { + cost->BuyBack->setExtraCostsAction(this, card); + game->waitForExtraPayment = cost->BuyBack->extraCosts; + card->paymenttype = 2; + return 0; + } + } + //------------------------------------------------------------------------ + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + int payResult = player->getManaPool()->pay(card->getManaCost()->BuyBack); + card->getManaCost()->doPayExtra(); + payResult = ManaCost::MANA_PAID_WITH_BUYBACK; + //if BuyBack has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the BuyBack cost. + if (BuyBack) + { + card->getManaCost()->BuyBack->doPayExtra(); + } + //--------------------------------------------------------------------------- + ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); + card->boughtback = 1; + delete previousManaPool; + if (card->hasType("land")) + { + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp); + Spell * spell = NEW Spell(copy); + copy->boughtback = 1; + spell->resolve(); + delete spellCost; + delete spell; + player->canPutLandsIntoPlay--; + payResult = ManaCost::MANA_PAID_WITH_BUYBACK; + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + else + { + Spell * spell = NULL; + card->boughtback = 1; + MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); + copy->boughtback = 1; + if (game->targetChooser) + { + spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, payResult, 0); + game->targetChooser = NULL; + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; + } + } + else + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0); + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; - return 1; + } + } + if (card->has(Constants::STORM)) + { + int storm = player->castedspellsthisturn; + ManaCost * spellCost = player->getManaPool(); + for (int i = storm; i > 1; i--) + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + }//end of storm + if (!card->has(Constants::STORM)) + { + copy->X = spell->computeX(copy); + copy->XX = spell->computeXX(copy); + } + } + + return 1; } //The Put into play rule is never destroyed -int MTGBuyBackRule::testDestroy(){ - return 0; +int MTGBuyBackRule::testDestroy() +{ + return 0; } ostream& MTGBuyBackRule::toString(ostream& out) const { - out << "MTGBuyBackRule ::: ("; - return MTGAbility::toString(out) << ")"; -} -MTGBuyBackRule * MTGBuyBackRule::clone() const{ - MTGBuyBackRule * a = NEW MTGBuyBackRule(*this); - a->isClone = 1; - return a; + out << "MTGBuyBackRule ::: ("; + return MTGAbility::toString(out) << ")"; } +MTGBuyBackRule * MTGBuyBackRule::clone() const +{ + MTGBuyBackRule * a = NEW MTGBuyBackRule(*this); + a->isClone = 1; + return a; +} //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //flashback follows its own resolving rules -MTGFlashBackRule::MTGFlashBackRule(int _id):MTGAbility(_id, NULL){ - aType=MTGAbility::FLASHBACK_COST; +MTGFlashBackRule::MTGFlashBackRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::FLASHBACK_COST; } -int MTGFlashBackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - int cardsingraveyard = game->players[0]->game->graveyard->nb_cards; - Player * player = game->currentlyActing(); - Player * currentPlayer = game->currentPlayer; - if (!player->game->graveyard->hasCard(card)) return 0; - if (!card->getManaCost()->FlashBack) return 0; - if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))){ - ManaCost * playerMana = player->getManaPool(); - ManaCost * cost = card->getManaCost(); - ManaCost * FlashBack = card->getManaCost()->FlashBack; +int MTGFlashBackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + int cardsingraveyard = game->players[0]->game->graveyard->nb_cards; + Player * player = game->currentlyActing(); + Player * currentPlayer = game->currentPlayer; + if (!player->game->graveyard->hasCard(card)) + return 0; + if (!card->getManaCost()->FlashBack) + return 0; + if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting + && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase + == Constants::MTG_PHASE_SECONDMAIN))) + { + ManaCost * playerMana = player->getManaPool(); + ManaCost * cost = card->getManaCost(); + ManaCost * FlashBack = card->getManaCost()->FlashBack; #ifdef WIN32 - cost->Dump(); + cost->Dump(); #endif - if(player->castrestrictedspell > 0 && !card->hasType("land")){ return 0;} - if(player->onlyonecast > 0 && player->castcount >= 1){return 0;} - if(player->nospellinstant > 0){return 0;} - if(player->onlyoneinstant > 0){ if(player->castcount >= 1){return 0;}} - if(player->nocreatureinstant > 0 && card->hasType("creature")){return 0;} - if(player->castrestrictedcreature > 0 && card->hasType("creature")){return 0;} - //cost of card. - if(FlashBack && playerMana->canAfford(FlashBack)){ - return 1; - } - } - return 0;//dont play if you cant afford it. + if (player->castrestrictedspell > 0 && !card->hasType("land")) + { + return 0; + } + if (player->onlyonecast > 0 && player->castcount >= 1) + { + return 0; + } + if (player->nospellinstant > 0) + { + return 0; + } + if (player->onlyoneinstant > 0) + { + if (player->castcount >= 1) + { + return 0; + } + } + if (player->nocreatureinstant > 0 && card->hasType("creature")) + { + return 0; + } + if (player->castrestrictedcreature > 0 && card->hasType("creature")) + { + return 0; + } + //cost of card. + if (FlashBack && playerMana->canAfford(FlashBack)) + { + return 1; + } + } + return 0;//dont play if you cant afford it. } -int MTGFlashBackRule::reactToClick(MTGCardInstance * card){ - if (!isReactingToClick(card)) return 0; - Player * player = game->currentlyActing(); - ManaCost * cost = card->getManaCost(); - ManaCost * FlashBack = card->getManaCost()->FlashBack; - ManaCost * playerMana = player->getManaPool(); - //this handles extra cost payments at the moment a card is played. - if(playerMana->canAfford(FlashBack)){ - if (cost->FlashBack->isExtraPaymentSet()){ - card->paymenttype = 3; - if (!game->targetListIsSet(card)){ - return 0; - } - }else{ - cost->FlashBack->setExtraCostsAction(this, card); - game->waitForExtraPayment = cost->FlashBack->extraCosts; - card->paymenttype = 3; - return 0; - } - } - //------------------------------------------------------------------------ - ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - int payResult = player->getManaPool()->pay(card->getManaCost()->FlashBack); - card->getManaCost()->doPayExtra(); - payResult = ManaCost::MANA_PAID_WITH_FLASHBACK; - //if flashBack has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the flashBack cost. - if(FlashBack){ - card->getManaCost()->FlashBack->doPayExtra(); - } - //--------------------------------------------------------------------------- - ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); - card->flashedback = 1; - delete previousManaPool; - if (card->hasType("land")){ - MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->temp); - Spell * spell = NEW Spell(copy); - copy->flashedback = 1; - spell->resolve(); - delete spellCost; - delete spell; - player->canPutLandsIntoPlay--; - payResult = ManaCost::MANA_PAID_WITH_FLASHBACK; - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - }else{ - Spell * spell = NULL; - card->flashedback = 1; - MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->stack); - copy->flashedback = 1; - if (game->targetChooser){ - spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); - game->targetChooser = NULL; - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} - }else{ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; +int MTGFlashBackRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; + Player * player = game->currentlyActing(); + ManaCost * cost = card->getManaCost(); + ManaCost * FlashBack = card->getManaCost()->FlashBack; + ManaCost * playerMana = player->getManaPool(); + //this handles extra cost payments at the moment a card is played. + if (playerMana->canAfford(FlashBack)) + { + if (cost->FlashBack->isExtraPaymentSet()) + { + card->paymenttype = 3; + if (!game->targetListIsSet(card)) + { + return 0; + } + } + else + { + cost->FlashBack->setExtraCostsAction(this, card); + game->waitForExtraPayment = cost->FlashBack->extraCosts; + card->paymenttype = 3; + return 0; + } + } + //------------------------------------------------------------------------ + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + int payResult = player->getManaPool()->pay(card->getManaCost()->FlashBack); + card->getManaCost()->doPayExtra(); + payResult = ManaCost::MANA_PAID_WITH_FLASHBACK; + //if flashBack has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the flashBack cost. + if (FlashBack) + { + card->getManaCost()->FlashBack->doPayExtra(); + } + //--------------------------------------------------------------------------- + ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); + card->flashedback = 1; + delete previousManaPool; + if (card->hasType("land")) + { + MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->temp); + Spell * spell = NEW Spell(copy); + copy->flashedback = 1; + spell->resolve(); + delete spellCost; + delete spell; + player->canPutLandsIntoPlay--; + payResult = ManaCost::MANA_PAID_WITH_FLASHBACK; + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + else + { + Spell * spell = NULL; + card->flashedback = 1; + MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->stack); + copy->flashedback = 1; + if (game->targetChooser) + { + spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, payResult, 0); + game->targetChooser = NULL; + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; + } + } + else + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0); + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; - } - } - if(card->has(Constants::STORM)){ - int storm = player->castedspellsthisturn; - ManaCost * spellCost = player->getManaPool(); - for(int i = storm; i > 1; i--){ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - } - }//end of storm - if(!card->has(Constants::STORM)){ - copy->X = spell->computeX(copy); - copy->XX = spell->computeXX(copy); - } - } + } + } + if (card->has(Constants::STORM)) + { + int storm = player->castedspellsthisturn; + ManaCost * spellCost = player->getManaPool(); + for (int i = storm; i > 1; i--) + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + }//end of storm + if (!card->has(Constants::STORM)) + { + copy->X = spell->computeX(copy); + copy->XX = spell->computeXX(copy); + } + } - return 1; + return 1; } //The Put into play rule is never destroyed -int MTGFlashBackRule::testDestroy(){ - return 0; +int MTGFlashBackRule::testDestroy() +{ + return 0; } ostream& MTGFlashBackRule::toString(ostream& out) const { - out << "MTGFlashBackRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGFlashBackRule ::: ("; + return MTGAbility::toString(out) << ")"; } -MTGFlashBackRule * MTGFlashBackRule::clone() const{ - MTGFlashBackRule * a = NEW MTGFlashBackRule(*this); - a->isClone = 1; - return a; +MTGFlashBackRule * MTGFlashBackRule::clone() const +{ + MTGFlashBackRule * a = NEW MTGFlashBackRule(*this); + a->isClone = 1; + return a; } - //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //retrace -MTGRetraceRule::MTGRetraceRule(int _id):MTGAbility(_id, NULL){ - aType=MTGAbility::RETRACE_COST; +MTGRetraceRule::MTGRetraceRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::RETRACE_COST; } -int MTGRetraceRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - int cardsingraveyard = game->players[0]->game->graveyard->nb_cards; - Player * player = game->currentlyActing(); - Player * currentPlayer = game->currentPlayer; - if (!player->game->graveyard->hasCard(card)) return 0; - if (!card->getManaCost()->Retrace) return 0; - if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))){ - ManaCost * playerMana = player->getManaPool(); - ManaCost * cost = card->getManaCost(); - ManaCost * Retrace = card->getManaCost()->Retrace; +int MTGRetraceRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + int cardsingraveyard = game->players[0]->game->graveyard->nb_cards; + Player * player = game->currentlyActing(); + Player * currentPlayer = game->currentPlayer; + if (!player->game->graveyard->hasCard(card)) + return 0; + if (!card->getManaCost()->Retrace) + return 0; + if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting + && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase + == Constants::MTG_PHASE_SECONDMAIN))) + { + ManaCost * playerMana = player->getManaPool(); + ManaCost * cost = card->getManaCost(); + ManaCost * Retrace = card->getManaCost()->Retrace; #ifdef WIN32 - cost->Dump(); + cost->Dump(); #endif - if(player->castrestrictedspell > 0 && !card->hasType("land")){ return 0;} - if(player->onlyonecast > 0 && player->castcount >= 1){return 0;} - if(player->nospellinstant > 0){return 0;} - if(player->onlyoneinstant > 0){ if(player->castcount >= 1){return 0;}} - if(player->nocreatureinstant > 0 && card->hasType("creature")){return 0;} - if(player->castrestrictedcreature > 0 && card->hasType("creature")){return 0;} - //cost of card. - if(Retrace && playerMana->canAfford(Retrace)){ - return 1; - } - } - return 0;//dont play if you cant afford it. + if (player->castrestrictedspell > 0 && !card->hasType("land")) + { + return 0; + } + if (player->onlyonecast > 0 && player->castcount >= 1) + { + return 0; + } + if (player->nospellinstant > 0) + { + return 0; + } + if (player->onlyoneinstant > 0) + { + if (player->castcount >= 1) + { + return 0; + } + } + if (player->nocreatureinstant > 0 && card->hasType("creature")) + { + return 0; + } + if (player->castrestrictedcreature > 0 && card->hasType("creature")) + { + return 0; + } + //cost of card. + if (Retrace && playerMana->canAfford(Retrace)) + { + return 1; + } + } + return 0;//dont play if you cant afford it. } -int MTGRetraceRule::reactToClick(MTGCardInstance * card){ - if (!isReactingToClick(card)) return 0; - Player * player = game->currentlyActing(); - ManaCost * cost = card->getManaCost(); - ManaCost * Retrace = card->getManaCost()->Retrace; - ManaCost * playerMana = player->getManaPool(); - //this handles extra cost payments at the moment a card is played. - if(playerMana->canAfford(Retrace)){ - if (cost->Retrace->isExtraPaymentSet()){ - card->paymenttype = 4; - if (!game->targetListIsSet(card)){ - return 0; - } - }else{ - cost->Retrace->setExtraCostsAction(this, card); - game->waitForExtraPayment = cost->Retrace->extraCosts; - card->paymenttype = 4; - return 0; - } - } - //------------------------------------------------------------------------ - ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); - int payResult = player->getManaPool()->pay(card->getManaCost()->Retrace); - card->getManaCost()->doPayExtra(); - payResult = ManaCost::MANA_PAID_WITH_RETRACE; - //if Retrace has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the Retrace cost. - if(Retrace){ - card->getManaCost()->Retrace->doPayExtra(); - } - //--------------------------------------------------------------------------- - ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); - delete previousManaPool; - if (card->hasType("land")){ - MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->temp); - Spell * spell = NEW Spell(copy); - spell->resolve(); - delete spellCost; - delete spell; - player->canPutLandsIntoPlay--; - payResult = ManaCost::MANA_PAID_WITH_RETRACE; - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - }else{ - Spell * spell = NULL; - MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->stack); - if (game->targetChooser){ - spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); - game->targetChooser = NULL; - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1;} - }else{ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); - player->castedspellsthisturn += 1; - player->opponent()->castedspellsthisturn += 1; - if(player->onlyonecast > 0 || player->onlyoneinstant > 0){player->castcount += 1; +int MTGRetraceRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; + Player * player = game->currentlyActing(); + ManaCost * cost = card->getManaCost(); + ManaCost * Retrace = card->getManaCost()->Retrace; + ManaCost * playerMana = player->getManaPool(); + //this handles extra cost payments at the moment a card is played. + if (playerMana->canAfford(Retrace)) + { + if (cost->Retrace->isExtraPaymentSet()) + { + card->paymenttype = 4; + if (!game->targetListIsSet(card)) + { + return 0; + } + } + else + { + cost->Retrace->setExtraCostsAction(this, card); + game->waitForExtraPayment = cost->Retrace->extraCosts; + card->paymenttype = 4; + return 0; + } + } + //------------------------------------------------------------------------ + ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); + int payResult = player->getManaPool()->pay(card->getManaCost()->Retrace); + card->getManaCost()->doPayExtra(); + payResult = ManaCost::MANA_PAID_WITH_RETRACE; + //if Retrace has a extra payment thats set, this code pays it.the if statement is 100% needed as it would cause a crash on cards that dont have the Retrace cost. + if (Retrace) + { + card->getManaCost()->Retrace->doPayExtra(); + } + //--------------------------------------------------------------------------- + ManaCost * spellCost = previousManaPool->Diff(player->getManaPool()); + delete previousManaPool; + if (card->hasType("land")) + { + MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->temp); + Spell * spell = NEW Spell(copy); + spell->resolve(); + delete spellCost; + delete spell; + player->canPutLandsIntoPlay--; + payResult = ManaCost::MANA_PAID_WITH_RETRACE; + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + else + { + Spell * spell = NULL; + MTGCardInstance * copy = player->game->putInZone(card, player->game->graveyard, player->game->stack); + if (game->targetChooser) + { + spell = game->mLayers->stackLayer()->addSpell(copy, game->targetChooser, spellCost, payResult, 0); + game->targetChooser = NULL; + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; + } + } + else + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 0); + player->castedspellsthisturn += 1; + player->opponent()->castedspellsthisturn += 1; + if (player->onlyonecast > 0 || player->onlyoneinstant > 0) + { + player->castcount += 1; - } - } - if(card->has(Constants::STORM)){ - int storm = player->castedspellsthisturn; - ManaCost * spellCost = player->getManaPool(); - for(int i = storm; i > 1; i--){ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); - } - }//end of storm - if(!card->has(Constants::STORM)){ - copy->X = spell->computeX(copy); - copy->XX = spell->computeXX(copy); - } - } + } + } + if (card->has(Constants::STORM)) + { + int storm = player->castedspellsthisturn; + ManaCost * spellCost = player->getManaPool(); + for (int i = storm; i > 1; i--) + { + spell = game->mLayers->stackLayer()->addSpell(copy, NULL, spellCost, payResult, 1); + } + }//end of storm + if (!card->has(Constants::STORM)) + { + copy->X = spell->computeX(copy); + copy->XX = spell->computeXX(copy); + } + } - return 1; + return 1; } //The Put into play rule is never destroyed -int MTGRetraceRule::testDestroy(){ - return 0; +int MTGRetraceRule::testDestroy() +{ + return 0; } ostream& MTGRetraceRule::toString(ostream& out) const { - out << "MTGRetraceRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGRetraceRule ::: ("; + return MTGAbility::toString(out) << ")"; } -MTGRetraceRule * MTGRetraceRule::clone() const{ - MTGRetraceRule * a = NEW MTGRetraceRule(*this); - a->isClone = 1; - return a; +MTGRetraceRule * MTGRetraceRule::clone() const +{ + MTGRetraceRule * a = NEW MTGRetraceRule(*this); + a->isClone = 1; + return a; } - //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- //----------------------------- bool MTGAttackRule::select(Target* t) { - if (CardView* c = dynamic_cast(t)) { - MTGCardInstance * card = c->getCard(); - if (card->canAttack()) return true; - } - return false; + if (CardView* c = dynamic_cast(t)) + { + MTGCardInstance * card = c->getCard(); + if (card->canAttack()) + return true; + } + return false; } bool MTGAttackRule::greyout(Target* t) { - return true; + return true; } -MTGAttackRule::MTGAttackRule(int _id):MTGAbility(_id,NULL){ - aType=MTGAbility::MTG_ATTACK_RULE; +MTGAttackRule::MTGAttackRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::MTG_ATTACK_RULE; } -int MTGAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - if (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer){ - if (card->isAttacker()) return 1; - if (card->canAttack()) return 1; - } - return 0; +int MTGAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + if (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer) + { + if (card->isAttacker()) + return 1; + if (card->canAttack()) + return 1; + } + return 0; } -int MTGAttackRule::receiveEvent(WEvent *e){ - if (WEventPhaseChange* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_COMBATATTACKERS == event->from->id) { - Player * p = game->currentPlayer; - MTGGameZone * z = p->game->inPlay; - for (int i= 0; i < z->nb_cards; i++){ - MTGCardInstance * card = z->cards[i]; - if (!card->isAttacker() && card->has(Constants::MUSTATTACK)) reactToClick(card); - if (card->isAttacker() && card->isTapped()) card->setAttacker(0); - if (card->isAttacker() && !card->has(Constants::VIGILANCE)) card->tap(); - } - return 1; - } - } - return 0; +int MTGAttackRule::receiveEvent(WEvent *e) +{ + if (WEventPhaseChange* event = dynamic_cast(e)) + { + if (Constants::MTG_PHASE_COMBATATTACKERS == event->from->id) + { + Player * p = game->currentPlayer; + MTGGameZone * z = p->game->inPlay; + for (int i = 0; i < z->nb_cards; i++) + { + MTGCardInstance * card = z->cards[i]; + if (!card->isAttacker() && card->has(Constants::MUSTATTACK)) + reactToClick(card); + if (card->isAttacker() && card->isTapped()) + card->setAttacker(0); + if (card->isAttacker() && !card->has(Constants::VIGILANCE)) + card->tap(); + } + return 1; + } + } + return 0; } -int MTGAttackRule::reactToClick(MTGCardInstance * card){ - if (!isReactingToClick(card)) return 0; +int MTGAttackRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; - //Graphically select the next card that can attack - if(!card->isAttacker()){ - CardSelectorSingleton::Instance()->PushLimitor(); - CardSelectorSingleton::Instance()->Limit(this, CardView::playZone); - CardSelectorSingleton::Instance()->CheckUserInput(JGE_BTN_RIGHT); - CardSelectorSingleton::Instance()->Limit(NULL, CardView::playZone); - CardSelectorSingleton::Instance()->PopLimitor(); - } - card->toggleAttacker(); - return 1; + //Graphically select the next card that can attack + if (!card->isAttacker()) + { + CardSelectorSingleton::Instance()->PushLimitor(); + CardSelectorSingleton::Instance()->Limit(this, CardView::playZone); + CardSelectorSingleton::Instance()->CheckUserInput(JGE_BTN_RIGHT); + CardSelectorSingleton::Instance()->Limit(NULL, CardView::playZone); + CardSelectorSingleton::Instance()->PopLimitor(); + } + card->toggleAttacker(); + return 1; } //The Attack rule is never destroyed -int MTGAttackRule::testDestroy(){ - return 0; +int MTGAttackRule::testDestroy() +{ + return 0; } ostream& MTGAttackRule::toString(ostream& out) const { - out << "MTGAttackRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGAttackRule ::: ("; + return MTGAbility::toString(out) << ")"; } -MTGAttackRule * MTGAttackRule::clone() const{ - MTGAttackRule * a = NEW MTGAttackRule(*this); - a->isClone = 1; - return a; +MTGAttackRule * MTGAttackRule::clone() const +{ + MTGAttackRule * a = NEW MTGAttackRule(*this); + a->isClone = 1; + return a; } //this rules handles returning cards to combat triggers for activations. -MTGCombatTriggersRule::MTGCombatTriggersRule(int _id):MTGAbility(_id,NULL){ - aType=MTGAbility::MTG_COMBATTRIGGERS_RULE; +MTGCombatTriggersRule::MTGCombatTriggersRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::MTG_COMBATTRIGGERS_RULE; } -int MTGCombatTriggersRule::receiveEvent(WEvent *e){ - if (WEventPhaseChange* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_COMBATATTACKERS == event->from->id) { - Player * p = game->currentPlayer; - MTGGameZone * z = p->game->inPlay; - for (int i= 0; i < z->nb_cards; i++){ - MTGCardInstance * card = z->cards[i]; - if (card && card->isAttacker()){ - card->eventattacked(); - } - } - } - if (Constants::MTG_PHASE_COMBATEND == event->from->id) { - Player * p = game->currentPlayer->opponent(); - MTGGameZone * z = p->game->inPlay; - for (int i= 0; i < z->nb_cards; i++){ - MTGCardInstance * card = z->cards[i]; - if (card){ - card->didattacked = 0; - card->didblocked = 0; - card->notblocked = 0; - } - } - } -//--------------- - } - if (WEventAttackersChosen * event = dynamic_cast(e)) - { - MTGCardInstance * lonelyAttacker = NULL; - int nbattackers = 0; - Player * p = game->currentPlayer; - MTGGameZone * z = p->game->inPlay; - int nbcards = z->nb_cards; - for (int i = 0; i < nbcards; ++i){ - MTGCardInstance * c = z->cards[i]; - if (c->attacker){ - nbattackers++; - lonelyAttacker = c; - } +int MTGCombatTriggersRule::receiveEvent(WEvent *e) +{ + if (WEventPhaseChange* event = dynamic_cast(e)) + { + if (Constants::MTG_PHASE_COMBATATTACKERS == event->from->id) + { + Player * p = game->currentPlayer; + MTGGameZone * z = p->game->inPlay; + for (int i = 0; i < z->nb_cards; i++) + { + MTGCardInstance * card = z->cards[i]; + if (card && card->isAttacker()) + { + card->eventattacked(); + } + } + } + if (Constants::MTG_PHASE_COMBATEND == event->from->id) + { + Player * p = game->currentPlayer->opponent(); + MTGGameZone * z = p->game->inPlay; + for (int i = 0; i < z->nb_cards; i++) + { + MTGCardInstance * card = z->cards[i]; + if (card) + { + card->didattacked = 0; + card->didblocked = 0; + card->notblocked = 0; + } + } + } + //--------------- + } + if (WEventAttackersChosen * event = dynamic_cast(e)) + { + MTGCardInstance * lonelyAttacker = NULL; + int nbattackers = 0; + Player * p = game->currentPlayer; + MTGGameZone * z = p->game->inPlay; + int nbcards = z->nb_cards; + for (int i = 0; i < nbcards; ++i) + { + MTGCardInstance * c = z->cards[i]; + if (c->attacker) + { + nbattackers++; + lonelyAttacker = c; + } + } + if (nbattackers == 1) + { + lonelyAttacker->eventattackedAlone(); + } + else + lonelyAttacker = NULL; + } + if (WEventBlockersChosen * event = dynamic_cast(e)) + { + Player * p = game->currentPlayer; + MTGGameZone * z = p->game->inPlay; + for (int i = 0; i < z->nb_cards; i++) + { + MTGCardInstance * card = z->cards[i]; + if (card && card->isAttacker() && !card->blocked) + { + card->eventattackednotblocked(); + card->notblocked += 1; + } + if (card && card->isAttacker() && card->blocked) + { + card->eventattackedblocked(); + } } - if (nbattackers == 1) - { - lonelyAttacker->eventattackedAlone(); - } - else lonelyAttacker = NULL; - } - if (WEventBlockersChosen * event = dynamic_cast(e)) - { - Player * p = game->currentPlayer; - MTGGameZone * z = p->game->inPlay; - for (int i= 0; i < z->nb_cards; i++){ - MTGCardInstance * card = z->cards[i]; - if (card && card->isAttacker() && !card->blocked) - { - card->eventattackednotblocked(); - card->notblocked += 1; - } - if (card && card->isAttacker() && card->blocked) - { - card->eventattackedblocked(); - } - } - MTGGameZone* opponentZone = game->currentPlayer->opponent()->game->inPlay; - for (int i = 0; i < opponentZone->nb_cards; i++) - { - MTGCardInstance* card = opponentZone->cards[i]; - if (card && card->didblocked > 0){ - card->eventblocked(); - } - } - } - return 0; + MTGGameZone* opponentZone = game->currentPlayer->opponent()->game->inPlay; + for (int i = 0; i < opponentZone->nb_cards; i++) + { + MTGCardInstance* card = opponentZone->cards[i]; + if (card && card->didblocked > 0) + { + card->eventblocked(); + } + } + } + return 0; } //trigger rules are never distroyed -int MTGCombatTriggersRule::testDestroy(){ - return 0; +int MTGCombatTriggersRule::testDestroy() +{ + return 0; } ostream& MTGCombatTriggersRule::toString(ostream& out) const { - out << "MTGCombatTriggersRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGCombatTriggersRule ::: ("; + return MTGAbility::toString(out) << ")"; } -MTGCombatTriggersRule * MTGCombatTriggersRule::clone() const{ - MTGCombatTriggersRule * a = NEW MTGCombatTriggersRule(*this); - a->isClone = 1; - return a; +MTGCombatTriggersRule * MTGCombatTriggersRule::clone() const +{ + MTGCombatTriggersRule * a = NEW MTGCombatTriggersRule(*this); + a->isClone = 1; + return a; } ///------------ -OtherAbilitiesEventReceiver::OtherAbilitiesEventReceiver(int _id):MTGAbility(_id,NULL){ +OtherAbilitiesEventReceiver::OtherAbilitiesEventReceiver(int _id) : + MTGAbility(_id, NULL) +{ } - -int OtherAbilitiesEventReceiver::receiveEvent(WEvent *e){ - if (WEventZoneChange* event = dynamic_cast(e)) { - if (event->to && (event->to != event->from)){ - GameObserver * g = GameObserver::GetInstance(); - for (int i = 0; i < 2; ++i){ - if (event->to == g->players[i]->game->inPlay) return 0; - } - AbilityFactory af; - af.magicText(g->mLayers->actionLayer()->getMaxId(), NULL, event->card, 1, 0,event->to); - return 1; - } - } - return 0; +int OtherAbilitiesEventReceiver::receiveEvent(WEvent *e) +{ + if (WEventZoneChange* event = dynamic_cast(e)) + { + if (event->to && (event->to != event->from)) + { + GameObserver * g = GameObserver::GetInstance(); + for (int i = 0; i < 2; ++i) + { + if (event->to == g->players[i]->game->inPlay) + return 0; + } + AbilityFactory af; + af.magicText(g->mLayers->actionLayer()->getMaxId(), NULL, event->card, 1, 0, event->to); + return 1; + } + } + return 0; } -int OtherAbilitiesEventReceiver::testDestroy(){ - return 0; +int OtherAbilitiesEventReceiver::testDestroy() +{ + return 0; } -OtherAbilitiesEventReceiver * OtherAbilitiesEventReceiver::clone() const{ - OtherAbilitiesEventReceiver * a = NEW OtherAbilitiesEventReceiver(*this); - a->isClone = 1; - return a; +OtherAbilitiesEventReceiver * OtherAbilitiesEventReceiver::clone() const +{ + OtherAbilitiesEventReceiver * a = NEW OtherAbilitiesEventReceiver(*this); + a->isClone = 1; + return a; } - -MTGBlockRule::MTGBlockRule(int _id):MTGAbility(_id,NULL){ - aType=MTGAbility::MTG_BLOCK_RULE; +MTGBlockRule::MTGBlockRule(int _id) : + MTGAbility(_id, NULL) +{ + aType = MTGAbility::MTG_BLOCK_RULE; } -int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() == game->currentlyActing()){ - if (card->canBlock())return 1; - } - return 0; +int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() + == game->currentlyActing()) + { + if (card->canBlock()) + return 1; + } + return 0; } -int MTGBlockRule::reactToClick(MTGCardInstance * card){ - if (!isReactingToClick(card)) return 0; - MTGCardInstance * currentOpponent = card->isDefenser(); - bool result = false; - int candefend = 0; - while (!result){ - currentOpponent = game->currentPlayer->game->inPlay->getNextAttacker(currentOpponent); - DebugTrace("Defenser Toggle: " << card->getName()); - candefend = card->toggleDefenser(currentOpponent); - result = (candefend || currentOpponent == NULL); - } - return 1; +int MTGBlockRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; + MTGCardInstance * currentOpponent = card->isDefenser(); + bool result = false; + int candefend = 0; + while (!result) + { + currentOpponent = game->currentPlayer->game->inPlay->getNextAttacker(currentOpponent); + DebugTrace("Defenser Toggle: " << card->getName()); + candefend = card->toggleDefenser(currentOpponent); + result = (candefend || currentOpponent == NULL); + } + return 1; } - - //The Block rule is never destroyed -int MTGBlockRule::testDestroy(){ - return 0; +int MTGBlockRule::testDestroy() +{ + return 0; } ostream& MTGBlockRule::toString(ostream& out) const { - out << "MTGBlockRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGBlockRule ::: ("; + return MTGAbility::toString(out) << ")"; } -MTGBlockRule * MTGBlockRule::clone() const{ - MTGBlockRule * a = NEW MTGBlockRule(*this); - a->isClone = 1; - return a; +MTGBlockRule * MTGBlockRule::clone() const +{ + MTGBlockRule * a = NEW MTGBlockRule(*this); + a->isClone = 1; + return a; } // // Attacker chooses blockers order @@ -935,723 +1277,1049 @@ MTGBlockRule * MTGBlockRule::clone() const{ int MTGMomirRule::initialized = 0; vector MTGMomirRule::pool[20]; -MTGMomirRule::MTGMomirRule(int _id, MTGAllCards * _collection):MTGAbility(_id, NULL){ - collection = _collection; - if (!initialized){ - for (size_t i = 0; i < collection->ids.size(); i++){ - MTGCard * card = collection->collection[collection->ids[i]]; - if (card->data->isCreature() && - (card->getRarity() != Constants::RARITY_T) && //remove tokens - card->setId != MTGSets::INTERNAL_SET //remove cards that are defined in primitives. Those are workarounds (usually tokens) and should only be used internally - ){ - int convertedCost = card->data->getManaCost()->getConvertedCost(); - if (convertedCost>20) continue; - pool[convertedCost].push_back(card->getMTGId()); - } - } - initialized =1; - } - alreadyplayed = 0; - aType=MTGAbility::MOMIR; - textAlpha = 0; +MTGMomirRule::MTGMomirRule(int _id, MTGAllCards * _collection) : + MTGAbility(_id, NULL) +{ + collection = _collection; + if (!initialized) + { + for (size_t i = 0; i < collection->ids.size(); i++) + { + MTGCard * card = collection->collection[collection->ids[i]]; + if (card->data->isCreature() && (card->getRarity() != Constants::RARITY_T) && //remove tokens + card->setId != MTGSets::INTERNAL_SET //remove cards that are defined in primitives. Those are workarounds (usually tokens) and should only be used internally + ) + { + int convertedCost = card->data->getManaCost()->getConvertedCost(); + if (convertedCost > 20) + continue; + pool[convertedCost].push_back(card->getMTGId()); + } + } + initialized = 1; + } + alreadyplayed = 0; + aType = MTGAbility::MOMIR; + textAlpha = 0; } -int MTGMomirRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - if (alreadyplayed) return 0; - Player * player = game->currentlyActing(); - Player * currentPlayer = game->currentPlayer; - if (!player->game->hand->hasCard(card)) return 0; - if (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)){ - return 1; - } - return 0; +int MTGMomirRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + if (alreadyplayed) + return 0; + Player * player = game->currentlyActing(); + Player * currentPlayer = game->currentPlayer; + if (!player->game->hand->hasCard(card)) + return 0; + if (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN + || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) + { + return 1; + } + return 0; } -int MTGMomirRule::reactToClick(MTGCardInstance * card_to_discard){ - Player * player = game->currentlyActing(); - ManaCost * cost = player->getManaPool(); - int converted = cost->getConvertedCost(); - int id = genRandomCreatureId(converted); - return reactToClick(card_to_discard, id); +int MTGMomirRule::reactToClick(MTGCardInstance * card_to_discard) +{ + Player * player = game->currentlyActing(); + ManaCost * cost = player->getManaPool(); + int converted = cost->getConvertedCost(); + int id = genRandomCreatureId(converted); + return reactToClick(card_to_discard, id); } -int MTGMomirRule::reactToClick(MTGCardInstance * card_to_discard, int cardId){ - if (!isReactingToClick(card_to_discard)) return 0; - Player * player = game->currentlyActing(); - ManaCost * cost = player->getManaPool(); - player->getManaPool()->pay(cost); - MTGCardInstance * card = genCreature(cardId); - player->game->putInZone(card_to_discard, player->game->hand, player->game->graveyard); +int MTGMomirRule::reactToClick(MTGCardInstance * card_to_discard, int cardId) +{ + if (!isReactingToClick(card_to_discard)) + return 0; + Player * player = game->currentlyActing(); + ManaCost * cost = player->getManaPool(); + player->getManaPool()->pay(cost); + MTGCardInstance * card = genCreature(cardId); + player->game->putInZone(card_to_discard, player->game->hand, player->game->graveyard); - player->game->stack->addCard(card); - Spell * spell = NEW Spell(card); - spell->resolve(); - spell->source->isToken = 1; - delete spell; - alreadyplayed = 1; - textAlpha = 255; - text = card->name; - return 1; + player->game->stack->addCard(card); + Spell * spell = NEW Spell(card); + spell->resolve(); + spell->source->isToken = 1; + delete spell; + alreadyplayed = 1; + textAlpha = 255; + text = card->name; + return 1; } -MTGCardInstance * MTGMomirRule::genCreature( int id){ - if (!id) return NULL; - Player * p = game->currentlyActing(); - MTGCard * card = collection->getCardById(id); - return NEW MTGCardInstance(card,p->game); +MTGCardInstance * MTGMomirRule::genCreature(int id) +{ + if (!id) + return NULL; + Player * p = game->currentlyActing(); + MTGCard * card = collection->getCardById(id); + return NEW MTGCardInstance(card, p->game); } -int MTGMomirRule::genRandomCreatureId(int convertedCost){ - if (convertedCost >= 20) convertedCost = 19; - int total_cards = 0; - int i = convertedCost; - while (!total_cards && i >=0){ - DebugTrace("Converted Cost in momir: " << i); - total_cards = pool[i].size(); - convertedCost = i; - i--; - } - if (!total_cards) return 0; - int start = (WRand() % total_cards); - return pool[convertedCost][start]; +int MTGMomirRule::genRandomCreatureId(int convertedCost) +{ + if (convertedCost >= 20) + convertedCost = 19; + int total_cards = 0; + int i = convertedCost; + while (!total_cards && i >= 0) + { + DebugTrace("Converted Cost in momir: " << i); + total_cards = pool[i].size(); + convertedCost = i; + i--; + } + if (!total_cards) + return 0; + int start = (WRand() % total_cards); + return pool[convertedCost][start]; } //The Momir rule is never destroyed -int MTGMomirRule::testDestroy(){ - return 0; +int MTGMomirRule::testDestroy() +{ + return 0; } -void MTGMomirRule::Update(float dt){ - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP){ - alreadyplayed = 0; - } - if (textAlpha){ - textAlpha -= static_cast(200*dt); - if (textAlpha <0) textAlpha = 0; - } - MTGAbility::Update(dt); +void MTGMomirRule::Update(float dt) +{ + if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP) + { + alreadyplayed = 0; + } + if (textAlpha) + { + textAlpha -= static_cast (200 * dt); + if (textAlpha < 0) + textAlpha = 0; + } + MTGAbility::Update(dt); } -void MTGMomirRule::Render(){ - if (!textAlpha) return; - WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); - mFont->SetScale(2 - (float)textAlpha/130); - mFont->SetColor(ARGB(textAlpha,255,255,255)); - mFont->DrawString(text.c_str(),SCREEN_WIDTH/2,SCREEN_HEIGHT/2,JGETEXT_CENTER); +void MTGMomirRule::Render() +{ + if (!textAlpha) + return; + WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); + mFont->SetScale(2 - (float) textAlpha / 130); + mFont->SetColor(ARGB(textAlpha,255,255,255)); + mFont->DrawString(text.c_str(), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, JGETEXT_CENTER); } ostream& MTGMomirRule::toString(ostream& out) const { - out << "MTGMomirRule ::: pool : " << pool << " ; initialized : " << initialized << " ; textAlpha : " << textAlpha << " ; text " << text << " ; alreadyplayed : " << alreadyplayed << " ; collection : " << collection << "("; - return MTGAbility::toString(out) << ")"; + out << "MTGMomirRule ::: pool : " << pool << " ; initialized : " << initialized << " ; textAlpha : " << textAlpha << " ; text " + << text << " ; alreadyplayed : " << alreadyplayed << " ; collection : " << collection << "("; + return MTGAbility::toString(out) << ")"; } - -MTGMomirRule * MTGMomirRule::clone() const{ - MTGMomirRule * a = NEW MTGMomirRule(*this); - a->isClone = 1; - return a; +MTGMomirRule * MTGMomirRule::clone() const +{ + MTGMomirRule * a = NEW MTGMomirRule(*this); + a->isClone = 1; + return a; } //HUDDisplay -int HUDDisplay::testDestroy(){ - return 0; +int HUDDisplay::testDestroy() +{ + return 0; } -void HUDDisplay::Update(float dt){ - timestamp += dt; - popdelay +=dt; - if (events.size()){ - list::iterator it = events.begin(); - HUDString * hs = *it; - if (popdelay > 1 && timestamp - hs->timestamp > 2){ - events.pop_front(); - delete hs; - if (events.size()) popdelay = 0; - } - }else{ - maxWidth = 0; - } +void HUDDisplay::Update(float dt) +{ + timestamp += dt; + popdelay += dt; + if (events.size()) + { + list::iterator it = events.begin(); + HUDString * hs = *it; + if (popdelay > 1 && timestamp - hs->timestamp > 2) + { + events.pop_front(); + delete hs; + if (events.size()) + popdelay = 0; + } + } + else + { + maxWidth = 0; + } } -int HUDDisplay::addEvent(string s){ - events.push_back(NEW HUDString(s, timestamp)); - float width = f->GetStringWidth(s.c_str()); - if (width > maxWidth) maxWidth = width; - return 1; +int HUDDisplay::addEvent(string s) +{ + events.push_back(NEW HUDString(s, timestamp)); + float width = f->GetStringWidth(s.c_str()); + if (width > maxWidth) + maxWidth = width; + return 1; } -int HUDDisplay::receiveEvent(WEvent * event){ +int HUDDisplay::receiveEvent(WEvent * event) +{ - WEventZoneChange * ezc = dynamic_cast(event); - if (ezc) { - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - if (ezc->to == p->game->graveyard ){ - char buffer[512]; - sprintf(buffer,_("%s goes to graveyard").c_str(), _(ezc->card->getName()).c_str()); - string s = buffer; - return addEvent(s); - } - } - } + WEventZoneChange * ezc = dynamic_cast (event); + if (ezc) + { + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (ezc->to == p->game->graveyard) + { + char buffer[512]; + sprintf(buffer, _("%s goes to graveyard").c_str(), _(ezc->card->getName()).c_str()); + string s = buffer; + return addEvent(s); + } + } + } - WEventDamage * ed = dynamic_cast(event); - if (ed) { - char buffer[512]; - sprintf(buffer, "%s: %i -> %s", _(ed->damage->source->name).c_str(), ed->damage->damage, _(ed->damage->target->getDisplayName()).c_str()); - string s = buffer; - return addEvent(s); - } + WEventDamage * ed = dynamic_cast (event); + if (ed) + { + char buffer[512]; + sprintf(buffer, "%s: %i -> %s", _(ed->damage->source->name).c_str(), ed->damage->damage, _( + ed->damage->target->getDisplayName()).c_str()); + string s = buffer; + return addEvent(s); + } - return 0; + return 0; } -void HUDDisplay::Render(){ - if (!options[Options::OSD].number) return; - if (!events.size()) return; +void HUDDisplay::Render() +{ + if (!options[Options::OSD].number) + return; + if (!events.size()) + return; - f->SetColor(ARGB(255,255,255,255)); + f->SetColor(ARGB(255,255,255,255)); - list::reverse_iterator it; + list::reverse_iterator it; - float x0 = SCREEN_WIDTH-10-maxWidth-10; - float y0 = 20; - float size = static_cast(events.size() * 16); - JRenderer * r = JRenderer::GetInstance(); - r->FillRoundRect(x0,y0,maxWidth + 10,size,5,ARGB(50,0,0,0)); + float x0 = SCREEN_WIDTH - 10 - maxWidth - 10; + float y0 = 20; + float size = static_cast (events.size() * 16); + JRenderer * r = JRenderer::GetInstance(); + r->FillRoundRect(x0, y0, maxWidth + 10, size, 5, ARGB(50,0,0,0)); - int i = 0; - for (it = events.rbegin(); it !=events.rend(); ++it){ - HUDString * hs = *it; - f->DrawString(hs->value.c_str(),x0 + 5, y0 + 16 * i); - i++; - } + int i = 0; + for (it = events.rbegin(); it != events.rend(); ++it) + { + HUDString * hs = *it; + f->DrawString(hs->value.c_str(), x0 + 5, y0 + 16 * i); + i++; + } } -HUDDisplay::HUDDisplay(int _id):MTGAbility(_id, NULL){ - timestamp = 0; - popdelay = 2; - f = resources.GetWFont(Fonts::MAIN_FONT); - maxWidth = 0; +HUDDisplay::HUDDisplay(int _id) : + MTGAbility(_id, NULL) +{ + timestamp = 0; + popdelay = 2; + f = resources.GetWFont(Fonts::MAIN_FONT); + maxWidth = 0; } -HUDDisplay::~HUDDisplay(){ - list::iterator it; - for (it = events.begin(); it !=events.end(); ++it){ - HUDString * hs = *it; - delete hs; - } - events.clear(); +HUDDisplay::~HUDDisplay() +{ + list::iterator it; + for (it = events.begin(); it != events.end(); ++it) + { + HUDString * hs = *it; + delete hs; + } + events.clear(); } -HUDDisplay * HUDDisplay::clone() const{ - HUDDisplay * a = NEW HUDDisplay(*this); - a->isClone = 1; - return a; +HUDDisplay * HUDDisplay::clone() const +{ + HUDDisplay * a = NEW HUDDisplay(*this); + a->isClone = 1; + return a; } - /* Persist */ -MTGPersistRule::MTGPersistRule(int _id):MTGAbility(_id,NULL){}; +MTGPersistRule::MTGPersistRule(int _id) : + MTGAbility(_id, NULL) +{ +} +; -int MTGPersistRule::receiveEvent(WEvent * event){ - if (event->type == WEvent::CHANGE_ZONE){ - WEventZoneChange * e = (WEventZoneChange *) event; - MTGCardInstance * card = e->card->previous; - if (card && card->basicAbilities[Constants::PERSIST] && !card->counters->hasCounter(-1,-1)){ - int ok = 0; - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - if (e->from == p->game->inPlay) ok = 1; - } - if (!ok) return 0; - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - if (e->to == p->game->graveyard){ - MTGCardInstance * copy = p->game->putInZone(e->card, p->game->graveyard, e->card->owner->game->stack); - Spell * spell = NEW Spell(copy); - spell->resolve(); - spell->source->counters->addCounter(-1,-1); - delete spell; - return 1; - } - } - } - } - return 0; +int MTGPersistRule::receiveEvent(WEvent * event) +{ + if (event->type == WEvent::CHANGE_ZONE) + { + WEventZoneChange * e = (WEventZoneChange *) event; + MTGCardInstance * card = e->card->previous; + if (card && card->basicAbilities[Constants::PERSIST] && !card->counters->hasCounter(-1, -1)) + { + int ok = 0; + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (e->from == p->game->inPlay) + ok = 1; + } + if (!ok) + return 0; + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (e->to == p->game->graveyard) + { + MTGCardInstance * copy = p->game->putInZone(e->card, p->game->graveyard, e->card->owner->game->stack); + Spell * spell = NEW Spell(copy); + spell->resolve(); + spell->source->counters->addCounter(-1, -1); + delete spell; + return 1; + } + } + } + } + return 0; } ostream& MTGPersistRule::toString(ostream& out) const { - out << "MTGPersistRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGPersistRule ::: ("; + return MTGAbility::toString(out) << ")"; } -int MTGPersistRule::testDestroy(){return 0;} -MTGPersistRule * MTGPersistRule::clone() const{ - MTGPersistRule * a = NEW MTGPersistRule(*this); - a->isClone = 1; - return a; +int MTGPersistRule::testDestroy() +{ + return 0; +} +MTGPersistRule * MTGPersistRule::clone() const +{ + MTGPersistRule * a = NEW MTGPersistRule(*this); + a->isClone = 1; + return a; } //putting cards with restricting effects inplay -MTGCantCasterstart::MTGCantCasterstart(int _id):MTGAbility(_id,NULL){}; -int MTGCantCasterstart::receiveEvent(WEvent * event){ - if (event->type == WEvent::CHANGE_ZONE){ - WEventZoneChange * e = (WEventZoneChange *) event; - MTGCardInstance * card = e->card->previous; - if(card){ - if(e->from == e->card->controller()->game->battlefield && e->to == e->card->controller()->game->graveyard){ - e->card->fresh = 1; - } - if(e->to == e->card->controller()->game->battlefield){ - e->card->fresh = 1; - } - if (card->basicAbilities[Constants::BOTHCANTCAST] || card->basicAbilities[Constants::BOTHNOCREATURE] || card->basicAbilities[Constants::CANTCAST] || card->basicAbilities[Constants::CANTCASTCREATURE] || card->basicAbilities[Constants::CANTCASTTWO] || card->basicAbilities[Constants::ONLYONEBOTH] || card->basicAbilities[Constants::NOMAXHAND] ){ - int ok = 0; - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from == p->game->exile || e->to == p->game->inPlay || e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library || e->to == p->game->exile || e->from == p->game->inPlay ){ ok = 1; - //check happens---------- - //reset restrictions if they exist and runs a check if these cards still exist. - p->nomaxhandsize = 0; - p->opponent()->nomaxhandsize = 0; - p->onlyonecast = 0; - p->opponent()->onlyonecast = 0; - p->castrestrictedspell = 0;//0 means no restrictions apply. - p->castrestrictedcreature = 0; - p->opponent()->castrestrictedspell = 0; - p->opponent()->castrestrictedcreature = 0; - /*--------------------------------------------------------------*/ - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - MTGGameZone * z = card->controller()->game->inPlay; - MTGGameZone * y = card->controller()->opponent()->game->inPlay; - int nbcards = z->nb_cards; - int onbcards = y->nb_cards; - //handsize modifier - //check my battlefield and opponents - for (int j = 0; j < nbcards; ++j){ - MTGCardInstance * c = z->cards[j]; - if (c->has(Constants::NOMAXHAND)){ - card->controller()->nomaxhandsize = 1; - } - if (c->has(Constants::BOTHCANTCAST)){ - card->controller()->castrestrictedspell = 1; - card->controller()->opponent()->castrestrictedspell = 1; - } - if (c->has(Constants::CANTCAST)){ - card->controller()->castrestrictedspell = 1; - } - if (c->has(Constants::BOTHNOCREATURE)){ - card->controller()->castrestrictedcreature += 1; - card->controller()->opponent()->castrestrictedcreature += 1; - } - if (c->has(Constants::CANTCASTCREATURE)){ - card->controller()->castrestrictedcreature = 1; - } - if (c->has(Constants::ONLYONEBOTH)){ - card->controller()->onlyonecast = 1; - card->controller()->opponent()->onlyonecast = 1; - } - if (c->has(Constants::CANTCASTTWO)){ - card->controller()->onlyonecast = 1; - } - } - //any on other side? - for (int j = 0; j < onbcards; ++j){ - MTGCardInstance * c = y->cards[j]; - if (c->has(Constants::NOMAXHAND)){ - card->controller()->opponent()->nomaxhandsize = 1; - } - if (c->has(Constants::BOTHCANTCAST)){ - card->controller()->castrestrictedspell = 1; - card->controller()->opponent()->castrestrictedspell = 1; - } - if (c->has(Constants::BOTHNOCREATURE)){ - card->controller()->castrestrictedcreature = 1; - card->controller()->opponent()->castrestrictedcreature = 1; - } - if (c->has(Constants::CANTCASTCREATURE)){ - card->controller()->opponent()->castrestrictedcreature = 1; - } - if (c->has(Constants::ONLYONEBOTH)){ - card->controller()->onlyonecast = 1; - card->controller()->opponent()->onlyonecast = 1; - } - if (c->has(Constants::CANTCASTTWO)){ - card->controller()->opponent()->onlyonecast = 1; - } - if (c->has(Constants::CANTCAST)){ - card->controller()->opponent()->castrestrictedspell = 1; - } - } - //-----if a card with both*restrict* was found then the players are still restricted, if one player is still restricted he stays restricted. - } - } - } - } - } - } - return 1; +MTGCantCasterstart::MTGCantCasterstart(int _id) : + MTGAbility(_id, NULL) +{ +} +; +int MTGCantCasterstart::receiveEvent(WEvent * event) +{ + if (event->type == WEvent::CHANGE_ZONE) + { + WEventZoneChange * e = (WEventZoneChange *) event; + MTGCardInstance * card = e->card->previous; + if (card) + { + if (e->from == e->card->controller()->game->battlefield && e->to == e->card->controller()->game->graveyard) + { + e->card->fresh = 1; + } + if (e->to == e->card->controller()->game->battlefield) + { + e->card->fresh = 1; + } + if (card->basicAbilities[Constants::BOTHCANTCAST] || card->basicAbilities[Constants::BOTHNOCREATURE] + || card->basicAbilities[Constants::CANTCAST] || card->basicAbilities[Constants::CANTCASTCREATURE] + || card->basicAbilities[Constants::CANTCASTTWO] || card->basicAbilities[Constants::ONLYONEBOTH] + || card->basicAbilities[Constants::NOMAXHAND]) + { + int ok = 0; + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from + == p->game->exile || e->to == p->game->inPlay || e->to == p->game->graveyard || e->to + == p->game->hand || e->to == p->game->library || e->to == p->game->exile || e->from + == p->game->inPlay) + { + ok = 1; + //check happens---------- + //reset restrictions if they exist and runs a check if these cards still exist. + p->nomaxhandsize = 0; + p->opponent()->nomaxhandsize = 0; + p->onlyonecast = 0; + p->opponent()->onlyonecast = 0; + p->castrestrictedspell = 0;//0 means no restrictions apply. + p->castrestrictedcreature = 0; + p->opponent()->castrestrictedspell = 0; + p->opponent()->castrestrictedcreature = 0; + /*--------------------------------------------------------------*/ + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + MTGGameZone * z = card->controller()->game->inPlay; + MTGGameZone * y = card->controller()->opponent()->game->inPlay; + int nbcards = z->nb_cards; + int onbcards = y->nb_cards; + //handsize modifier + //check my battlefield and opponents + for (int j = 0; j < nbcards; ++j) + { + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::NOMAXHAND)) + { + card->controller()->nomaxhandsize = 1; + } + if (c->has(Constants::BOTHCANTCAST)) + { + card->controller()->castrestrictedspell = 1; + card->controller()->opponent()->castrestrictedspell = 1; + } + if (c->has(Constants::CANTCAST)) + { + card->controller()->castrestrictedspell = 1; + } + if (c->has(Constants::BOTHNOCREATURE)) + { + card->controller()->castrestrictedcreature += 1; + card->controller()->opponent()->castrestrictedcreature += 1; + } + if (c->has(Constants::CANTCASTCREATURE)) + { + card->controller()->castrestrictedcreature = 1; + } + if (c->has(Constants::ONLYONEBOTH)) + { + card->controller()->onlyonecast = 1; + card->controller()->opponent()->onlyonecast = 1; + } + if (c->has(Constants::CANTCASTTWO)) + { + card->controller()->onlyonecast = 1; + } + } + //any on other side? + for (int j = 0; j < onbcards; ++j) + { + MTGCardInstance * c = y->cards[j]; + if (c->has(Constants::NOMAXHAND)) + { + card->controller()->opponent()->nomaxhandsize = 1; + } + if (c->has(Constants::BOTHCANTCAST)) + { + card->controller()->castrestrictedspell = 1; + card->controller()->opponent()->castrestrictedspell = 1; + } + if (c->has(Constants::BOTHNOCREATURE)) + { + card->controller()->castrestrictedcreature = 1; + card->controller()->opponent()->castrestrictedcreature = 1; + } + if (c->has(Constants::CANTCASTCREATURE)) + { + card->controller()->opponent()->castrestrictedcreature = 1; + } + if (c->has(Constants::ONLYONEBOTH)) + { + card->controller()->onlyonecast = 1; + card->controller()->opponent()->onlyonecast = 1; + } + if (c->has(Constants::CANTCASTTWO)) + { + card->controller()->opponent()->onlyonecast = 1; + } + if (c->has(Constants::CANTCAST)) + { + card->controller()->opponent()->castrestrictedspell = 1; + } + } + //-----if a card with both*restrict* was found then the players are still restricted, if one player is still restricted he stays restricted. + } + } + } + } + } + } + return 1; } ostream& MTGCantCasterstart::toString(ostream& out) const { - out << "MTGCantCasterstart ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGCantCasterstart ::: ("; + return MTGAbility::toString(out) << ")"; } -int MTGCantCasterstart::testDestroy(){return 0;} -MTGCantCasterstart * MTGCantCasterstart::clone() const{ - MTGCantCasterstart * a = NEW MTGCantCasterstart(*this); - a->isClone = 1; - return a; +int MTGCantCasterstart::testDestroy() +{ + return 0; +} +MTGCantCasterstart * MTGCantCasterstart::clone() const +{ + MTGCantCasterstart * a = NEW MTGCantCasterstart(*this); + a->isClone = 1; + return a; } //the end of this very complex code line. - //unearth rule---------------------------------- //if the card leaves play, exile it instead. -MTGUnearthRule::MTGUnearthRule(int _id):MTGAbility(_id,NULL){}; +MTGUnearthRule::MTGUnearthRule(int _id) : + MTGAbility(_id, NULL) +{ +} +; -int MTGUnearthRule::receiveEvent(WEvent * event){ - if (event->type == WEvent::CHANGE_ZONE){ - WEventZoneChange * e = (WEventZoneChange *) event; - MTGCardInstance * card = e->card->previous; - if (card && card->basicAbilities[Constants::UNEARTH]){ - int ok = 0; - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - if (e->from == p->game->inPlay) ok = 1; - } - if (!ok) return 0; - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - if (e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library){ - p->game->putInExile(e->card); - return 1; - } - } - } - } - return 0; +int MTGUnearthRule::receiveEvent(WEvent * event) +{ + if (event->type == WEvent::CHANGE_ZONE) + { + WEventZoneChange * e = (WEventZoneChange *) event; + MTGCardInstance * card = e->card->previous; + if (card && card->basicAbilities[Constants::UNEARTH]) + { + int ok = 0; + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (e->from == p->game->inPlay) + ok = 1; + } + if (!ok) + return 0; + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library) + { + p->game->putInExile(e->card); + return 1; + } + } + } + } + return 0; } ostream& MTGUnearthRule::toString(ostream& out) const { - out << "MTGUnearthRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGUnearthRule ::: ("; + return MTGAbility::toString(out) << ")"; } -int MTGUnearthRule::testDestroy(){return 0;} -MTGUnearthRule * MTGUnearthRule::clone() const{ - MTGUnearthRule * a = NEW MTGUnearthRule(*this); - a->isClone = 1; - return a; +int MTGUnearthRule::testDestroy() +{ + return 0; +} +MTGUnearthRule * MTGUnearthRule::clone() const +{ + MTGUnearthRule * a = NEW MTGUnearthRule(*this); + a->isClone = 1; + return a; } //---------------------------------------------------------------------- //sneakattack rule------------------------------------------------------ //this rule also handles the exile of unearth cards at end of turn. -MTGSneakAttackRule::MTGSneakAttackRule(int _id):MTGAbility(_id,NULL){}; +MTGSneakAttackRule::MTGSneakAttackRule(int _id) : + MTGAbility(_id, NULL) +{ +} +; -int MTGSneakAttackRule::receiveEvent(WEvent *e){ - if (WEventPhaseChange* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_ENDOFTURN == event->from->id) { - for (int j = 0; j < 2 ; j++){ - Player * p = game->players[j]; - MTGGameZone * z = p->game->inPlay; - for (int i= 0; i < z->nb_cards; i++){ - MTGCardInstance * card = z->cards[i]; - while(card->flanked){//undoes the flanking on a card - card->power += 1; - card->addToToughness(1); - card->flanked -= 1; - } - if (card->has(Constants::TREASON)) - { - WEvent * e = NEW WEventCardSacrifice(card); - GameObserver * game = GameObserver::GetInstance(); - game->receiveEvent(e); - p->game->putInGraveyard(card);i--; - } - if (card->has(Constants::UNEARTH)) {p->game->putInExile(card);i--;} - if (card->fresh) card->fresh = 0; - if (card->has(Constants::ONLYONEBOTH)) - { - card->controller()->castcount = 0; - card->controller()->opponent()->castcount = 0; - } - } - MTGGameZone * f = p->game->graveyard; - for (int k= 0; k < f->nb_cards; k++){ - MTGCardInstance * card = f->cards[k]; - card->fresh = 0; - } - } - } - return 1; - } - return 1; +int MTGSneakAttackRule::receiveEvent(WEvent *e) +{ + if (WEventPhaseChange* event = dynamic_cast(e)) + { + if (Constants::MTG_PHASE_ENDOFTURN == event->from->id) + { + for (int j = 0; j < 2; j++) + { + Player * p = game->players[j]; + MTGGameZone * z = p->game->inPlay; + for (int i = 0; i < z->nb_cards; i++) + { + MTGCardInstance * card = z->cards[i]; + while (card->flanked) + {//undoes the flanking on a card + card->power += 1; + card->addToToughness(1); + card->flanked -= 1; + } + if (card->has(Constants::TREASON)) + { + WEvent * e = NEW WEventCardSacrifice(card); + GameObserver * game = GameObserver::GetInstance(); + game->receiveEvent(e); + p->game->putInGraveyard(card); + i--; + } + if (card->has(Constants::UNEARTH)) + { + p->game->putInExile(card); + i--; + } + if (card->fresh) + card->fresh = 0; + if (card->has(Constants::ONLYONEBOTH)) + { + card->controller()->castcount = 0; + card->controller()->opponent()->castcount = 0; + } + } + MTGGameZone * f = p->game->graveyard; + for (int k = 0; k < f->nb_cards; k++) + { + MTGCardInstance * card = f->cards[k]; + card->fresh = 0; + } + } + } + return 1; + } + return 1; } ostream& MTGSneakAttackRule::toString(ostream& out) const { - out << "MTGSneakAttackRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGSneakAttackRule ::: ("; + return MTGAbility::toString(out) << ")"; } -int MTGSneakAttackRule::testDestroy(){return 0;} -MTGSneakAttackRule * MTGSneakAttackRule::clone() const{ - MTGSneakAttackRule * a = NEW MTGSneakAttackRule(*this); - a->isClone = 1; - return a; +int MTGSneakAttackRule::testDestroy() +{ + return 0; +} +MTGSneakAttackRule * MTGSneakAttackRule::clone() const +{ + MTGSneakAttackRule * a = NEW MTGSneakAttackRule(*this); + a->isClone = 1; + return a; } //Affinity rule------------------------------------------------------ //this rule is for Affinity cards. -MTGAffinityRule::MTGAffinityRule(int _id):MTGAbility(_id,NULL){}; -int MTGAffinityRule::receiveEvent(WEvent * event){ - if (event->type == WEvent::CHANGE_ZONE){ - WEventZoneChange * e = (WEventZoneChange *) event; - MTGCardInstance * card = e->card->previous; - if(e && card){ - int color = -1; - string type = ""; - int ok = 0; - for (int i = 0; i < 2 ; i++){ - Player * p = game->players[i]; - if (e->to == p->game->hand) ok = 1;//affinity card enters hand - //--------- - //when cards with affinity enter you hand from anywhere a redux is applied to them for the artifacts in play. - if(ok == 1){//enters play from anywhere - if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from == p->game->exile || e->from == p->game->stack || e->from == p->opponent()->game->battlefield || e->from == p->game->temp || e->from == p->game->battlefield){ - MTGCardInstance * card = e->card->previous; - if(card && card->has(Constants::AFFINITYARTIFACTS)) {color = 0 ; type = "artifact";} - if(card && card->has(Constants::AFFINITYSWAMP)) {color = 0 ; type = "swamp";} - if(card && card->has(Constants::AFFINITYMOUNTAIN)) {color = 0 ; type = "mountain";} - if(card && card->has(Constants::AFFINITYPLAINS)) {color = 0 ; type = "plains";} - if(card && card->has(Constants::AFFINITYISLAND)) {color = 0 ; type = "island";} - if(card && card->has(Constants::AFFINITYFOREST)) {color = 0 ; type = "forest";} - if(card && card->has(Constants::AFFINITYGREENCREATURES)) {color = 1 ; type = "creature";} - //--redux effect - MTGGameZone * z = card->controller()->game->battlefield; - int nbcards = z->nb_cards; - for (int j = 0; j < nbcards; ++j){ - MTGCardInstance * c = z->cards[j]; - int check = e->card->getManaCost()->getConvertedCost(); - if ((e->card->has(Constants::AFFINITYARTIFACTS) && c->hasSubtype("artifact") )|| ( e->card->has(Constants::AFFINITYSWAMP) && c->hasSubtype("swamp") )|| ( e->card->has(Constants::AFFINITYMOUNTAIN) && c->hasSubtype("moutain") )||( e->card->has(Constants::AFFINITYPLAINS) && c->hasSubtype("plains") )|| ( e->card->has(Constants::AFFINITYISLAND) && c->hasSubtype("island")) || ( e->card->has(Constants::AFFINITYFOREST) && c->hasSubtype("forest") )|| ( e->card->has(Constants::AFFINITYGREENCREATURES) && c->hasColor(1) && c->isCreature())){ - if( check > 0){ - if(color > 0 && !e->card->getManaCost()->hasColor(color)){//do nothing if its colored redux and the cards dont have the color - }else{ - //do normal redux - e->card->getManaCost()->remove(color,1); - }//one less colorless to cast - }else{ - e->card->reduxamount += 1; - } - } - }//--end of redux bracket - } - }//if ok == 1 - //-------------maintaining cost---------------------------------------------------------------- - ok = 0; - if (e->to == p->game->battlefield) ok = 2;//card enters play - if(ok == 2){//enters play from anywhere - if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from == p->game->exile || e->from == p->game->stack || e->from == p->game->temp){ - //--redux effect - MTGGameZone * z = card->controller()->game->hand; - int nbcards = z->nb_cards; - int colored = 0; - string etype = ""; - MTGCardInstance * card = e->card->previous; - if (card && card->hasSubtype("artifact")){etype.append("art");} - if (card && card->hasSubtype("swamp")){etype.append("swa");} - if (card && card->hasSubtype("mountain")){etype.append("mou");} - if (card && card->hasSubtype("plains")){etype.append("pla");} - if (card && card->hasSubtype("island")){etype.append("isl");} - if (card && card->hasSubtype("forest")){etype.append("for");} - if (card && card->hasSubtype("creature") && card->hasColor(1)){etype.append("cre"); colored = 1;} - for (int j = 0; j < nbcards; ++j){ - MTGCardInstance * c = z->cards[j]; - if ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art") != string::npos) || ( c->has(Constants::AFFINITYSWAMP) && etype.find("swa")!= string::npos) || ( c->has(Constants::AFFINITYMOUNTAIN) && etype.find("mou")!= string::npos) ||( c->has(Constants::AFFINITYPLAINS) && etype.find("pla")!= string::npos) || ( c->has(Constants::AFFINITYISLAND) && etype.find("isl")!= string::npos) || ( c->has(Constants::AFFINITYFOREST) && etype.find("for")!= string::npos) || ( c->has(Constants::AFFINITYGREENCREATURES) && etype.find("cre")!= string::npos)){ - if(c->getManaCost()->getConvertedCost() > 0){ - c->getManaCost()->remove(colored,1);//one less colorless to cast - }else{ - c->reduxamount += 1; - } - } - } - } - }//--end of redux bracket ok == 2 - //--------- - ok = 0; - if (e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library || e->to == p->game->exile || e->to == p->game->stack || e->to == p->opponent()->game->battlefield) ok = 3;//card leaves play - if(ok == 3){//leave play from your battlefield - if (e->from == p->game->battlefield){ - int colored = 0; - MTGGameZone * z = card->controller()->game->hand; - int nbcards = z->nb_cards; - string etype = ""; - MTGCardInstance * card = e->card->previous; - if (card && card->hasSubtype("artifact")){etype.append("art");} - if (card && card->hasSubtype("swamp")){etype.append("swa");} - if (card && card->hasSubtype("mountain")){etype.append("mou");} - if (card && card->hasSubtype("plains")){etype.append("pla");} - if (card && card->hasSubtype("island")){etype.append("isl");} - if (card && card->hasSubtype("forest")){etype.append("for");} - if (card && card->hasSubtype("creature") && card->hasColor(1)){etype.append("cre"); colored = 1;} - for (int j = 0; j < nbcards; ++j){ - MTGCardInstance * c = z->cards[j]; - if (c && ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art")!= string::npos) || ( c->has(Constants::AFFINITYSWAMP) && etype.find("swa")!= string::npos) || ( c->has(Constants::AFFINITYMOUNTAIN) && etype.find("mou")!= string::npos) ||( c->has(Constants::AFFINITYPLAINS) && etype.find("pla")!= string::npos) || ( c->has(Constants::AFFINITYISLAND) && etype.find("isl")!= string::npos) || ( c->has(Constants::AFFINITYFOREST) && etype.find("for")!= string::npos) || ( c->has(Constants::AFFINITYGREENCREATURES) && etype.find("cre")!= string::npos))){ - if(c->reduxamount > 0){ - c->reduxamount -= 1; - }else{ - c->getManaCost()->add(colored,1); - } - } - } - //------------------------------- - } - }//---ok == 3 - //---------------------------------------- - } - } - return 0; - } - return 0; +MTGAffinityRule::MTGAffinityRule(int _id) : + MTGAbility(_id, NULL) +{ +} +; +int MTGAffinityRule::receiveEvent(WEvent * event) +{ + if (event->type == WEvent::CHANGE_ZONE) + { + WEventZoneChange * e = (WEventZoneChange *) event; + MTGCardInstance * card = e->card->previous; + if (e && card) + { + int color = -1; + string type = ""; + int ok = 0; + for (int i = 0; i < 2; i++) + { + Player * p = game->players[i]; + if (e->to == p->game->hand) + ok = 1;//affinity card enters hand + //--------- + //when cards with affinity enter you hand from anywhere a redux is applied to them for the artifacts in play. + if (ok == 1) + {//enters play from anywhere + if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from + == p->game->exile || e->from == p->game->stack || e->from == p->opponent()->game->battlefield + || e->from == p->game->temp || e->from == p->game->battlefield) + { + MTGCardInstance * card = e->card->previous; + if (card && card->has(Constants::AFFINITYARTIFACTS)) + { + color = 0; + type = "artifact"; + } + if (card && card->has(Constants::AFFINITYSWAMP)) + { + color = 0; + type = "swamp"; + } + if (card && card->has(Constants::AFFINITYMOUNTAIN)) + { + color = 0; + type = "mountain"; + } + if (card && card->has(Constants::AFFINITYPLAINS)) + { + color = 0; + type = "plains"; + } + if (card && card->has(Constants::AFFINITYISLAND)) + { + color = 0; + type = "island"; + } + if (card && card->has(Constants::AFFINITYFOREST)) + { + color = 0; + type = "forest"; + } + if (card && card->has(Constants::AFFINITYGREENCREATURES)) + { + color = 1; + type = "creature"; + } + //--redux effect + MTGGameZone * z = card->controller()->game->battlefield; + int nbcards = z->nb_cards; + for (int j = 0; j < nbcards; ++j) + { + MTGCardInstance * c = z->cards[j]; + int check = e->card->getManaCost()->getConvertedCost(); + if ((e->card->has(Constants::AFFINITYARTIFACTS) && c->hasSubtype("artifact")) || (e->card->has( + Constants::AFFINITYSWAMP) && c->hasSubtype("swamp")) || (e->card->has( + Constants::AFFINITYMOUNTAIN) && c->hasSubtype("moutain")) || (e->card->has( + Constants::AFFINITYPLAINS) && c->hasSubtype("plains")) || (e->card->has( + Constants::AFFINITYISLAND) && c->hasSubtype("island")) || (e->card->has( + Constants::AFFINITYFOREST) && c->hasSubtype("forest")) || (e->card->has( + Constants::AFFINITYGREENCREATURES) && c->hasColor(1) && c->isCreature())) + { + if (check > 0) + { + if (color > 0 && !e->card->getManaCost()->hasColor(color)) + {//do nothing if its colored redux and the cards dont have the color + } + else + { + //do normal redux + e->card->getManaCost()->remove(color, 1); + }//one less colorless to cast + } + else + { + e->card->reduxamount += 1; + } + } + }//--end of redux bracket + } + }//if ok == 1 + //-------------maintaining cost---------------------------------------------------------------- + ok = 0; + if (e->to == p->game->battlefield) + ok = 2;//card enters play + if (ok == 2) + {//enters play from anywhere + if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from + == p->game->exile || e->from == p->game->stack || e->from == p->game->temp) + { + //--redux effect + MTGGameZone * z = card->controller()->game->hand; + int nbcards = z->nb_cards; + int colored = 0; + string etype = ""; + MTGCardInstance * card = e->card->previous; + if (card && card->hasSubtype("artifact")) + { + etype.append("art"); + } + if (card && card->hasSubtype("swamp")) + { + etype.append("swa"); + } + if (card && card->hasSubtype("mountain")) + { + etype.append("mou"); + } + if (card && card->hasSubtype("plains")) + { + etype.append("pla"); + } + if (card && card->hasSubtype("island")) + { + etype.append("isl"); + } + if (card && card->hasSubtype("forest")) + { + etype.append("for"); + } + if (card && card->hasSubtype("creature") && card->hasColor(1)) + { + etype.append("cre"); + colored = 1; + } + for (int j = 0; j < nbcards; ++j) + { + MTGCardInstance * c = z->cards[j]; + if ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art") != string::npos) || (c->has( + Constants::AFFINITYSWAMP) && etype.find("swa") != string::npos) || (c->has( + Constants::AFFINITYMOUNTAIN) && etype.find("mou") != string::npos) || (c->has( + Constants::AFFINITYPLAINS) && etype.find("pla") != string::npos) || (c->has( + Constants::AFFINITYISLAND) && etype.find("isl") != string::npos) || (c->has( + Constants::AFFINITYFOREST) && etype.find("for") != string::npos) || (c->has( + Constants::AFFINITYGREENCREATURES) && etype.find("cre") != string::npos)) + { + if (c->getManaCost()->getConvertedCost() > 0) + { + c->getManaCost()->remove(colored, 1);//one less colorless to cast + } + else + { + c->reduxamount += 1; + } + } + } + } + }//--end of redux bracket ok == 2 + //--------- + ok = 0; + if (e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library || e->to == p->game->exile + || e->to == p->game->stack || e->to == p->opponent()->game->battlefield) + ok = 3;//card leaves play + if (ok == 3) + {//leave play from your battlefield + if (e->from == p->game->battlefield) + { + int colored = 0; + MTGGameZone * z = card->controller()->game->hand; + int nbcards = z->nb_cards; + string etype = ""; + MTGCardInstance * card = e->card->previous; + if (card && card->hasSubtype("artifact")) + { + etype.append("art"); + } + if (card && card->hasSubtype("swamp")) + { + etype.append("swa"); + } + if (card && card->hasSubtype("mountain")) + { + etype.append("mou"); + } + if (card && card->hasSubtype("plains")) + { + etype.append("pla"); + } + if (card && card->hasSubtype("island")) + { + etype.append("isl"); + } + if (card && card->hasSubtype("forest")) + { + etype.append("for"); + } + if (card && card->hasSubtype("creature") && card->hasColor(1)) + { + etype.append("cre"); + colored = 1; + } + for (int j = 0; j < nbcards; ++j) + { + MTGCardInstance * c = z->cards[j]; + if (c && ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art") != string::npos) || (c->has( + Constants::AFFINITYSWAMP) && etype.find("swa") != string::npos) || (c->has( + Constants::AFFINITYMOUNTAIN) && etype.find("mou") != string::npos) || (c->has( + Constants::AFFINITYPLAINS) && etype.find("pla") != string::npos) || (c->has( + Constants::AFFINITYISLAND) && etype.find("isl") != string::npos) || (c->has( + Constants::AFFINITYFOREST) && etype.find("for") != string::npos) || (c->has( + Constants::AFFINITYGREENCREATURES) && etype.find("cre") != string::npos))) + { + if (c->reduxamount > 0) + { + c->reduxamount -= 1; + } + else + { + c->getManaCost()->add(colored, 1); + } + } + } + //------------------------------- + } + }//---ok == 3 + //---------------------------------------- + } + } + return 0; + } + return 0; } ostream& MTGAffinityRule::toString(ostream& out) const { - out << "MTGAffinityRule ::: ("; - return MTGAbility::toString(out) << ")"; + out << "MTGAffinityRule ::: ("; + return MTGAbility::toString(out) << ")"; } -int MTGAffinityRule::testDestroy(){return 0;} -MTGAffinityRule * MTGAffinityRule::clone() const{ - MTGAffinityRule * a = NEW MTGAffinityRule(*this); - a->isClone = 1; - return a; +int MTGAffinityRule::testDestroy() +{ + return 0; +} +MTGAffinityRule * MTGAffinityRule::clone() const +{ + MTGAffinityRule * a = NEW MTGAffinityRule(*this); + a->isClone = 1; + return a; } //------------------------------------------------------------------- -MTGTokensCleanup::MTGTokensCleanup(int _id):MTGAbility(_id, NULL){} - -int MTGTokensCleanup::receiveEvent(WEvent * e){ - if (WEventZoneChange* event = dynamic_cast(e)){ - if (!event->card->isToken) return 0; - if (event->to == game->players[0]->game->inPlay || event->to == game->players[1]->game->inPlay) return 0; - if (event->to == game->players[0]->game->garbage || event->to == game->players[1]->game->garbage) return 0; - MTGCardInstance * c = event->card; - c->controller()->game->putInZone(c,c->currentZone, c->controller()->game->garbage); - return 1; - } - return 0; +MTGTokensCleanup::MTGTokensCleanup(int _id) : + MTGAbility(_id, NULL) +{ } -int MTGTokensCleanup::testDestroy(){return 0;} +int MTGTokensCleanup::receiveEvent(WEvent * e) +{ + if (WEventZoneChange* event = dynamic_cast(e)) + { + if (!event->card->isToken) + return 0; + if (event->to == game->players[0]->game->inPlay || event->to == game->players[1]->game->inPlay) + return 0; + if (event->to == game->players[0]->game->garbage || event->to == game->players[1]->game->garbage) + return 0; + MTGCardInstance * c = event->card; + c->controller()->game->putInZone(c, c->currentZone, c->controller()->game->garbage); + return 1; + } + return 0; +} +int MTGTokensCleanup::testDestroy() +{ + return 0; +} -MTGTokensCleanup * MTGTokensCleanup::clone() const{ - MTGTokensCleanup * a = NEW MTGTokensCleanup(*this); - a->isClone = 1; - return a; +MTGTokensCleanup * MTGTokensCleanup::clone() const +{ + MTGTokensCleanup * a = NEW MTGTokensCleanup(*this); + a->isClone = 1; + return a; } /* Legend Rule */ -MTGLegendRule::MTGLegendRule(int _id):ListMaintainerAbility(_id){}; +MTGLegendRule::MTGLegendRule(int _id) : + ListMaintainerAbility(_id) +{ +} +; -int MTGLegendRule::canBeInList(MTGCardInstance * card){ - if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->isInPlay(card)){ - return 1; - } - return 0; +int MTGLegendRule::canBeInList(MTGCardInstance * card) +{ + if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->isInPlay(card)) + { + return 1; + } + return 0; } -int MTGLegendRule::added(MTGCardInstance * card){ - map::iterator it; - int destroy = 0; - for ( it=cards.begin() ; it != cards.end(); it++ ){ - MTGCardInstance * comparison = (*it).first; - if (comparison != card && !(comparison->getName().compare(card->getName()))){ - comparison->controller()->game->putInGraveyard(comparison); - destroy = 1; - } - } - if (destroy){ - card->owner->game->putInGraveyard(card); - } - return 1; +int MTGLegendRule::added(MTGCardInstance * card) +{ + map::iterator it; + int destroy = 0; + for (it = cards.begin(); it != cards.end(); it++) + { + MTGCardInstance * comparison = (*it).first; + if (comparison != card && !(comparison->getName().compare(card->getName()))) + { + comparison->controller()->game->putInGraveyard(comparison); + destroy = 1; + } + } + if (destroy) + { + card->owner->game->putInGraveyard(card); + } + return 1; } -int MTGLegendRule::removed(MTGCardInstance * card){return 0;} +int MTGLegendRule::removed(MTGCardInstance * card) +{ + return 0; +} -int MTGLegendRule::testDestroy(){return 0;} +int MTGLegendRule::testDestroy() +{ + return 0; +} ostream& MTGLegendRule::toString(ostream& out) const { - return out << "MTGLegendRule :::"; + return out << "MTGLegendRule :::"; } -MTGLegendRule * MTGLegendRule::clone() const{ - MTGLegendRule * a = NEW MTGLegendRule(*this); - a->isClone = 1; - return a; +MTGLegendRule * MTGLegendRule::clone() const +{ + MTGLegendRule * a = NEW MTGLegendRule(*this); + a->isClone = 1; + return a; } /* Lifelink */ -MTGLifelinkRule::MTGLifelinkRule(int _id):MTGAbility(_id,NULL){}; - -int MTGLifelinkRule::receiveEvent(WEvent * event){ - if (event->type == WEvent::DAMAGE){ - WEventDamage * e = (WEventDamage *) event; - Damage * d = e->damage; - MTGCardInstance * card = d->source; - if (d->damage>0 && card && card->basicAbilities[Constants::LIFELINK]){ - card->controller()->life+= d->damage; - return 1; - } - } - return 0; -} - -int MTGLifelinkRule::testDestroy(){return 0;} - -ostream& MTGLifelinkRule::toString(ostream& out) const +MTGLifelinkRule::MTGLifelinkRule(int _id) : + MTGAbility(_id, NULL) { - out << "MTGLifelinkRule ::: ("; - return MTGAbility::toString(out) << ")"; } -MTGLifelinkRule * MTGLifelinkRule::clone() const{ - MTGLifelinkRule * a = NEW MTGLifelinkRule(*this); - a->isClone = 1; - return a; +; + +int MTGLifelinkRule::receiveEvent(WEvent * event) +{ + if (event->type == WEvent::DAMAGE) + { + WEventDamage * e = (WEventDamage *) event; + Damage * d = e->damage; + MTGCardInstance * card = d->source; + if (d->damage > 0 && card && card->basicAbilities[Constants::LIFELINK]) + { + card->controller()->life += d->damage; + return 1; + } + } + return 0; } +int MTGLifelinkRule::testDestroy() +{ + return 0; +} + +ostream& MTGLifelinkRule::toString(ostream& out) const +{ + out << "MTGLifelinkRule ::: ("; + return MTGAbility::toString(out) << ")"; +} +MTGLifelinkRule * MTGLifelinkRule::clone() const +{ + MTGLifelinkRule * a = NEW MTGLifelinkRule(*this); + a->isClone = 1; + return a; +} /* Deathtouch */ -MTGDeathtouchRule::MTGDeathtouchRule(int _id):MTGAbility(_id,NULL){}; +MTGDeathtouchRule::MTGDeathtouchRule(int _id) : + MTGAbility(_id, NULL) +{ +} +; -int MTGDeathtouchRule::receiveEvent(WEvent * event){ - if (event->type == WEvent::DAMAGE){ - WEventDamage * e = (WEventDamage *) event; +int MTGDeathtouchRule::receiveEvent(WEvent * event) +{ + if (event->type == WEvent::DAMAGE) + { + WEventDamage * e = (WEventDamage *) event; - Damage * d = e->damage; - if (d->damage <= 0) return 0; + Damage * d = e->damage; + if (d->damage <= 0) + return 0; - MTGCardInstance * card = d->source; - if (!card) return 0; + MTGCardInstance * card = d->source; + if (!card) + return 0; - if (d->target->type_as_damageable != DAMAGEABLE_MTGCARDINSTANCE) return 0; - MTGCardInstance * _target = (MTGCardInstance *) (d->target); + if (d->target->type_as_damageable != DAMAGEABLE_MTGCARDINSTANCE) + return 0; + MTGCardInstance * _target = (MTGCardInstance *) (d->target); - if (card->basicAbilities[Constants::DEATHTOUCH]){ - _target->destroy(); - return 1; - } - } - return 0; + if (card->basicAbilities[Constants::DEATHTOUCH]) + { + _target->destroy(); + return 1; + } + } + return 0; } -int MTGDeathtouchRule::testDestroy(){return 0;} - - -MTGDeathtouchRule * MTGDeathtouchRule::clone() const{ - MTGDeathtouchRule * a = NEW MTGDeathtouchRule(*this); - a->isClone = 1; - return a; +int MTGDeathtouchRule::testDestroy() +{ + return 0; +} + +MTGDeathtouchRule * MTGDeathtouchRule::clone() const +{ + MTGDeathtouchRule * a = NEW MTGDeathtouchRule(*this); + a->isClone = 1; + return a; } diff --git a/projects/mtg/src/MTGSpellStack.cpp b/projects/mtg/src/MTGSpellStack.cpp index c4f10a92a..0b8fac351 100644 --- a/projects/mtg/src/MTGSpellStack.cpp +++ b/projects/mtg/src/MTGSpellStack.cpp @@ -1,19 +1,22 @@ #include "MTGSpellStack.h" -MTGSpellStack::MTGSpellStack(){ - cursor = -1; +MTGSpellStack::MTGSpellStack() +{ + cursor = -1; } -void MTGSpellStack::addSpell(Ability * ability){ - cursor++; - spellStack[cursor] ability; +void MTGSpellStack::addSpell(Ability * ability) +{ + cursor++; + spellStack[cursor] ability; } -int MTGSpellStack::resolve(){ - if (cursor < 0) - return 0; - int result = cursor; - cursor--; - (spellStack[cursor + 1])->resolve(); - return (result+1); +int MTGSpellStack::resolve() +{ + if (cursor < 0) + return 0; + int result = cursor; + cursor--; + (spellStack[cursor + 1])->resolve(); + return (result + 1); } diff --git a/projects/mtg/src/MTGardInstance.cpp b/projects/mtg/src/MTGardInstance.cpp index e4bc93f6b..7535d6b81 100644 --- a/projects/mtg/src/MTGardInstance.cpp +++ b/projects/mtg/src/MTGardInstance.cpp @@ -3,15 +3,18 @@ //--------------------------------------------- //Card Instance //-------------------------------------------- -MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * _belongs_to): model(card){ - belongs_to = _belongs_to; +MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * _belongs_to) : + model(card) +{ + belongs_to = _belongs_to; } -int MTGCardInstance::isInPlay(){ - return belongs_to->isInPlay(this); +int MTGCardInstance::isInPlay() +{ + return belongs_to->isInPlay(this); } - -JQuad * MTGCardInstance::getQuad(TexturesCache * cache){ - return model->getQuad(cache); +JQuad * MTGCardInstance::getQuad(TexturesCache * cache) +{ + return model->getQuad(cache); } diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index ee05598c1..c398fb6fe 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -9,567 +9,716 @@ #include "WEvent.h" #include "MTGAbility.h" - -ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstance * c){ - ManaCost * manaCost; - if (_manaCost){ - manaCost = _manaCost; - }else{ - manaCost = NEW ManaCost(); - } - int state = 0; - size_t start = 0; - size_t end = 0; - while (!s.empty() && state != -1){ - switch(state){ - case 0: - start = s.find_first_of("{"); - if (start == string::npos){ - return manaCost; - }else{ - state = 1; - } - break; - case 1: - end = s.find_first_of("}"); - if (end == string::npos){ - state = -1; - }else{ - string value = s.substr(start+1, end - 1 - start); - - if (value == "u") { - manaCost->add(Constants::MTG_COLOR_BLUE, 1); - } else if (value == "b") { - manaCost->add(Constants::MTG_COLOR_BLACK, 1); - } else if (value == "w") { - manaCost->add(Constants::MTG_COLOR_WHITE, 1); - } else if (value == "g") { - manaCost->add(Constants::MTG_COLOR_GREEN, 1); - } else if (value == "r") { - manaCost->add(Constants::MTG_COLOR_RED, 1); - - } else { - - //Parse target for extraCosts - TargetChooserFactory tcf; - TargetChooser * tc = NULL; - size_t target_start = value.find("("); - size_t target_end = value.find(")"); - if (target_start!=string::npos && target_end!=string::npos){ - string target = value.substr(target_start+1, target_end-1 - target_start); - tc = tcf.createTargetChooser(target,c); - } - - //switch on the first letter. If two costs share their first letter, add an "if" within the switch - switch(value[0]) { - case 'x': - manaCost->x(); - break; - case 't': //Tap - if (value == "t"){ - //default Tap is handled outside of Manacost - } else { - manaCost->addExtraCost(NEW TapTargetCost(tc)); - } - break; - case 's': - if (value == "s2l") { //Send To Library Cost (move from anywhere to Library) - manaCost->addExtraCost(NEW ToLibraryCost(tc)); - } else { //Sacrifice - manaCost->addExtraCost(NEW SacrificeCost(tc)); - } - break; - case 'e': //Exile - manaCost->addExtraCost(NEW ExileTargetCost(tc)); - break; - case 'h': //bounce (move to Hand) - manaCost->addExtraCost(NEW BounceTargetCost(tc)); - break; - case 'l': - if (value == "l2e") { //Mill to exile yourself as a cost (Library 2 Exile) - manaCost->addExtraCost(NEW MillExileCost(tc)); - } else { //Life cost - manaCost->addExtraCost(NEW LifeCost(tc)); - } - break; - case 'd': //DiscardRandom cost - if (value == "d"){ - manaCost->addExtraCost(NEW DiscardRandomCost(tc)); - }else{ - manaCost->addExtraCost(NEW DiscardCost(tc)); - } - break; - case 'm': //Mill yourself as a cost - manaCost->addExtraCost(NEW MillCost(tc)); - break; - case 'n': //return unblocked attacker cost - TargetChooserFactory tcf; - tc = tcf.createTargetChooser("creature|myBattlefield", c); - manaCost->addExtraCost(NEW Ninja(tc)); - break; - case 'c': //Counters - { - size_t counter_start = value.find("("); - size_t counter_end = value.find(")", counter_start); - AbilityFactory abf; - string counterString = value.substr(counter_start+1,counter_end-counter_start-1); - Counter * counter = abf.parseCounter(counterString,c); - size_t separator = value.find(",",counter_start); - size_t separator2 = string::npos; - if (separator != string::npos) { - separator2 = value.find(",",separator + 1); - } - SAFE_DELETE(tc); - size_t target_start = string::npos; - if (separator2 != string::npos) { - target_start = value.find(",",separator2+1); - } - size_t target_end = counter_end; - if (target_start!=string::npos && target_end!=string::npos){ - string target = value.substr(target_start+1, target_end-1 - target_start); - tc = tcf.createTargetChooser(target,c); - } - manaCost->addExtraCost(NEW CounterCost(counter,tc)); - break; - } - default: //uncolored cost and hybrid costs - { - int intvalue = atoi(value.c_str()); - int colors[2]; - int values[2]; - if (intvalue < 10 && value.size() > 1){ - for (int i = 0; i < 2; i++){ - char c = value[i]; - if (c >='0' && c <='9'){ - colors[i] = Constants::MTG_COLOR_ARTIFACT; - values[i] = c - '0'; - }else{ - for (int j = 0; j < Constants::MTG_NB_COLORS; j++){ - if (c == Constants::MTGColorChars[j]){ - colors[i] = j; - values[i] = 1; - } - } - } - } - manaCost->addHybrid(colors[0], values[0], colors[1], values[1]); - }else{ - manaCost->add(Constants::MTG_COLOR_ARTIFACT, intvalue); - } - break; - } - } - } - s = s.substr(end + 1); - state = 0; - } - break; - default: - break; +ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstance * c) +{ + ManaCost * manaCost; + if (_manaCost) + { + manaCost = _manaCost; } - } - return manaCost; + else + { + manaCost = NEW ManaCost(); + } + int state = 0; + size_t start = 0; + size_t end = 0; + while (!s.empty() && state != -1) + { + switch (state) + { + case 0: + start = s.find_first_of("{"); + if (start == string::npos) + { + return manaCost; + } + else + { + state = 1; + } + break; + case 1: + end = s.find_first_of("}"); + if (end == string::npos) + { + state = -1; + } + else + { + string value = s.substr(start + 1, end - 1 - start); + + if (value == "u") + { + manaCost->add(Constants::MTG_COLOR_BLUE, 1); + } + else if (value == "b") + { + manaCost->add(Constants::MTG_COLOR_BLACK, 1); + } + else if (value == "w") + { + manaCost->add(Constants::MTG_COLOR_WHITE, 1); + } + else if (value == "g") + { + manaCost->add(Constants::MTG_COLOR_GREEN, 1); + } + else if (value == "r") + { + manaCost->add(Constants::MTG_COLOR_RED, 1); + + } + else + { + + //Parse target for extraCosts + TargetChooserFactory tcf; + TargetChooser * tc = NULL; + size_t target_start = value.find("("); + size_t target_end = value.find(")"); + if (target_start != string::npos && target_end != string::npos) + { + string target = value.substr(target_start + 1, target_end - 1 - target_start); + tc = tcf.createTargetChooser(target, c); + } + + //switch on the first letter. If two costs share their first letter, add an "if" within the switch + switch (value[0]) + { + case 'x': + manaCost->x(); + break; + case 't': //Tap + if (value == "t") + { + //default Tap is handled outside of Manacost + } + else + { + manaCost->addExtraCost(NEW TapTargetCost(tc)); + } + break; + case 's': + if (value == "s2l") + { //Send To Library Cost (move from anywhere to Library) + manaCost->addExtraCost(NEW ToLibraryCost(tc)); + } + else + { //Sacrifice + manaCost->addExtraCost(NEW SacrificeCost(tc)); + } + break; + case 'e': //Exile + manaCost->addExtraCost(NEW ExileTargetCost(tc)); + break; + case 'h': //bounce (move to Hand) + manaCost->addExtraCost(NEW BounceTargetCost(tc)); + break; + case 'l': + if (value == "l2e") + { //Mill to exile yourself as a cost (Library 2 Exile) + manaCost->addExtraCost(NEW MillExileCost(tc)); + } + else + { //Life cost + manaCost->addExtraCost(NEW LifeCost(tc)); + } + break; + case 'd': //DiscardRandom cost + if (value == "d") + { + manaCost->addExtraCost(NEW DiscardRandomCost(tc)); + } + else + { + manaCost->addExtraCost(NEW DiscardCost(tc)); + } + break; + case 'm': //Mill yourself as a cost + manaCost->addExtraCost(NEW MillCost(tc)); + break; + case 'n': //return unblocked attacker cost + TargetChooserFactory tcf; + tc = tcf.createTargetChooser("creature|myBattlefield", c); + manaCost->addExtraCost(NEW Ninja(tc)); + break; + case 'c': //Counters + { + size_t counter_start = value.find("("); + size_t counter_end = value.find(")", counter_start); + AbilityFactory abf; + string counterString = value.substr(counter_start + 1, counter_end - counter_start - 1); + Counter * counter = abf.parseCounter(counterString, c); + size_t separator = value.find(",", counter_start); + size_t separator2 = string::npos; + if (separator != string::npos) + { + separator2 = value.find(",", separator + 1); + } + SAFE_DELETE(tc); + size_t target_start = string::npos; + if (separator2 != string::npos) + { + target_start = value.find(",", separator2 + 1); + } + size_t target_end = counter_end; + if (target_start != string::npos && target_end != string::npos) + { + string target = value.substr(target_start + 1, target_end - 1 - target_start); + tc = tcf.createTargetChooser(target, c); + } + manaCost->addExtraCost(NEW CounterCost(counter, tc)); + break; + } + default: //uncolored cost and hybrid costs + { + int intvalue = atoi(value.c_str()); + int colors[2]; + int values[2]; + if (intvalue < 10 && value.size() > 1) + { + for (int i = 0; i < 2; i++) + { + char c = value[i]; + if (c >= '0' && c <= '9') + { + colors[i] = Constants::MTG_COLOR_ARTIFACT; + values[i] = c - '0'; + } + else + { + for (int j = 0; j < Constants::MTG_NB_COLORS; j++) + { + if (c == Constants::MTGColorChars[j]) + { + colors[i] = j; + values[i] = 1; + } + } + } + } + manaCost->addHybrid(colors[0], values[0], colors[1], values[1]); + } + else + { + manaCost->add(Constants::MTG_COLOR_ARTIFACT, intvalue); + } + break; + } + } + } + s = s.substr(end + 1); + state = 0; + } + break; + default: + break; + } + } + return manaCost; } -ManaCost::ManaCost(){ - init(); +ManaCost::ManaCost() +{ + init(); } -ManaCost::ManaCost(int _cost[], int nb_elems){ - init(); - int i; - int total = nb_elems; - for (i = 0; i < total; i++){ - cost[_cost[i*2]] = _cost[i*2 + 1]; - } +ManaCost::ManaCost(int _cost[], int nb_elems) +{ + init(); + int i; + int total = nb_elems; + for (i = 0; i < total; i++) + { + cost[_cost[i * 2]] = _cost[i * 2 + 1]; + } } -ManaCost::ManaCost(ManaCost * _manaCost){ - init(); - int i; - for (i=0; i<= Constants::MTG_NB_COLORS; i++){ - cost[i] = _manaCost->getCost(i); - } +ManaCost::ManaCost(ManaCost * _manaCost) +{ + init(); + int i; + for (i = 0; i <= Constants::MTG_NB_COLORS; i++) + { + cost[i] = _manaCost->getCost(i); + } } -ManaCost::~ManaCost(){ - for (unsigned int i = 0; i < nbhybrids ; i++){ - SAFE_DELETE(hybrids[i]); - } - - SAFE_DELETE(extraCosts); - - SAFE_DELETE(kicker); - - SAFE_DELETE(alternative); +ManaCost::~ManaCost() +{ + for (unsigned int i = 0; i < nbhybrids; i++) + { + SAFE_DELETE(hybrids[i]); + } + SAFE_DELETE(extraCosts); + SAFE_DELETE(kicker); + SAFE_DELETE(alternative); SAFE_DELETE(BuyBack); - - SAFE_DELETE(FlashBack); - - SAFE_DELETE(Retrace); -} - -void ManaCost::x(){ - cost[Constants::MTG_NB_COLORS] = 1; -} - -int ManaCost::hasX(){ - return cost[Constants::MTG_NB_COLORS]; -} - -void ManaCost::init(){ - int i; - for (i=0; i<= Constants::MTG_NB_COLORS; i++){ - cost[i] = 0; - } - nbhybrids = 0; - extraCosts = NULL; - extraCostsIsCopy = 0; - kicker = NULL; - alternative = NULL; - BuyBack = NULL; - FlashBack = NULL; - Retrace = NULL; -} - - -void ManaCost::copy(ManaCost * _manaCost){ - if (!_manaCost) return; - for (unsigned int i = 0; i <= Constants::MTG_NB_COLORS; i++){ - cost[i] = _manaCost->getCost(i); - } - for (unsigned int i = 0; i < nbhybrids ; i++){ - SAFE_DELETE(hybrids[i]); - } - for (unsigned int i = 0; i < _manaCost->nbhybrids; i++){ - hybrids[i] = NEW ManaCostHybrid((*_manaCost->hybrids[i])); - } - nbhybrids = _manaCost->nbhybrids; - - SAFE_DELETE(extraCosts); - if (_manaCost->extraCosts){ - extraCosts = _manaCost->extraCosts->clone(); - } - - SAFE_DELETE(kicker); - if (_manaCost->kicker){ - kicker = NEW ManaCost(); - kicker->copy(_manaCost->kicker); - } - SAFE_DELETE(alternative); - if (_manaCost->alternative){ - alternative = NEW ManaCost(); - alternative->copy(_manaCost->alternative); - } - SAFE_DELETE(BuyBack); - if (_manaCost->BuyBack){ - BuyBack = NEW ManaCost(); - BuyBack->copy(_manaCost->BuyBack); - } SAFE_DELETE(FlashBack); - if (_manaCost->FlashBack){ - FlashBack = NEW ManaCost(); - FlashBack->copy(_manaCost->FlashBack); - } SAFE_DELETE(Retrace); - if (_manaCost->Retrace){ - Retrace = NEW ManaCost(); - Retrace->copy(_manaCost->Retrace); - } } -int ManaCost::getCost(int color){ - return cost[color]; +void ManaCost::x() +{ + cost[Constants::MTG_NB_COLORS] = 1; } -ManaCostHybrid * ManaCost::getHybridCost(unsigned int i){ - if (nbhybrids <= i) return NULL; - return hybrids[i]; +int ManaCost::hasX() +{ + return cost[Constants::MTG_NB_COLORS]; } -int ManaCost::hasColor(int color){ - if (cost[color]) return 1; - for (unsigned int i = 0; i < nbhybrids; i++){ - if (hybrids[i]->hasColor(color)) return 1; - } - return 0; +void ManaCost::init() +{ + int i; + for (i = 0; i <= Constants::MTG_NB_COLORS; i++) + { + cost[i] = 0; + } + nbhybrids = 0; + extraCosts = NULL; + extraCostsIsCopy = 0; + kicker = NULL; + alternative = NULL; + BuyBack = NULL; + FlashBack = NULL; + Retrace = NULL; } -int ManaCost::isNull(){ - if (getConvertedCost()) return 0; - if (extraCosts) return 0; - return 1; +void ManaCost::copy(ManaCost * _manaCost) +{ + if (!_manaCost) + return; + for (unsigned int i = 0; i <= Constants::MTG_NB_COLORS; i++) + { + cost[i] = _manaCost->getCost(i); + } + for (unsigned int i = 0; i < nbhybrids; i++) + { + SAFE_DELETE(hybrids[i]); + } + for (unsigned int i = 0; i < _manaCost->nbhybrids; i++) + { + hybrids[i] = NEW ManaCostHybrid((*_manaCost->hybrids[i])); + } + nbhybrids = _manaCost->nbhybrids; + + SAFE_DELETE(extraCosts); + if (_manaCost->extraCosts) + { + extraCosts = _manaCost->extraCosts->clone(); + } + + SAFE_DELETE(kicker); + if (_manaCost->kicker) + { + kicker = NEW ManaCost(); + kicker->copy(_manaCost->kicker); + } + SAFE_DELETE(alternative); + if (_manaCost->alternative) + { + alternative = NEW ManaCost(); + alternative->copy(_manaCost->alternative); + } + SAFE_DELETE(BuyBack); + if (_manaCost->BuyBack) + { + BuyBack = NEW ManaCost(); + BuyBack->copy(_manaCost->BuyBack); + } + SAFE_DELETE(FlashBack); + if (_manaCost->FlashBack) + { + FlashBack = NEW ManaCost(); + FlashBack->copy(_manaCost->FlashBack); + } + SAFE_DELETE(Retrace); + if (_manaCost->Retrace) + { + Retrace = NEW ManaCost(); + Retrace->copy(_manaCost->Retrace); + } } -int ManaCost::getConvertedCost(){ - int result = 0; - for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++){ - result += cost[i]; - } - for (unsigned int i = 0; i < nbhybrids; i++){ - result+= hybrids[i]->getConvertedCost(); - } - return result; +int ManaCost::getCost(int color) +{ + return cost[color]; } -int ManaCost::remove(int color, int value){ - cost[color] -= value; - if(cost[color] < 0){cost[color] = 0;} - return 1; +ManaCostHybrid * ManaCost::getHybridCost(unsigned int i) +{ + if (nbhybrids <= i) + return NULL; + return hybrids[i]; } -int ManaCost::add(int color, int value){ - if(value < 0) value = 0; - cost[color] += value; - return 1; +int ManaCost::hasColor(int color) +{ + if (cost[color]) + return 1; + for (unsigned int i = 0; i < nbhybrids; i++) + { + if (hybrids[i]->hasColor(color)) + return 1; + } + return 0; } -int ManaCost::add(ManaCost * _cost){ - if(!_cost) return 0; - for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++){ - cost[i]+= _cost->getCost(i); - } - for (unsigned int i = 0; i < _cost->nbhybrids; i++){ - hybrids[nbhybrids] = NEW ManaCostHybrid((*_cost->hybrids[i])); +int ManaCost::isNull() +{ + if (getConvertedCost()) + return 0; + if (extraCosts) + return 0; + return 1; +} + +int ManaCost::getConvertedCost() +{ + int result = 0; + for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + result += cost[i]; + } + for (unsigned int i = 0; i < nbhybrids; i++) + { + result += hybrids[i]->getConvertedCost(); + } + return result; +} + +int ManaCost::remove(int color, int value) +{ + cost[color] -= value; + if (cost[color] < 0) + { + cost[color] = 0; + } + return 1; +} + +int ManaCost::add(int color, int value) +{ + if (value < 0) + value = 0; + cost[color] += value; + return 1; +} + +int ManaCost::add(ManaCost * _cost) +{ + if (!_cost) + return 0; + for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + cost[i] += _cost->getCost(i); + } + for (unsigned int i = 0; i < _cost->nbhybrids; i++) + { + hybrids[nbhybrids] = NEW ManaCostHybrid((*_cost->hybrids[i])); + nbhybrids++; + } + return 1; +} + +string ManaCost::toString() +{ + return "ManaCost - Todo"; +} + +int ManaCost::addHybrid(int c1, int v1, int c2, int v2) +{ + ManaCostHybrid * h = NEW ManaCostHybrid(c1, v1, c2, v2); + hybrids[nbhybrids] = h; nbhybrids++; - } - return 1; + return nbhybrids; } -string ManaCost::toString(){ - return "ManaCost - Todo"; +int ManaCost::addExtraCost(ExtraCost * _cost) +{ + if (!extraCosts) + extraCosts = NEW ExtraCosts(); + extraCosts->costs.push_back(_cost); + return 1; } - -int ManaCost::addHybrid(int c1, int v1, int c2, int v2){ - ManaCostHybrid * h = NEW ManaCostHybrid(c1,v1,c2,v2); - hybrids[nbhybrids] = h; - nbhybrids++; - return nbhybrids; +int ManaCost::isExtraPaymentSet() +{ + if (!extraCosts) + return 1; + return extraCosts->isPaymentSet(); } -int ManaCost::addExtraCost(ExtraCost * _cost){ - if (!extraCosts) extraCosts = NEW ExtraCosts(); - extraCosts->costs.push_back(_cost); - return 1; +int ManaCost::canPayExtra() +{ + if (!extraCosts) + return 1; + return extraCosts->canPay(); } - -int ManaCost::isExtraPaymentSet(){ - if (!extraCosts) return 1; - return extraCosts->isPaymentSet(); +int ManaCost::doPayExtra() +{ + if (!extraCosts) + return 0; + return extraCosts->doPay(); //TODO reset ? } -int ManaCost::canPayExtra(){ - if (!extraCosts) return 1; - return extraCosts->canPay(); +int ManaCost::setExtraCostsAction(MTGAbility * action, MTGCardInstance * card) +{ + if (extraCosts) + extraCosts->setAction(action, card); + return 1; } -int ManaCost::doPayExtra(){ - if (!extraCosts) return 0; - return extraCosts->doPay(); //TODO reset ? -} +int ManaCost::pay(ManaCost * _cost) +{ + int result = MANA_PAID; + ManaCost * toPay = NEW ManaCost(); + toPay->copy(_cost); -int ManaCost::setExtraCostsAction(MTGAbility * action, MTGCardInstance * card){ - if (extraCosts) extraCosts->setAction(action, card); - return 1; -} + if (toPay->kicker) + { + toPay->add(toPay->kicker); + if (!canAfford(toPay)) + { + toPay->copy(_cost); + } + else + { + result = MANA_PAID_WITH_KICKER; + } + } -int ManaCost::pay(ManaCost * _cost){ - int result = MANA_PAID; - ManaCost * toPay = NEW ManaCost(); - toPay->copy(_cost); - - if (toPay->kicker){ - toPay->add(toPay->kicker); - if (!canAfford(toPay)){ - toPay->copy(_cost); - }else{ - result = MANA_PAID_WITH_KICKER; - } - } - - ManaCost * diff = Diff(toPay); - for (int i=0; i < Constants::MTG_NB_COLORS; i++){ - cost[i] = diff->getCost(i); - } - delete diff; - delete toPay; - return result; - //TODO return 0 if can't afford the cost! + ManaCost * diff = Diff(toPay); + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + cost[i] = diff->getCost(i); + } + delete diff; + delete toPay; + return result; + //TODO return 0 if can't afford the cost! } //return 1 if _cost can be paid with current data, 0 otherwise -int ManaCost::canAfford(ManaCost * _cost){ - ManaCost * diff = Diff(_cost); - int positive = diff->isPositive(); - delete diff; - if (positive){ - return 1; - } - return 0; -} - -int ManaCost::isPositive(){ - for (int i=0; i < Constants::MTG_NB_COLORS; i++){ - - if (cost[i] < 0){ - return 0; +int ManaCost::canAfford(ManaCost * _cost) +{ + ManaCost * diff = Diff(_cost); + int positive = diff->isPositive(); + delete diff; + if (positive) + { + return 1; } - } - return 1; + return 0; +} + +int ManaCost::isPositive() +{ + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + + if (cost[i] < 0) + { + return 0; + } + } + return 1; } - -void ManaCost::randomDiffHybrids(ManaCost * _cost, int diff[]){ - int _nbhybrids = _cost->nbhybrids; - for (int i = 0; i < _nbhybrids; i++){ - ManaCostHybrid * h = _cost->hybrids[i]; - diff[h->color1 * 2 +1]-= h->value1; - } +void ManaCost::randomDiffHybrids(ManaCost * _cost, int diff[]) +{ + int _nbhybrids = _cost->nbhybrids; + for (int i = 0; i < _nbhybrids; i++) + { + ManaCostHybrid * h = _cost->hybrids[i]; + diff[h->color1 * 2 + 1] -= h->value1; + } } -int ManaCost::tryToPayHybrids(ManaCostHybrid * _hybrids[], int _nbhybrids, int diff[]){ - if (!_nbhybrids) return 1; - int result = 0; - ManaCostHybrid * h = _hybrids[_nbhybrids -1]; - if (diff[h->color1 * 2 +1] >= h->value1){ - diff[h->color1 * 2 +1]-= h->value1; - result = tryToPayHybrids(_hybrids,_nbhybrids -1, diff); - if (result) return 1; - diff[h->color1 * 2 +1]+= h->value1; - } - if (diff[h->color2 * 2 +1] >= h->value2){ - diff[h->color2 * 2 +1]-= h->value2; - result = tryToPayHybrids(_hybrids,_nbhybrids -1, diff); - if (result) return 1; - diff[h->color2 * 2 +1]+= h->value2; - } - return 0; +int ManaCost::tryToPayHybrids(ManaCostHybrid * _hybrids[], int _nbhybrids, int diff[]) +{ + if (!_nbhybrids) + return 1; + int result = 0; + ManaCostHybrid * h = _hybrids[_nbhybrids - 1]; + if (diff[h->color1 * 2 + 1] >= h->value1) + { + diff[h->color1 * 2 + 1] -= h->value1; + result = tryToPayHybrids(_hybrids, _nbhybrids - 1, diff); + if (result) + return 1; + diff[h->color1 * 2 + 1] += h->value1; + } + if (diff[h->color2 * 2 + 1] >= h->value2) + { + diff[h->color2 * 2 + 1] -= h->value2; + result = tryToPayHybrids(_hybrids, _nbhybrids - 1, diff); + if (result) + return 1; + diff[h->color2 * 2 + 1] += h->value2; + } + return 0; } //compute the difference between two mana costs -ManaCost * ManaCost::Diff(ManaCost * _cost){ - int diff[(Constants::MTG_NB_COLORS + 1 )* 2]; - diff[Constants::MTG_NB_COLORS * 2] = Constants::MTG_NB_COLORS; - for (int i=0; i < Constants::MTG_NB_COLORS; i++){ - diff[i*2] = i; - diff[i*2 +1] = cost[i] - _cost->getCost(i); - } - int hybridResult = tryToPayHybrids(_cost->hybrids, _cost->nbhybrids, diff); - if (!hybridResult) randomDiffHybrids(_cost,diff); - - //Colorless mana, special case - int colorless_idx = Constants::MTG_COLOR_ARTIFACT * 2 + 1; - if (diff[colorless_idx] < 0){ - for (int i=0; i < Constants::MTG_NB_COLORS; i++){ - if (diff[i*2 + 1] > 0){ - if (diff[i*2 + 1] + diff[colorless_idx] > 0){ - diff[i*2 + 1] += diff[colorless_idx]; - diff[colorless_idx] = 0; - break; - }else{ - diff[colorless_idx] += diff[i*2 + 1]; - diff[i*2 + 1] = 0; - } - } +ManaCost * ManaCost::Diff(ManaCost * _cost) +{ + int diff[(Constants::MTG_NB_COLORS + 1) * 2]; + diff[Constants::MTG_NB_COLORS * 2] = Constants::MTG_NB_COLORS; + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + diff[i * 2] = i; + diff[i * 2 + 1] = cost[i] - _cost->getCost(i); } - } + int hybridResult = tryToPayHybrids(_cost->hybrids, _cost->nbhybrids, diff); + if (!hybridResult) + randomDiffHybrids(_cost, diff); - //Cost X - if (_cost->hasX()){ - diff[Constants::MTG_NB_COLORS * 2 + 1] = 0; - for (int i=0; i < Constants::MTG_NB_COLORS; i++){ - if (diff[i*2 + 1] > 0){ - diff[Constants::MTG_NB_COLORS * 2 + 1] += diff[i*2 + 1]; - diff[i*2 + 1] = 0; - } + //Colorless mana, special case + int colorless_idx = Constants::MTG_COLOR_ARTIFACT * 2 + 1; + if (diff[colorless_idx] < 0) + { + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + if (diff[i * 2 + 1] > 0) + { + if (diff[i * 2 + 1] + diff[colorless_idx] > 0) + { + diff[i * 2 + 1] += diff[colorless_idx]; + diff[colorless_idx] = 0; + break; + } + else + { + diff[colorless_idx] += diff[i * 2 + 1]; + diff[i * 2 + 1] = 0; + } + } + } } - } - ManaCost * result = NEW ManaCost(diff, Constants::MTG_NB_COLORS +1); - return result; + //Cost X + if (_cost->hasX()) + { + diff[Constants::MTG_NB_COLORS * 2 + 1] = 0; + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + if (diff[i * 2 + 1] > 0) + { + diff[Constants::MTG_NB_COLORS * 2 + 1] += diff[i * 2 + 1]; + diff[i * 2 + 1] = 0; + } + } + } + + ManaCost * result = NEW ManaCost(diff, Constants::MTG_NB_COLORS + 1); + return result; } #ifdef WIN32 -void ManaCost::Dump(){ - DebugTrace("\n===ManaCost===\n"); - for (int i=0; i<= Constants::MTG_NB_COLORS; i++){ - if (cost[i]) { - DebugTrace(Constants::MTGColorChars[i] << ":" << cost[i] << " - "); +void ManaCost::Dump() +{ + DebugTrace("\n===ManaCost===\n"); + for (int i=0; i<= Constants::MTG_NB_COLORS; i++) + { + if (cost[i]) + { + DebugTrace(Constants::MTGColorChars[i] << ":" << cost[i] << " - "); + } } - } - for (unsigned int i=0; i< nbhybrids; i++){ - ManaCostHybrid * h = hybrids[i]; - DebugTrace("H:{" << Constants::MTGColorChars[h->color1] << ":" << h->value1 << "}/{" << Constants::MTGColorChars[h->color2] << ":" << h->value2 << "}"); - } - DebugTrace("\n=============\n"); + for (unsigned int i=0; i< nbhybrids; i++) + { + ManaCostHybrid * h = hybrids[i]; + DebugTrace("H:{" << Constants::MTGColorChars[h->color1] << ":" << h->value1 << "}/{" << Constants::MTGColorChars[h->color2] << ":" << h->value2 << "}"); + } + DebugTrace("\n=============\n"); } #endif ostream& operator<<(ostream& out, const ManaCost& m) { - return out << "(manacost)"; + return out << "(manacost)"; } - -void ManaPool::init(){ - ManaCost::init(); - WEvent * e = NEW WEventEmptyManaPool(this); - GameObserver::GetInstance()->receiveEvent(e); +void ManaPool::init() +{ + ManaCost::init(); + WEvent * e = NEW WEventEmptyManaPool(this); + GameObserver::GetInstance()->receiveEvent(e); } -ManaPool::ManaPool(Player * player):ManaCost(),player(player){} -ManaPool::ManaPool(ManaCost * _manaCost,Player * player):ManaCost(_manaCost),player(player){} - -int ManaPool::remove (int color, int value){ - int result = ManaCost::remove(color, value); - for (int i = 0; i < value; ++i){ - WEvent * e = NEW WEventConsumeMana(color, this); - GameObserver::GetInstance()->receiveEvent(e); - } - return result; +ManaPool::ManaPool(Player * player) : + ManaCost(), player(player) +{ +} +ManaPool::ManaPool(ManaCost * _manaCost, Player * player) : + ManaCost(_manaCost), player(player) +{ } -int ManaPool::add(int color, int value, MTGCardInstance * source ){ - int result = ManaCost::add(color, value); - for (int i = 0; i < value; ++i){ - WEvent * e = NEW WEventEngageMana(color, source,this); - GameObserver::GetInstance()->receiveEvent(e); - } - return result; -} - -int ManaPool::add(ManaCost * _cost, MTGCardInstance * source){ - if(!_cost) return 0; - int result = ManaCost::add(_cost); - for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++){ - for (int j = 0; j < _cost->getCost(i); j++){ - WEvent * e = NEW WEventEngageMana(i, source, this); - GameObserver::GetInstance()->receiveEvent(e); +int ManaPool::remove(int color, int value) +{ + int result = ManaCost::remove(color, value); + for (int i = 0; i < value; ++i) + { + WEvent * e = NEW WEventConsumeMana(color, this); + GameObserver::GetInstance()->receiveEvent(e); } - } - return result; + return result; } -int ManaPool::pay (ManaCost * _cost){ - int current[Constants::MTG_NB_COLORS]; - for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++){ - current[i] = cost[i]; - } - - int result = ManaCost::pay(_cost); - for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++){ - int value = current[i] - cost[i]; - for (int j = 0; j receiveEvent(e); +int ManaPool::add(int color, int value, MTGCardInstance * source) +{ + int result = ManaCost::add(color, value); + for (int i = 0; i < value; ++i) + { + WEvent * e = NEW WEventEngageMana(color, source, this); + GameObserver::GetInstance()->receiveEvent(e); } - } - return result; + return result; +} + +int ManaPool::add(ManaCost * _cost, MTGCardInstance * source) +{ + if (!_cost) + return 0; + int result = ManaCost::add(_cost); + for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + for (int j = 0; j < _cost->getCost(i); j++) + { + WEvent * e = NEW WEventEngageMana(i, source, this); + GameObserver::GetInstance()->receiveEvent(e); + } + } + return result; +} +int ManaPool::pay(ManaCost * _cost) +{ + int current[Constants::MTG_NB_COLORS]; + for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + current[i] = cost[i]; + } + + int result = ManaCost::pay(_cost); + for (unsigned int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + int value = current[i] - cost[i]; + for (int j = 0; j < value; j++) + { + WEvent * e = NEW WEventConsumeMana(i, this); + GameObserver::GetInstance()->receiveEvent(e); + + } + } + return result; } diff --git a/projects/mtg/src/ManaCostHybrid.cpp b/projects/mtg/src/ManaCostHybrid.cpp index fc2221f57..b407e1a9d 100644 --- a/projects/mtg/src/ManaCostHybrid.cpp +++ b/projects/mtg/src/ManaCostHybrid.cpp @@ -2,27 +2,34 @@ #include "ManaCostHybrid.h" -ManaCostHybrid::ManaCostHybrid(){ - init(0,0,0,0); +ManaCostHybrid::ManaCostHybrid() +{ + init(0, 0, 0, 0); } -ManaCostHybrid::ManaCostHybrid(int c1,int v1,int c2,int v2){ - init(c1,v1,c2,v2); +ManaCostHybrid::ManaCostHybrid(int c1, int v1, int c2, int v2) +{ + init(c1, v1, c2, v2); } -void ManaCostHybrid::init(int c1,int v1,int c2,int v2){ - color1 = c1; - color2 = c2; - value1 = v1; - value2 = v2; +void ManaCostHybrid::init(int c1, int v1, int c2, int v2) +{ + color1 = c1; + color2 = c2; + value1 = v1; + value2 = v2; } -int ManaCostHybrid::getConvertedCost(){ - if (value2 > value1) return value2; - return value1; +int ManaCostHybrid::getConvertedCost() +{ + if (value2 > value1) + return value2; + return value1; } -int ManaCostHybrid::hasColor(int color){ - if (((color1 == color) && value1) || ((color2 == color) && value2)) return 1; - return 0; +int ManaCostHybrid::hasColor(int color) +{ + if (((color1 == color) && value1) || ((color2 == color) && value2)) + return 1; + return 0; } diff --git a/projects/mtg/src/MenuItem.cpp b/projects/mtg/src/MenuItem.cpp index 12b9f5532..9455de5de 100644 --- a/projects/mtg/src/MenuItem.cpp +++ b/projects/mtg/src/MenuItem.cpp @@ -4,127 +4,109 @@ #include "GameOptions.h" #include "Translate.h" -MenuItem::MenuItem(int id, WFont *font, string text, float x, float y, JQuad * _off, JQuad * _on, const char * particle, JQuad * particleTex, bool hasFocus): JGuiObject(id), mFont(font), mX(x), mY(y) +MenuItem::MenuItem(int id, WFont *font, string text, float x, float y, JQuad * _off, JQuad * _on, const char * particle, + JQuad * particleTex, bool hasFocus) : + JGuiObject(id), mFont(font), mX(x), mY(y) { - mText = _(text); - updatedSinceLastRender = 1; - mParticleSys = NEW hgeParticleSystem(resources.RetrievePSI(particle, particleTex)); - mParticleSys->MoveTo(mX, mY); + mText = _(text); + updatedSinceLastRender = 1; + mParticleSys = NEW hgeParticleSystem(resources.RetrievePSI(particle, particleTex)); + mParticleSys->MoveTo(mX, mY); - mHasFocus = hasFocus; - lastDt = 0.001f; - mScale = 1.0f; - mTargetScale = 1.0f; + mHasFocus = hasFocus; + lastDt = 0.001f; + mScale = 1.0f; + mTargetScale = 1.0f; - onQuad = _on; - offQuad = _off; + onQuad = _on; + offQuad = _off; - if (hasFocus) - Entering(); + if (hasFocus) + Entering(); } - void MenuItem::Render() { - JRenderer * renderer = JRenderer::GetInstance(); + JRenderer * renderer = JRenderer::GetInstance(); - - if (mHasFocus) + if (mHasFocus) { - PIXEL_TYPE start = ARGB(46,255,255,200); - if(mParticleSys) - start = mParticleSys->info.colColorStart.GetHWColor(); - - PIXEL_TYPE colors[] = - { - ARGB(0,0,0,0), - start, - ARGB(0,0,0,0), - start, - }; - renderer->FillRect(255,0,SCREEN_WIDTH-155,SCREEN_HEIGHT,colors); - // set additive blending - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); - mParticleSys->Render(); - // set normal blending - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - mFont->SetColor(ARGB(255,255,255,255)); - onQuad->SetColor(ARGB(70,255,255,255)); - renderer->RenderQuad(onQuad, SCREEN_WIDTH , SCREEN_HEIGHT/2 , 0,8,8); - onQuad->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(mText.c_str(), SCREEN_WIDTH/2, 20 + 3*SCREEN_HEIGHT/4, JGETEXT_CENTER); - renderer->RenderQuad(onQuad, mX , mY , 0,mScale,mScale); + PIXEL_TYPE start = ARGB(46,255,255,200); + if (mParticleSys) + start = mParticleSys->info.colColorStart.GetHWColor(); + PIXEL_TYPE colors[] = { ARGB(0,0,0,0), start, ARGB(0,0,0,0), start, }; + renderer->FillRect(255, 0, SCREEN_WIDTH - 155, SCREEN_HEIGHT, colors); + // set additive blending + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); + mParticleSys->Render(); + // set normal blending + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + mFont->SetColor(ARGB(255,255,255,255)); + onQuad->SetColor(ARGB(70,255,255,255)); + renderer->RenderQuad(onQuad, SCREEN_WIDTH, SCREEN_HEIGHT / 2, 0, 8, 8); + onQuad->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(mText.c_str(), SCREEN_WIDTH / 2, 20 + 3 * SCREEN_HEIGHT / 4, JGETEXT_CENTER); + renderer->RenderQuad(onQuad, mX, mY, 0, mScale, mScale); } - else + else { - renderer->RenderQuad(offQuad, mX , mY , 0,mScale,mScale); + renderer->RenderQuad(offQuad, mX, mY, 0, mScale, mScale); } - updatedSinceLastRender= 0; + updatedSinceLastRender = 0; } void MenuItem::Update(float dt) { - updatedSinceLastRender = 1; - lastDt = dt; - if (mScale < mTargetScale) + updatedSinceLastRender = 1; + lastDt = dt; + if (mScale < mTargetScale) { - mScale += 8.0f*dt; - if (mScale > mTargetScale) - mScale = mTargetScale; + mScale += 8.0f * dt; + if (mScale > mTargetScale) + mScale = mTargetScale; } - else if (mScale > mTargetScale) + else if (mScale > mTargetScale) { - mScale -= 8.0f*dt; - if (mScale < mTargetScale) - mScale = mTargetScale; + mScale -= 8.0f * dt; + if (mScale < mTargetScale) + mScale = mTargetScale; } mParticleSys->Update(dt); } - - - void MenuItem::Entering() { - mParticleSys->Fire(); - mHasFocus = true; - mTargetScale = 1.3f; + mParticleSys->Fire(); + mHasFocus = true; + mTargetScale = 1.3f; } - bool MenuItem::Leaving(JButton key) { - mParticleSys->Stop(true); - mHasFocus = false; - mTargetScale = 1.0f; - return true; + mParticleSys->Stop(true); + mHasFocus = false; + mTargetScale = 1.0f; + return true; } - bool MenuItem::ButtonPressed() { - return true; + return true; } - -MenuItem::~MenuItem(){ - if (mParticleSys) delete mParticleSys; +MenuItem::~MenuItem() +{ + if (mParticleSys) + delete mParticleSys; } ostream& MenuItem::toString(ostream& out) const { - return out << "MenuItem ::: mHasFocus : " << mHasFocus - << " ; mFont : " << mFont - << " ; mText : " << mText - << " ; mX,mY : " << mX << "," << mY - << " ; updatedSinceLastRender : " << updatedSinceLastRender - << " ; lastDt : " << lastDt - << " ; mScale : " << mScale - << " ; mTargetScale : " << mTargetScale - << " ; onQuad : " << onQuad - << " ; offQuad : " << offQuad - << " ; mParticleSys : " << mParticleSys; + return out << "MenuItem ::: mHasFocus : " << mHasFocus << " ; mFont : " << mFont << " ; mText : " << mText << " ; mX,mY : " + << mX << "," << mY << " ; updatedSinceLastRender : " << updatedSinceLastRender << " ; lastDt : " << lastDt + << " ; mScale : " << mScale << " ; mTargetScale : " << mTargetScale << " ; onQuad : " << onQuad + << " ; offQuad : " << offQuad << " ; mParticleSys : " << mParticleSys; } diff --git a/projects/mtg/src/Navigator.cpp b/projects/mtg/src/Navigator.cpp index 7fd7872eb..b31d739fd 100644 --- a/projects/mtg/src/Navigator.cpp +++ b/projects/mtg/src/Navigator.cpp @@ -5,766 +5,774 @@ namespace { - const Pos kDefaultCardPosition(300, 150, 1.0, 0.0, 220); - // the diagonal length of a card, doubled - const float kOverrideDistance = sqrtf(powf(CardGui::Width, 2) + powf(CardGui::Height, 2)) * 2; + const Pos kDefaultCardPosition(300, 150, 1.0, 0.0, 220); + // the diagonal length of a card, doubled + const float kOverrideDistance = sqrtf(powf(CardGui::Width, 2) + powf(CardGui::Height, 2)) * 2; - enum - { - kCardZone_Unknown = -1, - kCardZone_PlayerHand = 0, - kCardZone_PlayerAvatar, - kCardZone_PlayerLibrary, - kCardZone_PlayerGraveyard, - kCardZone_PlayerLands, - kCardZone_PlayerCreatures, - kCardZone_PlayerEnchantmentsAndArtifacts, - kCardZone_AIHand, - kCardZone_AIAvatar, - kCardZone_AILibrary, - kCardZone_AIGraveyard, - kCardZone_AILands, - kCardZone_AICreatures, - kCardZone_AIEnchantmentsAndArtifacts - }; + enum + { + kCardZone_Unknown = -1, + kCardZone_PlayerHand = 0, + kCardZone_PlayerAvatar, + kCardZone_PlayerLibrary, + kCardZone_PlayerGraveyard, + kCardZone_PlayerLands, + kCardZone_PlayerCreatures, + kCardZone_PlayerEnchantmentsAndArtifacts, + kCardZone_AIHand, + kCardZone_AIAvatar, + kCardZone_AILibrary, + kCardZone_AIGraveyard, + kCardZone_AILands, + kCardZone_AICreatures, + kCardZone_AIEnchantmentsAndArtifacts + }; } /** -** Helper class to Navigator. Represents a group of cards on the battlefield. -*/ + ** Helper class to Navigator. Represents a group of cards on the battlefield. + */ class CardZone { public: - /* - ** - */ - CardZone() : mCurrentCard(0) - { - } - - /* - ** - */ - void AddCard(PlayGuiObject* inCard) - { - mCards.push_back(inCard); - inCard->zoom = 1.0f; - } - - /* - ** - */ - void RemoveCard(PlayGuiObject* inCard) - { - bool found = false; - for (size_t index = 0; index < mCards.size(); ++index) + /* + ** + */ + CardZone() : + mCurrentCard(0) { - if (mCards[index] == inCard) - { - // if mCurrentCard points to a card at the end of an item but we're - // about to delete something earlier in the container, mCurrentCard - // won't be pointing anymore to the same element, so shift it - if (mCurrentCard >= index) + } + + /* + ** + */ + void AddCard(PlayGuiObject* inCard) + { + mCards.push_back(inCard); + inCard->zoom = 1.0f; + } + + /* + ** + */ + void RemoveCard(PlayGuiObject* inCard) + { + bool found = false; + for (size_t index = 0; index < mCards.size(); ++index) { - if (mCurrentCard > 0) - --mCurrentCard; + if (mCards[index] == inCard) + { + // if mCurrentCard points to a card at the end of an item but we're + // about to delete something earlier in the container, mCurrentCard + // won't be pointing anymore to the same element, so shift it + if (mCurrentCard >= index) + { + if (mCurrentCard > 0) + --mCurrentCard; + } + mCards[index]->zoom = 1.0f; + + mCards.erase(mCards.begin() + index); + found = true; + break; + } } - mCards[index]->zoom = 1.0f; - mCards.erase(mCards.begin() + index); - found = true; - break; - } + assert(found); } - assert(found); - } - - /* - ** Generic handling of navigation - left/right moves through the container, - ** up/down is rejected & moves to the next zone - */ - virtual bool HandleSelection(JButton inKey) - { - bool changeZone = true; - size_t oldIndex = mCurrentCard; - if (inKey == JGE_BTN_LEFT) + /* + ** Generic handling of navigation - left/right moves through the container, + ** up/down is rejected & moves to the next zone + */ + virtual bool HandleSelection(JButton inKey) { - if (mCurrentCard > 0) - { - --mCurrentCard; - changeZone = false; - } + bool changeZone = true; + size_t oldIndex = mCurrentCard; + if (inKey == JGE_BTN_LEFT) + { + if (mCurrentCard > 0) + { + --mCurrentCard; + changeZone = false; + } + } + + if (inKey == JGE_BTN_RIGHT) + { + if (mCurrentCard + 1 < mCards.size()) + { + ++mCurrentCard; + changeZone = false; + } + } + + if (oldIndex != mCurrentCard) + { + AnimateSelectionChange(oldIndex, true); + AnimateSelectionChange(mCurrentCard, false); + } + return changeZone; } - if (inKey == JGE_BTN_RIGHT) + /* + ** + */ + void AnimateSelectionChange(size_t inIndex, bool inLeaving) { - if (mCurrentCard + 1 < mCards.size()) - { - ++mCurrentCard; - changeZone = false; - } + if (inIndex < mCards.size()) + { + if (inLeaving) + { + mCards[inIndex]->zoom = 1.0f; + mCards[inIndex]->Leaving(JGE_BTN_NONE); + } + else + { + mCards[inIndex]->zoom = 1.4f; + mCards[inIndex]->Entering(); + } + } } - if (oldIndex != mCurrentCard) + /* + ** Return a neighbour CardZone (ie where to navigate to given a direction) + ** If there is no neighbour in that direction, return self (this ensures that + ** the parent Navigator class always has a legal currentZone pointer) + */ + CardZone* GetNeighbour(JButton inDirection) { - AnimateSelectionChange(oldIndex, true); - AnimateSelectionChange(mCurrentCard, false); - } - return changeZone; - } + CardZone* neighbour = this; + if (mNeighbours[inDirection]) + neighbour = mNeighbours[inDirection]; - /* - ** - */ - void AnimateSelectionChange(size_t inIndex, bool inLeaving) - { - if (inIndex < mCards.size()) + return neighbour; + } + + /* + ** When a zone change occurs, this will be called. This allows a zone + ** to 'pass through' so to speak, if a zone is empty, allow the navigation to + ** travel to the next neighbour + */ + virtual CardZone* EnterZone(JButton inDirection) { - if (inLeaving) - { - mCards[inIndex]->zoom = 1.0f; - mCards[inIndex]->Leaving(JGE_BTN_NONE); - } - else - { - mCards[inIndex]->zoom = 1.4f; - mCards[inIndex]->Entering(); - } + if (mCards.empty()) + { + if (inDirection != JGE_BTN_NONE) + { + CardZone* nextNeighbour = GetNeighbour(inDirection); + if (nextNeighbour) + return nextNeighbour->EnterZone(inDirection); + } + } + + // when entering a zone, animate the selection of the current card + AnimateSelectionChange(mCurrentCard, false); + return this; } - } - /* - ** Return a neighbour CardZone (ie where to navigate to given a direction) - ** If there is no neighbour in that direction, return self (this ensures that - ** the parent Navigator class always has a legal currentZone pointer) - */ - CardZone* GetNeighbour(JButton inDirection) - { - CardZone* neighbour = this; - if (mNeighbours[inDirection]) - neighbour = mNeighbours[inDirection]; - - return neighbour; - } - - /* - ** When a zone change occurs, this will be called. This allows a zone - ** to 'pass through' so to speak, if a zone is empty, allow the navigation to - ** travel to the next neighbour - */ - virtual CardZone* EnterZone(JButton inDirection) - { - if (mCards.empty()) + /* + ** + */ + void LeaveZone(JButton inDirection) { - if (inDirection != JGE_BTN_NONE) - { - CardZone* nextNeighbour = GetNeighbour(inDirection); - if (nextNeighbour) - return nextNeighbour->EnterZone(inDirection); - } + AnimateSelectionChange(mCurrentCard, true); } - - // when entering a zone, animate the selection of the current card - AnimateSelectionChange(mCurrentCard, false); - return this; - } - /* - ** - */ - void LeaveZone(JButton inDirection) - { - AnimateSelectionChange(mCurrentCard, true); - } - - /* - ** - */ - PlayGuiObject* GetCurrentCard() - { - PlayGuiObject* current = NULL; - if (mCards.size()) + /* + ** + */ + PlayGuiObject* GetCurrentCard() { - if (mCurrentCard < mCards.size()) - { - current = mCards[mCurrentCard]; - } + PlayGuiObject* current = NULL; + if (mCards.size()) + { + if (mCurrentCard < mCards.size()) + { + current = mCards[mCurrentCard]; + } + } + return current; } - return current; - } - std::vector mCards; - size_t mCurrentCard; + std::vector mCards; + size_t mCurrentCard; - // you'll typically have up to 4 neighbours, ie left/right/up/down - std::map mNeighbours; + // you'll typically have up to 4 neighbours, ie left/right/up/down + std::map mNeighbours; }; /* -** Derivation of CardZone, but with special key handling for the grid style layout, -** where we need to navigate up/down as well as left/right -*/ -class GridCardZone : public CardZone + ** Derivation of CardZone, but with special key handling for the grid style layout, + ** where we need to navigate up/down as well as left/right + */ +class GridCardZone: public CardZone { public: - GridCardZone(bool inEnforceAxisAlignment = false) : mEnforceAxisAlignment(inEnforceAxisAlignment) - { - } - - virtual bool HandleSelection(JButton inKey) - { - size_t oldIndex = mCurrentCard; - - float minDistance = 100000; - int selectedCardIndex = -1; - bool isHorizontal = (inKey == JGE_BTN_LEFT || inKey == JGE_BTN_RIGHT); - - for (size_t index = 0; index < mCards.size(); ++index) + GridCardZone(bool inEnforceAxisAlignment = false) : + mEnforceAxisAlignment(inEnforceAxisAlignment) { - // skip yourself - if (mCurrentCard == index) continue; + } - // skip if the card isn't on the same axis that we're stepping in - // this flag is an optional override. If enabled, it forces you to only be able to thumb over to the next card - // that is exactly on the same x or y coordinate axis - any card not strictly parallel is ignored. - if (mEnforceAxisAlignment) - { - if ((isHorizontal && mCards[mCurrentCard]->y != mCards[index]->y) || - (!isHorizontal && mCards[mCurrentCard]->x != mCards[index]->x)) + virtual bool HandleSelection(JButton inKey) + { + size_t oldIndex = mCurrentCard; + + float minDistance = 100000; + int selectedCardIndex = -1; + bool isHorizontal = (inKey == JGE_BTN_LEFT || inKey == JGE_BTN_RIGHT); + + for (size_t index = 0; index < mCards.size(); ++index) { - continue; + // skip yourself + if (mCurrentCard == index) + continue; + + // skip if the card isn't on the same axis that we're stepping in + // this flag is an optional override. If enabled, it forces you to only be able to thumb over to the next card + // that is exactly on the same x or y coordinate axis - any card not strictly parallel is ignored. + if (mEnforceAxisAlignment) + { + if ((isHorizontal && mCards[mCurrentCard]->y != mCards[index]->y) || (!isHorizontal && mCards[mCurrentCard]->x + != mCards[index]->x)) + { + continue; + } + } + + // if it's going in the wrong direction, skip + if (inKey == JGE_BTN_RIGHT && mCards[index]->x <= mCards[mCurrentCard]->x) + continue; + if (inKey == JGE_BTN_LEFT && mCards[index]->x >= mCards[mCurrentCard]->x) + continue; + if (inKey == JGE_BTN_DOWN && mCards[index]->y <= mCards[mCurrentCard]->y) + continue; + if (inKey == JGE_BTN_UP && mCards[index]->y >= mCards[mCurrentCard]->y) + continue; + + // we've found a card on the same axis, stash its value & compare against the previous + float yDiff = fabs(mCards[mCurrentCard]->y - mCards[index]->y); + float xDiff = fabs(mCards[mCurrentCard]->x - mCards[index]->x); + float distance = sqrtf(yDiff * yDiff + xDiff * xDiff); + + // CardSelector does this thing where if the distance in the axis you're moving is less than the distance od the card on the opposite axis, + // it would ignore the move - this made for some weird behavior where the UI wouldn't let you move in certain directions when a card looked reachable. + // instead, I'm using a different logic - if there's a card in the direction that you're stepping, and it's within a defined radius, go for it. + if (distance < minDistance && distance < kOverrideDistance) + { + minDistance = distance; + selectedCardIndex = index; + } } - } - // if it's going in the wrong direction, skip - if (inKey == JGE_BTN_RIGHT && mCards[index]->x <= mCards[mCurrentCard]->x) continue; - if (inKey == JGE_BTN_LEFT && mCards[index]->x >= mCards[mCurrentCard]->x) continue; - if (inKey == JGE_BTN_DOWN && mCards[index]->y <= mCards[mCurrentCard]->y) continue; - if (inKey == JGE_BTN_UP && mCards[index]->y >= mCards[mCurrentCard]->y) continue; + bool changeZone = true; + if (selectedCardIndex != -1) + { + mCurrentCard = selectedCardIndex; + changeZone = false; - // we've found a card on the same axis, stash its value & compare against the previous - float yDiff = fabs(mCards[mCurrentCard]->y - mCards[index]->y); - float xDiff = fabs(mCards[mCurrentCard]->x - mCards[index]->x); - float distance = sqrtf(yDiff * yDiff + xDiff * xDiff); - - // CardSelector does this thing where if the distance in the axis you're moving is less than the distance od the card on the opposite axis, - // it would ignore the move - this made for some weird behavior where the UI wouldn't let you move in certain directions when a card looked reachable. - // instead, I'm using a different logic - if there's a card in the direction that you're stepping, and it's within a defined radius, go for it. - if (distance < minDistance && distance < kOverrideDistance) - { - minDistance = distance; - selectedCardIndex = index; - } + if (oldIndex != mCurrentCard) + { + AnimateSelectionChange(oldIndex, true); + AnimateSelectionChange(mCurrentCard, false); + } + } + + return changeZone; } - bool changeZone = true; - if (selectedCardIndex != -1) - { - mCurrentCard = selectedCardIndex; - changeZone = false; - - if (oldIndex != mCurrentCard) - { - AnimateSelectionChange(oldIndex, true); - AnimateSelectionChange(mCurrentCard, false); - } - } - - return changeZone; - } - protected: - bool mEnforceAxisAlignment; + bool mEnforceAxisAlignment; }; /* -** -*/ + ** + */ class HandCardZone: public GridCardZone { public: - /* - ** the card hand zone operates slightly differently than the default zones: - ** if entering via up/down, - ** set the current card selection to the bottom/top card - */ - virtual CardZone* EnterZone(JButton inDirection) - { - // TODO, check if the hand is flattened - if (mCards.size()) + /* + ** the card hand zone operates slightly differently than the default zones: + ** if entering via up/down, + ** set the current card selection to the bottom/top card + */ + virtual CardZone* EnterZone(JButton inDirection) { - if (inDirection == JGE_BTN_UP) - mCurrentCard = mCards.size() - 1; - else if (inDirection == JGE_BTN_DOWN) - mCurrentCard = 0; + // TODO, check if the hand is flattened + if (mCards.size()) + { + if (inDirection == JGE_BTN_UP) + mCurrentCard = mCards.size() - 1; + else if (inDirection == JGE_BTN_DOWN) + mCurrentCard = 0; + } + + return CardZone::EnterZone(inDirection); + } +}; + +/* + ** + */ +class LandCardZone: public GridCardZone +{ +public: + virtual CardZone* EnterZone(JButton inDirection); +}; + +/* + ** + */ +class CreatureCardZone: public GridCardZone +{ +public: + virtual CardZone* EnterZone(JButton inDirection); +}; + +/* + ** The base class dictates normally, if you enter a zone and it's empty, move to + ** the next zone in the same direction. + ** Adding an override here - if there are no creatures in play but there are land, + ** and we're moving horizontally, jump up to the land instead + */ +CardZone* CreatureCardZone::EnterZone(JButton inDirection) +{ + if ((inDirection == JGE_BTN_LEFT || inDirection == JGE_BTN_RIGHT) && mCards.empty()) + { + LandCardZone* landZone = dynamic_cast (mNeighbours[JGE_BTN_DOWN]); + if (landZone == NULL) + { + landZone = dynamic_cast (mNeighbours[JGE_BTN_UP]); + } + + if (landZone && !landZone->mCards.empty()) + { + return landZone->EnterZone(inDirection); + } } return CardZone::EnterZone(inDirection); - } -}; - -/* -** -*/ -class LandCardZone : public GridCardZone -{ -public: - virtual CardZone* EnterZone(JButton inDirection); -}; - -/* -** -*/ -class CreatureCardZone : public GridCardZone -{ -public: - virtual CardZone* EnterZone(JButton inDirection); -}; - -/* -** The base class dictates normally, if you enter a zone and it's empty, move to -** the next zone in the same direction. -** Adding an override here - if there are no creatures in play but there are land, -** and we're moving horizontally, jump up to the land instead -*/ -CardZone* CreatureCardZone::EnterZone(JButton inDirection) -{ - if ((inDirection == JGE_BTN_LEFT || inDirection == JGE_BTN_RIGHT) && mCards.empty()) - { - LandCardZone* landZone = dynamic_cast(mNeighbours[JGE_BTN_DOWN]); - if (landZone == NULL) - { - landZone = dynamic_cast(mNeighbours[JGE_BTN_UP]); - } - - if (landZone && !landZone->mCards.empty()) - { - return landZone->EnterZone(inDirection); - } - } - - return CardZone::EnterZone(inDirection); } /* -** Same pattern to the CreatureCardZone pattern - if moving through an empty land zone, -** set the focus on the land zone if it has cards -*/ + ** Same pattern to the CreatureCardZone pattern - if moving through an empty land zone, + ** set the focus on the land zone if it has cards + */ CardZone* LandCardZone::EnterZone(JButton inDirection) { - if ((inDirection == JGE_BTN_LEFT || inDirection == JGE_BTN_RIGHT) && mCards.empty()) - { - CreatureCardZone* creatureZone = dynamic_cast(mNeighbours[JGE_BTN_DOWN]); - if (creatureZone == NULL) + if ((inDirection == JGE_BTN_LEFT || inDirection == JGE_BTN_RIGHT) && mCards.empty()) { - creatureZone = dynamic_cast(mNeighbours[JGE_BTN_UP]); + CreatureCardZone* creatureZone = dynamic_cast (mNeighbours[JGE_BTN_DOWN]); + if (creatureZone == NULL) + { + creatureZone = dynamic_cast (mNeighbours[JGE_BTN_UP]); + } + + if (creatureZone && !creatureZone->mCards.empty()) + { + return creatureZone->EnterZone(inDirection); + } } - if (creatureZone && !creatureZone->mCards.empty()) - { - return creatureZone->EnterZone(inDirection); - } - } - - return CardZone::EnterZone(inDirection); + return CardZone::EnterZone(inDirection); } - /* -** Constructor. All the navigation logic is initialized here, by pairing up each card zone with a set of neighbours. -*/ -Navigator::Navigator(DuelLayers* inDuelLayers) - : mDrawPosition(kDefaultCardPosition), mDuelLayers(inDuelLayers), mLimitorEnabled(false) + ** Constructor. All the navigation logic is initialized here, by pairing up each card zone with a set of neighbours. + */ +Navigator::Navigator(DuelLayers* inDuelLayers) : + mDrawPosition(kDefaultCardPosition), mDuelLayers(inDuelLayers), mLimitorEnabled(false) { - assert(mDuelLayers); + assert(mDuelLayers); - // initialize the cardZone layout - mCardZones.insert(std::pair(kCardZone_PlayerHand, NEW HandCardZone())); - mCardZones.insert(std::pair(kCardZone_PlayerAvatar, NEW CardZone())); - mCardZones.insert(std::pair(kCardZone_PlayerLibrary, NEW CardZone())); - mCardZones.insert(std::pair(kCardZone_PlayerGraveyard, NEW CardZone())); - mCardZones.insert(std::pair(kCardZone_PlayerLands, NEW LandCardZone())); - mCardZones.insert(std::pair(kCardZone_PlayerCreatures, NEW CreatureCardZone())); - mCardZones.insert(std::pair(kCardZone_PlayerEnchantmentsAndArtifacts, NEW GridCardZone())); - mCardZones.insert(std::pair(kCardZone_AIHand, NEW CardZone())); - mCardZones.insert(std::pair(kCardZone_AIAvatar, NEW CardZone())); - mCardZones.insert(std::pair(kCardZone_AILibrary, NEW CardZone())); - mCardZones.insert(std::pair(kCardZone_AIGraveyard, NEW CardZone())); - mCardZones.insert(std::pair(kCardZone_AILands, NEW LandCardZone())); - mCardZones.insert(std::pair(kCardZone_AICreatures, NEW CreatureCardZone())); - mCardZones.insert(std::pair(kCardZone_AIEnchantmentsAndArtifacts, NEW GridCardZone())); + // initialize the cardZone layout + mCardZones.insert(std::pair(kCardZone_PlayerHand, NEW HandCardZone())); + mCardZones.insert(std::pair(kCardZone_PlayerAvatar, NEW CardZone())); + mCardZones.insert(std::pair(kCardZone_PlayerLibrary, NEW CardZone())); + mCardZones.insert(std::pair(kCardZone_PlayerGraveyard, NEW CardZone())); + mCardZones.insert(std::pair(kCardZone_PlayerLands, NEW LandCardZone())); + mCardZones.insert(std::pair(kCardZone_PlayerCreatures, NEW CreatureCardZone())); + mCardZones.insert(std::pair(kCardZone_PlayerEnchantmentsAndArtifacts, NEW GridCardZone())); + mCardZones.insert(std::pair(kCardZone_AIHand, NEW CardZone())); + mCardZones.insert(std::pair(kCardZone_AIAvatar, NEW CardZone())); + mCardZones.insert(std::pair(kCardZone_AILibrary, NEW CardZone())); + mCardZones.insert(std::pair(kCardZone_AIGraveyard, NEW CardZone())); + mCardZones.insert(std::pair(kCardZone_AILands, NEW LandCardZone())); + mCardZones.insert(std::pair(kCardZone_AICreatures, NEW CreatureCardZone())); + mCardZones.insert(std::pair(kCardZone_AIEnchantmentsAndArtifacts, NEW GridCardZone())); - // navigation rules: each zone has up to 4 neighbours, specified here - mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerAvatar]; - mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerCreatures]; - mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AIAvatar]; + // navigation rules: each zone has up to 4 neighbours, specified here + mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; + mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerAvatar]; + mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerCreatures]; + mCardZones[kCardZone_PlayerHand]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerHand]; - mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerLibrary]; - mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]; - mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLands]; + mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerHand]; + mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerLibrary]; + mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]; + mCardZones[kCardZone_PlayerAvatar]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLands]; - mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerGraveyard]; - mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerAvatar]; - mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerLands]; - mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerAvatar]; + mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerGraveyard]; + mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerAvatar]; + mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerLands]; + mCardZones[kCardZone_PlayerLibrary]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerAvatar]; - mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerHand]; - mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLibrary]; - mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerCreatures]; - mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerAvatar]; + mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerHand]; + mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLibrary]; + mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerCreatures]; + mCardZones[kCardZone_PlayerGraveyard]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerAvatar]; - mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerCreatures]; - mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerAvatar]; - mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]; - mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerAvatar]; + mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerCreatures]; + mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerAvatar]; + mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]; + mCardZones[kCardZone_PlayerLands]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerAvatar]; - mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AICreatures]; - mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLands]; - mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]; - mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerHand]; + mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AICreatures]; + mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLands]; + mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]; + mCardZones[kCardZone_PlayerCreatures]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerHand]; - mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerCreatures]; - mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLands]; - // experiment, allow round tripping from the left edge over to the right side - mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerAvatar]; - mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerCreatures]; + mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_PlayerCreatures]; + mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerLands]; + // experiment, allow round tripping from the left edge over to the right side + mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerAvatar]; + mCardZones[kCardZone_PlayerEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerCreatures]; - mCardZones[kCardZone_AIHand]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_AIHand]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AIEnchantmentsAndArtifacts]; - mCardZones[kCardZone_AIHand]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILibrary]; + mCardZones[kCardZone_AIHand]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; + mCardZones[kCardZone_AIHand]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AIEnchantmentsAndArtifacts]; + mCardZones[kCardZone_AIHand]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILibrary]; - mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AILands]; - mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AIHand]; - mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILibrary]; - mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerHand]; + mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AILands]; + mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AIHand]; + mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILibrary]; + mCardZones[kCardZone_AIAvatar]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerHand]; - mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIGraveyard]; - mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AILands]; - mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILands]; + mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIGraveyard]; + mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AILands]; + mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIAvatar]; + mCardZones[kCardZone_AILibrary]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILands]; - mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AILibrary]; - mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILands]; + mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; + mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AILibrary]; + mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIAvatar]; + mCardZones[kCardZone_AIGraveyard]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AILands]; - mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AICreatures]; - mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIEnchantmentsAndArtifacts]; - mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerHand]; + mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; + mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AICreatures]; + mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIEnchantmentsAndArtifacts]; + mCardZones[kCardZone_AILands]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerHand]; - mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AILands]; - mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerCreatures]; - mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIEnchantmentsAndArtifacts]; - mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerHand]; + mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AILands]; + mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_PlayerCreatures]; + mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_AIEnchantmentsAndArtifacts]; + mCardZones[kCardZone_AICreatures]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_PlayerHand]; - mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; - mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AICreatures]; - // experiment, allow round tripping from the left edge over to the right side - mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerHand]; - mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AICreatures]; + mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_UP] = mCardZones[kCardZone_AIAvatar]; + mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_DOWN] = mCardZones[kCardZone_AICreatures]; + // experiment, allow round tripping from the left edge over to the right side + mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_LEFT] = mCardZones[kCardZone_PlayerHand]; + mCardZones[kCardZone_AIEnchantmentsAndArtifacts]->mNeighbours[JGE_BTN_RIGHT] = mCardZones[kCardZone_AICreatures]; - mCurrentZone = mCardZones[kCardZone_PlayerAvatar]; + mCurrentZone = mCardZones[kCardZone_PlayerAvatar]; } /* -** -*/ + ** + */ Navigator::~Navigator() { - std::map::iterator iter = mCardZones.begin(); - for (; iter != mCardZones.end(); ++iter) - { - SAFE_DELETE(iter->second); - } + std::map::iterator iter = mCardZones.begin(); + for (; iter != mCardZones.end(); ++iter) + { + SAFE_DELETE(iter->second); + } } + /* -** -*/ + ** + */ bool Navigator::CheckUserInput(JButton inKey) { - bool result = true; + bool result = true; - switch (inKey) - { + switch (inKey) + { case JGE_BTN_SEC: - GameObserver::GetInstance()->cancelCurrentAction(); - return true; + GameObserver::GetInstance()->cancelCurrentAction(); + return true; case JGE_BTN_OK: - GameObserver::GetInstance()->ButtonPressed(GetCurrentCard()); - return true; - break; + GameObserver::GetInstance()->ButtonPressed(GetCurrentCard()); + return true; + break; case JGE_BTN_LEFT: case JGE_BTN_RIGHT: case JGE_BTN_UP: case JGE_BTN_DOWN: - HandleKeyStroke(inKey); - break; + HandleKeyStroke(inKey); + break; case JGE_BTN_CANCEL: - mDrawMode = (mDrawMode+1) % DrawMode::kNumDrawModes; - if(mDrawMode == DrawMode::kText) - options[Options::DISABLECARDS].number = 1; - else - options[Options::DISABLECARDS].number = 0; - break; + mDrawMode = (mDrawMode + 1) % DrawMode::kNumDrawModes; + if (mDrawMode == DrawMode::kText) + options[Options::DISABLECARDS].number = 1; + else + options[Options::DISABLECARDS].number = 0; + break; default: - result = false; - } + result = false; + } - return result; + return result; } bool Navigator::CheckUserInput(int x, int y) { - // TODO - figure out what to do with mouse support - return false; + // TODO - figure out what to do with mouse support + return false; } /* -** reposition the selected card's draw location -*/ + ** reposition the selected card's draw location + */ void Navigator::Update(float dt) { - float boundary = mDuelLayers->RightBoundary(); - float position = boundary - CardGui::BigWidth / 2; - if (GetCurrentCard() != NULL) - { - if ((GetCurrentCard()->x + CardGui::Width / 2 > position - CardGui::BigWidth / 2) && - (GetCurrentCard()->x - CardGui::Width / 2 < position + CardGui::BigWidth / 2)) + float boundary = mDuelLayers->RightBoundary(); + float position = boundary - CardGui::BigWidth / 2; + if (GetCurrentCard() != NULL) { - position = CardGui::BigWidth / 2 - 10; + if ((GetCurrentCard()->x + CardGui::Width / 2 > position - CardGui::BigWidth / 2) && (GetCurrentCard()->x - CardGui::Width + / 2 < position + CardGui::BigWidth / 2)) + { + position = CardGui::BigWidth / 2 - 10; + } } - } - if (position < CardGui::BigWidth / 2) - position = CardGui::BigWidth / 2; - - mDrawPosition.x = position; - mDrawPosition.Update(dt); + if (position < CardGui::BigWidth / 2) + position = CardGui::BigWidth / 2; + + mDrawPosition.x = position; + mDrawPosition.Update(dt); } /* -** -*/ + ** + */ PlayGuiObject* Navigator::GetCurrentCard() { - return mCurrentZone ? mCurrentZone->GetCurrentCard() : NULL; + return mCurrentZone ? mCurrentZone->GetCurrentCard() : NULL; } /* -** -*/ + ** + */ void Navigator::Render() { - if (GetCurrentCard() != NULL) - { - GetCurrentCard()->Render(); - - CardView* card = dynamic_cast(GetCurrentCard()); - if (card) + if (GetCurrentCard() != NULL) { - card->DrawCard(mDrawPosition, mDrawMode); + GetCurrentCard()->Render(); + + CardView* card = dynamic_cast (GetCurrentCard()); + if (card) + { + card->DrawCard(mDrawPosition, mDrawMode); + } } - } } /* -** -*/ + ** + */ void Navigator::HandleKeyStroke(JButton inKey) { - assert(mCurrentZone); - if (mCurrentZone) - { - bool changeZone = mCurrentZone->HandleSelection(inKey); - - if (changeZone && !mLimitorEnabled) + assert(mCurrentZone); + if (mCurrentZone) { - mCurrentZone->LeaveZone(inKey); - mCurrentZone = mCurrentZone->GetNeighbour(inKey); - mCurrentZone = mCurrentZone->EnterZone(inKey); + bool changeZone = mCurrentZone->HandleSelection(inKey); + + if (changeZone && !mLimitorEnabled) + { + mCurrentZone->LeaveZone(inKey); + mCurrentZone = mCurrentZone->GetNeighbour(inKey); + mCurrentZone = mCurrentZone->EnterZone(inKey); + } } - } } /* -** unused. This is CardSelector specific. -*/ + ** unused. This is CardSelector specific. + */ void Navigator::PopLimitor() { } /* -** same as above. -*/ + ** same as above. + */ void Navigator::PushLimitor() { } /* -** -*/ + ** + */ void Navigator::Limit(LimitorFunctor* inLimitor, CardView::SelectorZone inZone) { - mLimitorEnabled = (inLimitor != NULL); - if (inZone == CardView::handZone) - { - mCurrentZone->LeaveZone(JGE_BTN_NONE); - - if (mLimitorEnabled) + mLimitorEnabled = (inLimitor != NULL); + if (inZone == CardView::handZone) { - mCurrentZoneStack.push(mCurrentZone); - mCurrentZone = mCardZones[kCardZone_PlayerHand]; - } - else - { - mCurrentZone = mCurrentZoneStack.top(); - mCurrentZoneStack.pop(); - assert(mCurrentZone); - if (mCurrentZone == NULL) - { - mCurrentZone = mCardZones[kCardZone_PlayerHand]; - } - } + mCurrentZone->LeaveZone(JGE_BTN_NONE); - mCurrentZone->EnterZone(JGE_BTN_NONE); - } + if (mLimitorEnabled) + { + mCurrentZoneStack.push(mCurrentZone); + mCurrentZone = mCardZones[kCardZone_PlayerHand]; + } + else + { + mCurrentZone = mCurrentZoneStack.top(); + mCurrentZoneStack.pop(); + assert(mCurrentZone); + if (mCurrentZone == NULL) + { + mCurrentZone = mCardZones[kCardZone_PlayerHand]; + } + } + + mCurrentZone->EnterZone(JGE_BTN_NONE); + } } /* -** -*/ + ** + */ int Navigator::CardToCardZone(PlayGuiObject* inCard) { - int result = kCardZone_Unknown; - GuiAvatar* avatar = dynamic_cast(inCard); - if (avatar) - { - if (avatar->player->isAI()) + int result = kCardZone_Unknown; + GuiAvatar* avatar = dynamic_cast (inCard); + if (avatar) { - result = kCardZone_AIAvatar; - } - else - { - result = kCardZone_PlayerAvatar; - } - } - - GuiGraveyard* graveyard = dynamic_cast(inCard); - if (graveyard) - { - if (graveyard->player->isAI()) - { - result = kCardZone_AIGraveyard; - } - else - { - result = kCardZone_PlayerGraveyard; - } - } - - GuiLibrary* library = dynamic_cast(inCard); - if (library) - { - if (library->player->isAI()) - { - result = kCardZone_AILibrary; - } - else - { - result = kCardZone_PlayerLibrary; - } - } - - GuiOpponentHand* opponentHand = dynamic_cast(inCard); - if (opponentHand) - { - result = kCardZone_AIHand; - } - - CardView* card = dynamic_cast(inCard); - { - if (card) - { - if (card->owner == CardView::handZone) - { - result = kCardZone_PlayerHand; - } - else if (card->owner == CardView::playZone) - { - int isAI = card->getCard()->owner->isAI(); - - if (card->getCard()->isCreature()) + if (avatar->player->isAI()) { - result = isAI ? kCardZone_AICreatures : kCardZone_PlayerCreatures; + result = kCardZone_AIAvatar; } - else if (card->getCard()->isLand()) + else { - result = isAI ? kCardZone_AILands : kCardZone_PlayerLands; + result = kCardZone_PlayerAvatar; } - else if (card->getCard()->isSpell()) - { - - if (card->getCard()->target != NULL) - isAI = card->getCard()->target->owner->isAI(); - - // nasty hack: the lines above don't always work, as when an enchantment comes into play, its ability hasn't been activated yet, - // so it doesn't yet have a target. Instead, we now look at the card's position, if it's in the top half of the screen, it goes into an AI zone - //isAI = card->y < JRenderer::GetInstance()->GetActualHeight() / 2; - - // enchantments that target creatures are treated as part of the creature zone - if (card->getCard()->spellTargetType.find("creature") != string::npos) - { - result = isAI ? kCardZone_AICreatures : kCardZone_PlayerCreatures; - } - else if (card->getCard()->spellTargetType.find("land") != string::npos) - { - result = isAI ? kCardZone_AILands : kCardZone_PlayerLands; - } - else - { - result = isAI ? kCardZone_AIEnchantmentsAndArtifacts : kCardZone_PlayerEnchantmentsAndArtifacts; - } - } - else assert(false); - } - else - { - assert(false); - } } - } - assert(result != kCardZone_Unknown); - return result; + GuiGraveyard* graveyard = dynamic_cast (inCard); + if (graveyard) + { + if (graveyard->player->isAI()) + { + result = kCardZone_AIGraveyard; + } + else + { + result = kCardZone_PlayerGraveyard; + } + } + + GuiLibrary* library = dynamic_cast (inCard); + if (library) + { + if (library->player->isAI()) + { + result = kCardZone_AILibrary; + } + else + { + result = kCardZone_PlayerLibrary; + } + } + + GuiOpponentHand* opponentHand = dynamic_cast (inCard); + if (opponentHand) + { + result = kCardZone_AIHand; + } + + CardView* card = dynamic_cast (inCard); + { + if (card) + { + if (card->owner == CardView::handZone) + { + result = kCardZone_PlayerHand; + } + else if (card->owner == CardView::playZone) + { + int isAI = card->getCard()->owner->isAI(); + + if (card->getCard()->isCreature()) + { + result = isAI ? kCardZone_AICreatures : kCardZone_PlayerCreatures; + } + else if (card->getCard()->isLand()) + { + result = isAI ? kCardZone_AILands : kCardZone_PlayerLands; + } + else if (card->getCard()->isSpell()) + { + + if (card->getCard()->target != NULL) + isAI = card->getCard()->target->owner->isAI(); + + // nasty hack: the lines above don't always work, as when an enchantment comes into play, its ability hasn't been activated yet, + // so it doesn't yet have a target. Instead, we now look at the card's position, if it's in the top half of the screen, it goes into an AI zone + //isAI = card->y < JRenderer::GetInstance()->GetActualHeight() / 2; + + // enchantments that target creatures are treated as part of the creature zone + if (card->getCard()->spellTargetType.find("creature") != string::npos) + { + result = isAI ? kCardZone_AICreatures : kCardZone_PlayerCreatures; + } + else if (card->getCard()->spellTargetType.find("land") != string::npos) + { + result = isAI ? kCardZone_AILands : kCardZone_PlayerLands; + } + else + { + result = isAI ? kCardZone_AIEnchantmentsAndArtifacts : kCardZone_PlayerEnchantmentsAndArtifacts; + } + } + else + assert(false); + } + else + { + assert(false); + } + } + } + + assert(result != kCardZone_Unknown); + return result; } /* -** -*/ + ** + */ void Navigator::Add(PlayGuiObject* card) { - // figure out what card's been added, add it to the appropriate pile - int zone = CardToCardZone(card); - if (zone != kCardZone_Unknown) - { - mCardZones[zone]->AddCard(card); - } + // figure out what card's been added, add it to the appropriate pile + int zone = CardToCardZone(card); + if (zone != kCardZone_Unknown) + { + mCardZones[zone]->AddCard(card); + } } /* -** -*/ + ** + */ void Navigator::Remove(PlayGuiObject* card) { - int zone = CardToCardZone(card); - if (zone != kCardZone_Unknown) - { - mCardZones[zone]->RemoveCard(card); - } + int zone = CardToCardZone(card); + if (zone != kCardZone_Unknown) + { + mCardZones[zone]->RemoveCard(card); + } } diff --git a/projects/mtg/src/OptionItem.cpp b/projects/mtg/src/OptionItem.cpp index ece1e7bb6..b79db651a 100644 --- a/projects/mtg/src/OptionItem.cpp +++ b/projects/mtg/src/OptionItem.cpp @@ -9,534 +9,675 @@ #include //OptionItem -OptionItem::OptionItem( int _id, string _displayValue): WGuiItem(_displayValue) { - id = _id; - mFocus=false; +OptionItem::OptionItem(int _id, string _displayValue) : + WGuiItem(_displayValue) +{ + id = _id; + mFocus = false; } //OptionInteger -void OptionInteger::Render(){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT)); - JRenderer * renderer = JRenderer::GetInstance(); +void OptionInteger::Render() +{ + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT)); + JRenderer * renderer = JRenderer::GetInstance(); - mFont->DrawString(_(displayValue).c_str(), x + 2, y + 3); - char buf[512]; - if (maxValue == 1){ - if (value) - sprintf(buf, "%s", _("Yes").c_str()); + mFont->DrawString(_(displayValue).c_str(), x + 2, y + 3); + char buf[512]; + if (maxValue == 1) + { + if (value) + sprintf(buf, "%s", _("Yes").c_str()); + else + sprintf(buf, "%s", _("No").c_str()); + } else - sprintf(buf, "%s", _("No").c_str()); - }else{ - if(value == defValue && strDefault.size()) - sprintf(buf, "%s", _(strDefault).c_str()); - else - sprintf(buf, "%i", value); - } - mFont->DrawString(buf, width - 5, y + 3, JGETEXT_RIGHT); + { + if (value == defValue && strDefault.size()) + sprintf(buf, "%s", _(strDefault).c_str()); + else + sprintf(buf, "%i", value); + } + mFont->DrawString(buf, width - 5, y + 3, JGETEXT_RIGHT); } -OptionInteger::OptionInteger(int _id, string _displayValue, int _maxValue, int _increment, int _defV, string _sDef, int _minValue): OptionItem(_id, _displayValue){ - defValue = _defV; - strDefault = _sDef; - maxValue = _maxValue; - minValue = _minValue; - increment = _increment; - value = ::options[id].number; - x = 0; - y = 0; +OptionInteger::OptionInteger(int _id, string _displayValue, int _maxValue, int _increment, int _defV, string _sDef, int _minValue) : + OptionItem(_id, _displayValue) +{ + defValue = _defV; + strDefault = _sDef; + maxValue = _maxValue; + minValue = _minValue; + increment = _increment; + value = ::options[id].number; + x = 0; + y = 0; } -void OptionInteger::setData(){ - if(id != INVALID_OPTION) - options[id] = GameOption(value); +void OptionInteger::setData() +{ + if (id != INVALID_OPTION) + options[id] = GameOption(value); } //Option Select -void OptionSelect::initSelections(){ - //Find currently active bit in the list. - for (size_t i = 0; i < selections.size(); ++i) - if (selections[i] == options[id].str) - value = i; +void OptionSelect::initSelections() +{ + //Find currently active bit in the list. + for (size_t i = 0; i < selections.size(); ++i) + if (selections[i] == options[id].str) + value = i; } -void OptionSelect::Entering(JButton key){ - OptionItem::Entering(key); - prior_value = value; +void OptionSelect::Entering(JButton key) +{ + OptionItem::Entering(key); + prior_value = value; } -void OptionSelect::Render(){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT)); +void OptionSelect::Render() +{ + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT)); - JRenderer * renderer = JRenderer::GetInstance(); - mFont->DrawString(_(displayValue).c_str(), x, y + 2); + JRenderer * renderer = JRenderer::GetInstance(); + mFont->DrawString(_(displayValue).c_str(), x, y + 2); - if (value < selections.size()) - mFont->DrawString(_(selections[value]).c_str(), x + width - 10, y + 2, JGETEXT_RIGHT); - else - mFont->DrawString(_("Unset").c_str(),x + width - 10, y + 2, JGETEXT_RIGHT); + if (value < selections.size()) + mFont->DrawString(_(selections[value]).c_str(), x + width - 10, y + 2, JGETEXT_RIGHT); + else + mFont->DrawString(_("Unset").c_str(), x + width - 10, y + 2, JGETEXT_RIGHT); } -void OptionSelect::setData(){ - if(id == INVALID_OPTION) return; +void OptionSelect::setData() +{ + if (id == INVALID_OPTION) + return; - if (value < selections.size()) - options[id] = GameOption(selections[value]); + if (value < selections.size()) + options[id] = GameOption(selections[value]); } -bool OptionSelect::Selectable(){ - return (selections.size() > 1); +bool OptionSelect::Selectable() +{ + return (selections.size() > 1); } -void OptionSelect::addSelection(string s){ - selections.push_back(s); +void OptionSelect::addSelection(string s) +{ + selections.push_back(s); } //OptionProfile const string OptionProfile::DIRTESTER = "collection.dat"; -OptionProfile::OptionProfile(GameApp * _app, JGuiListener * jgl) : OptionDirectory(JGE_GET_RES("profiles"), Options::ACTIVE_PROFILE, "Profile", DIRTESTER){ - app = _app; - listener = jgl; - height=60; - addSelection("Default"); - sort(selections.begin(),selections.end()); - mFocus = false; - initSelections(); - populate(); -}; - -void OptionProfile::initSelections() { - OptionSelect::initSelections(); - initialValue = value; -} - -void OptionProfile::addSelection(string s){ - OptionDirectory::addSelection(s); - - //Check how many options... if 1, we're not selectable. - if(selections.size() > 1) - canSelect = true; - else - canSelect = false; - -} -void OptionProfile::updateValue(){ - value++; - if (value > selections.size() - 1) - value=0; - - populate(); -} - -void OptionProfile::Reload(){ - OptionDirectory::Reload(); - populate(); -} -void OptionProfile::populate(){ - string temp = options[Options::ACTIVE_PROFILE].str; - if (value >= selections.size()){ //TODO fail gracefully. - return; - } - options[Options::ACTIVE_PROFILE].str = selections[value]; - PlayerData * pdata = NEW PlayerData(app->collection); - - int unlocked = 0, sets = setlist.size(); - std::ifstream file(options.profileFile(PLAYER_SETTINGS).c_str()); - std::string s; - if(file){ - while(std::getline(file,s)){ - if(s.substr(0, 9) == "unlocked_") - unlocked++; - } - file.close(); - } - - options[Options::ACTIVE_PROFILE] = temp; - - char buf[512], format[512]; - sprintf(format,"%s\n%s\n%s\n",_("Credits: %i").c_str(),_("Cards: %i").c_str(),_("Sets: %i (of %i)").c_str()); - sprintf(buf,format,pdata->credits,pdata->collection->totalCards(),unlocked,sets); - preview = buf; - - SAFE_DELETE(pdata); -} - -void OptionProfile::Render(){ - JRenderer * renderer = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetScale(1); - int spacing = 2+(int)mFont->GetHeight(); - - float pX, pY; - pX = x; - pY = y; - char buf[512]; - if(selections[value] == "Default") - sprintf(buf,"player/avatar.jpg"); - else - sprintf(buf,"profiles/%s/avatar.jpg",selections[value].c_str()); - string filename = buf; - JQuad * mAvatar = resources.RetrieveTempQuad(filename,TEXTURE_SUB_EXACT); - - if(mAvatar){ - renderer->RenderQuad(mAvatar,x,pY); - pX += 40; - } - - mFont->SetColor(getColor(WGuiColor::TEXT_HEADER)); - mFont->DrawString(selections[value].c_str(), pX, pY + 2, JGETEXT_LEFT); - mFont->SetScale(0.8f); - mFont->SetColor(getColor(WGuiColor::TEXT_BODY)); - mFont->DrawString(preview.c_str(), pX, pY + spacing + 2, JGETEXT_LEFT); - mFont->SetScale(1.0f); - -} -void OptionProfile::Entering(JButton key){ - mFocus = true; - initialValue = value; -} - -void OptionProfile::confirmChange(bool confirmed){ - if (initialValue >= selections.size()) - return; - - int result; - - if(confirmed) result = value; - else result = initialValue; - - options[Options::ACTIVE_PROFILE] = selections[result]; - value = result; - - populate(); - if(listener && confirmed){ - listener->ButtonPressed(-102,5); - initialValue = value; - } - return; -} -//OptionThemeStyle -OptionThemeStyle::OptionThemeStyle(string _displayValue) : OptionSelect(Options::GUI_STYLE,_displayValue) +OptionProfile::OptionProfile(GameApp * _app, JGuiListener * jgl) : + OptionDirectory(JGE_GET_RES("profiles"), Options::ACTIVE_PROFILE, "Profile", DIRTESTER) { - Reload(); - initSelections(); -}; -bool OptionThemeStyle::Visible() { - return (selections.size() > 1); -}; -void OptionThemeStyle::confirmChange(bool confirmed){ - options.getStyleMan()->determineActive(NULL,NULL); + app = _app; + listener = jgl; + height = 60; + addSelection("Default"); + sort(selections.begin(), selections.end()); + mFocus = false; + initSelections(); + populate(); } -void OptionThemeStyle::Reload(){ +; + +void OptionProfile::initSelections() +{ + OptionSelect::initSelections(); + initialValue = value; +} + +void OptionProfile::addSelection(string s) +{ + OptionDirectory::addSelection(s); + + //Check how many options... if 1, we're not selectable. + if (selections.size() > 1) + canSelect = true; + else + canSelect = false; + +} + +void OptionProfile::updateValue() +{ + value++; + if (value > selections.size() - 1) + value = 0; + + populate(); +} + +void OptionProfile::Reload() +{ + OptionDirectory::Reload(); + populate(); +} + +void OptionProfile::populate() +{ + string temp = options[Options::ACTIVE_PROFILE].str; + if (value >= selections.size()) + { //TODO fail gracefully. + return; + } + options[Options::ACTIVE_PROFILE].str = selections[value]; + PlayerData * pdata = NEW PlayerData(app->collection); + + int unlocked = 0, sets = setlist.size(); + std::ifstream file(options.profileFile(PLAYER_SETTINGS).c_str()); + std::string s; + if (file) + { + while (std::getline(file, s)) + { + if (s.substr(0, 9) == "unlocked_") + unlocked++; + } + file.close(); + } + + options[Options::ACTIVE_PROFILE] = temp; + + char buf[512], format[512]; + sprintf(format, "%s\n%s\n%s\n", _("Credits: %i").c_str(), _("Cards: %i").c_str(), _("Sets: %i (of %i)").c_str()); + sprintf(buf, format, pdata->credits, pdata->collection->totalCards(), unlocked, sets); + preview = buf; + + SAFE_DELETE(pdata); +} + +void OptionProfile::Render() +{ + JRenderer * renderer = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetScale(1); + int spacing = 2 + (int) mFont->GetHeight(); + + float pX, pY; + pX = x; + pY = y; + char buf[512]; + if (selections[value] == "Default") + sprintf(buf, "player/avatar.jpg"); + else + sprintf(buf, "profiles/%s/avatar.jpg", selections[value].c_str()); + string filename = buf; + JQuad * mAvatar = resources.RetrieveTempQuad(filename, TEXTURE_SUB_EXACT); + + if (mAvatar) + { + renderer->RenderQuad(mAvatar, x, pY); + pX += 40; + } + + mFont->SetColor(getColor(WGuiColor::TEXT_HEADER)); + mFont->DrawString(selections[value].c_str(), pX, pY + 2, JGETEXT_LEFT); + mFont->SetScale(0.8f); + mFont->SetColor(getColor(WGuiColor::TEXT_BODY)); + mFont->DrawString(preview.c_str(), pX, pY + spacing + 2, JGETEXT_LEFT); + mFont->SetScale(1.0f); + +} + +void OptionProfile::Entering(JButton key) +{ + mFocus = true; + initialValue = value; +} + +void OptionProfile::confirmChange(bool confirmed) +{ + if (initialValue >= selections.size()) + return; + + int result; + + if (confirmed) + result = value; + else + result = initialValue; + + options[Options::ACTIVE_PROFILE] = selections[result]; + value = result; + + populate(); + if (listener && confirmed) + { + listener->ButtonPressed(-102, 5); + initialValue = value; + } + return; +} + +//OptionThemeStyle +OptionThemeStyle::OptionThemeStyle(string _displayValue) : + OptionSelect(Options::GUI_STYLE, _displayValue) +{ + Reload(); + initSelections(); +} + +bool OptionThemeStyle::Visible() +{ + return (selections.size() > 1); +} + +void OptionThemeStyle::confirmChange(bool confirmed) +{ + options.getStyleMan()->determineActive(NULL, NULL); +} + +void OptionThemeStyle::Reload() +{ selections.clear(); addSelection("Dynamic"); - map::iterator it; + map::iterator it; StyleManager * sm = options.getStyleMan(); - for(it=sm->styles.begin();it!=sm->styles.end();it++) + for (it = sm->styles.begin(); it != sm->styles.end(); it++) addSelection(it->first); } //OptionLanguage -OptionLanguage::OptionLanguage(string _displayValue) : OptionSelect(Options::LANG,_displayValue) +OptionLanguage::OptionLanguage(string _displayValue) : + OptionSelect(Options::LANG, _displayValue) { - Reload(); - initSelections(); -}; - -void OptionLanguage::setData(){ - if(id == INVALID_OPTION) return; - - if (value < selections.size()){ - options[id] = GameOption(actual_data[value]); - Translator::EndInstance(); - Translator::GetInstance()->init(); - Translator::GetInstance()->tempValues.clear(); - } + Reload(); + initSelections(); } -void OptionLanguage::confirmChange(bool confirmed){ - if(!confirmed) - value = prior_value; - else{ - setData(); - if(Changed()){ - options[id] = GameOption(actual_data[value]); - Translator::EndInstance(); - Translator::GetInstance()->init(); - Translator::GetInstance()->tempValues.clear(); +; + +void OptionLanguage::setData() +{ + if (id == INVALID_OPTION) + return; + + if (value < selections.size()) + { + options[id] = GameOption(actual_data[value]); + Translator::EndInstance(); + Translator::GetInstance()->init(); + Translator::GetInstance()->tempValues.clear(); } - prior_value = value; - } } -void OptionLanguage::Reload(){ - struct dirent *mDit; - DIR *mDip; - mDip = opendir(JGE_GET_RES("lang").c_str()); - - while ((mDit = readdir(mDip))){ - string filename = JGE_GET_RES("lang/"); - filename += mDit->d_name; - std::ifstream file(filename.c_str()); - string s; - string lang; - if(file){ - if(std::getline(file,s)){ - if (!s.size()){ - lang = ""; - }else{ - if (s[s.size()-1] == '\r') - s.erase(s.size()-1); //Handle DOS files - size_t found = s.find("#LANG:"); - if (found != 0) lang = ""; - else lang = s.substr(6); +void OptionLanguage::confirmChange(bool confirmed) +{ + if (!confirmed) + value = prior_value; + else + { + setData(); + if (Changed()) + { + options[id] = GameOption(actual_data[value]); + Translator::EndInstance(); + Translator::GetInstance()->init(); + Translator::GetInstance()->tempValues.clear(); } - } - file.close(); + prior_value = value; } +} - if (lang.size()){ - string filen = mDit->d_name; - addSelection(filen.substr(0,filen.size()-4),lang); +void OptionLanguage::Reload() +{ + struct dirent *mDit; + DIR *mDip; + + mDip = opendir(JGE_GET_RES("lang").c_str()); + + while ((mDit = readdir(mDip))) + { + string filename = JGE_GET_RES("lang/"); + filename += mDit->d_name; + std::ifstream file(filename.c_str()); + string s; + string lang; + if (file) + { + if (std::getline(file, s)) + { + if (!s.size()) + { + lang = ""; + } + else + { + if (s[s.size() - 1] == '\r') + s.erase(s.size() - 1); //Handle DOS files + size_t found = s.find("#LANG:"); + if (found != 0) + lang = ""; + else + lang = s.substr(6); + } + } + file.close(); + } + + if (lang.size()) + { + string filen = mDit->d_name; + addSelection(filen.substr(0, filen.size() - 4), lang); + } } - } - closedir(mDip); - initSelections(); + closedir(mDip); + initSelections(); } -void OptionLanguage::addSelection(string s,string show){ - selections.push_back(show); - actual_data.push_back(s); + +void OptionLanguage::addSelection(string s, string show) +{ + selections.push_back(show); + actual_data.push_back(s); } -void OptionLanguage::initSelections(){ - //Find currently active bit in the list. - for(size_t i=0;i 1) - return true; - return false; + +bool OptionLanguage::Visible() +{ + if (selections.size() > 1) + return true; + return false; } -bool OptionLanguage::Selectable(){ - if(selections.size() > 1) - return true; - return false; + +bool OptionLanguage::Selectable() +{ + if (selections.size() > 1) + return true; + return false; } + //OptionDirectory -void OptionDirectory::Reload(){ - DIR *mDip; - struct dirent *mDit; - char buf[PATH_MAX]; - mDip = opendir(root.c_str()); +void OptionDirectory::Reload() +{ + DIR *mDip; + struct dirent *mDit; + char buf[PATH_MAX]; + mDip = opendir(root.c_str()); - if (!mDip) return; + if (!mDip) + return; - while ((mDit = readdir(mDip))){ - sprintf(buf,"%s/%s/%s", root.c_str(), mDit->d_name, type.c_str()); - std::ifstream file(buf); - if (!file) continue; - file.close(); - if (find(selections.begin(), selections.end(), mDit->d_name) == selections.end()) - addSelection(mDit->d_name); - } + while ((mDit = readdir(mDip))) + { + sprintf(buf, "%s/%s/%s", root.c_str(), mDit->d_name, type.c_str()); + std::ifstream file(buf); + if (!file) + continue; + file.close(); + if (find(selections.begin(), selections.end(), mDit->d_name) == selections.end()) + addSelection(mDit->d_name); + } - closedir(mDip); - mDip = NULL; - initSelections(); + closedir(mDip); + mDip = NULL; + initSelections(); } -OptionDirectory::OptionDirectory(string root, int id, string displayValue, string type): OptionSelect(id, displayValue), root(root), type(type){ - DIR *mDip; - struct dirent *mDit; - char buf[PATH_MAX]; +OptionDirectory::OptionDirectory(string root, int id, string displayValue, string type) : + OptionSelect(id, displayValue), root(root), type(type) +{ + DIR *mDip; + struct dirent *mDit; + char buf[PATH_MAX]; - mDip = opendir(root.c_str()); - if(!mDip) return; + mDip = opendir(root.c_str()); + if (!mDip) + return; - while ((mDit = readdir(mDip))){ - sprintf(buf,"%s/%s/%s", root.c_str(), mDit->d_name, type.c_str()); - std::ifstream file(buf); - if (!file) continue; - file.close(); - addSelection(mDit->d_name); - } + while ((mDit = readdir(mDip))) + { + sprintf(buf, "%s/%s/%s", root.c_str(), mDit->d_name, type.c_str()); + std::ifstream file(buf); + if (!file) + continue; + file.close(); + addSelection(mDit->d_name); + } - closedir(mDip); - mDip = NULL; - initSelections(); + closedir(mDip); + mDip = NULL; + initSelections(); } const string OptionTheme::DIRTESTER = "preview.png"; -OptionTheme::OptionTheme(OptionThemeStyle * style) : OptionDirectory(JGE_GET_RES("themes"), Options::ACTIVE_THEME, "Current Theme", DIRTESTER){ - addSelection("Default"); - sort(selections.begin(),selections.end()); - initSelections(); - mFocus=false; - bChecked = false; - ts = style; -} -JQuad * OptionTheme::getImage(){ - char buf[512]; - string val = selections[value]; - if(val == "Default") - sprintf(buf,"graphics/preview.png"); - else - sprintf(buf,"themes/%s/preview.png",val.c_str()); - string filename = buf; - return resources.RetrieveTempQuad(filename,TEXTURE_SUB_EXACT); +OptionTheme::OptionTheme(OptionThemeStyle * style) : + OptionDirectory(JGE_GET_RES("themes"), Options::ACTIVE_THEME, "Current Theme", DIRTESTER) +{ + addSelection("Default"); + sort(selections.begin(), selections.end()); + initSelections(); + mFocus = false; + bChecked = false; + ts = style; } -float OptionTheme::getHeight(){ - return 130; -}; -void OptionTheme::updateValue(){ - OptionDirectory::updateValue(); - bChecked = false; -} - -void OptionTheme::Render(){ - JRenderer * renderer = JRenderer::GetInstance(); - char buf[512]; - if(!bChecked){ - author = ""; - bChecked = true; - if(selections[value] == "Default") - sprintf(buf,JGE_GET_RES("graphics/themeinfo.txt").c_str()); +JQuad * OptionTheme::getImage() +{ + char buf[512]; + string val = selections[value]; + if (val == "Default") + sprintf(buf, "graphics/preview.png"); else - sprintf(buf,JGE_GET_RES("themes/%s/themeinfo.txt").c_str(),selections[value].c_str()); - std::ifstream file(buf); - if(file){ - string temp; - std::getline(file,temp); - for(unsigned int x=0;x<17,xDrawString, cuts to 16 chars. - author += temp[x]; - } - file.close(); - } - } - sprintf(buf,_("Theme: %s").c_str(),selections[value].c_str()); - - JQuad * q = getImage(); - if(q){ - float scale = 128 / q->mHeight; - renderer->RenderQuad(q,x, y,0,scale,scale); - } - - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT_HEADER)); - mFont->DrawString(buf, x + 2, y + 2); - if(bChecked && author.size()){ - mFont->SetColor(getColor(WGuiColor::TEXT_BODY)); - mFont->SetScale(0.8f); - float hi = mFont->GetHeight(); - sprintf(buf,_("Artist: %s").c_str(),author.c_str()); - mFont->DrawString(buf, x + 2, y + getHeight() - hi); - mFont->SetScale(1); - } + sprintf(buf, "themes/%s/preview.png", val.c_str()); + string filename = buf; + return resources.RetrieveTempQuad(filename, TEXTURE_SUB_EXACT); } -bool OptionTheme::Visible(){ - if(selections.size() <= 1) - return false; - - return true; +float OptionTheme::getHeight() +{ + return 130; } -void OptionTheme::confirmChange(bool confirmed){ - bChecked = false; - if(!confirmed) - value = prior_value; - else{ - setData(); - options.getStyleMan()->loadRules(); - if(ts) ts->Reload(); - - resources.Refresh(); //Update images - prior_value = value; - } +void OptionTheme::updateValue() +{ + OptionDirectory::updateValue(); + bChecked = false; } -OptionKey::OptionKey(GameStateOptions* g, LocalKeySym from, JButton to) : WGuiItem(""), from(from), to(to), grabbed(false), g(g), btnMenu(NULL) {} - -void OptionKey::Update(float dt) { if (btnMenu) btnMenu->Update(dt); } -void OptionKey::Render() { - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT)); - JRenderer * renderer = JRenderer::GetInstance(); - - if (LOCAL_KEY_NONE == from) +void OptionTheme::Render() +{ + JRenderer * renderer = JRenderer::GetInstance(); + char buf[512]; + if (!bChecked) { - string msg = _("New binding..."); - mFont->DrawString(msg, (SCREEN_WIDTH - mFont->GetStringWidth(msg.c_str())) / 2, y + 2); - } - else - { - const KeyRep& rep = translateKey(from); - if (rep.second) - renderer->RenderQuad(rep.second, x + 4, y + 3, 0, 16.0f / rep.second->mHeight, 16.0f / rep.second->mHeight); - else - mFont->DrawString(rep.first, x + 4, y + 3, JGETEXT_LEFT); - const KeyRep& rep2 = translateKey(to); - if (rep2.second) + author = ""; + bChecked = true; + if (selections[value] == "Default") + sprintf(buf, JGE_GET_RES("graphics/themeinfo.txt").c_str()); + else + sprintf(buf, JGE_GET_RES("themes/%s/themeinfo.txt").c_str(), selections[value].c_str()); + std::ifstream file(buf); + if (file) { - float ratio = 16.0f / rep2.second->mHeight; - renderer->RenderQuad(rep2.second, x + width - (ratio * rep2.second->mWidth) - 2, y + 3, 0, ratio, ratio); + string temp; + std::getline(file, temp); + for (unsigned int x = 0; x < 17, x < temp.size(); x++) + { + if (isprint(temp[x])) //Clear stuff that breaks mFont->DrawString, cuts to 16 chars. + author += temp[x]; + } + file.close(); } - else - mFont->DrawString(rep2.first, width - 4, y + 3, JGETEXT_RIGHT); } -} -bool OptionKey::CheckUserInput(JButton key) { - if (btnMenu) - return btnMenu->CheckUserInput(key); - if (JGE_BTN_OK == key) { - grabbed = true; - g->GrabKeyboard(this); - return true; + sprintf(buf, _("Theme: %s").c_str(), selections[value].c_str()); + + JQuad * q = getImage(); + if (q) + { + float scale = 128 / q->mHeight; + renderer->RenderQuad(q, x, y, 0, scale, scale); + } + + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT_HEADER)); + mFont->DrawString(buf, x + 2, y + 2); + if (bChecked && author.size()) + { + mFont->SetColor(getColor(WGuiColor::TEXT_BODY)); + mFont->SetScale(0.8f); + float hi = mFont->GetHeight(); + sprintf(buf, _("Artist: %s").c_str(), author.c_str()); + mFont->DrawString(buf, x + 2, y + getHeight() - hi); + mFont->SetScale(1); } - return false; } -static const JButton btnList[] = {JGE_BTN_MENU, JGE_BTN_CTRL, JGE_BTN_RIGHT, - JGE_BTN_LEFT, JGE_BTN_UP, JGE_BTN_DOWN, - JGE_BTN_OK, JGE_BTN_CANCEL, JGE_BTN_PRI, - JGE_BTN_SEC, JGE_BTN_PREV, JGE_BTN_NEXT, +bool OptionTheme::Visible() +{ + if (selections.size() <= 1) + return false; + + return true; +} + +void OptionTheme::confirmChange(bool confirmed) +{ + bChecked = false; + if (!confirmed) + value = prior_value; + else + { + setData(); + options.getStyleMan()->loadRules(); + if (ts) + ts->Reload(); + + resources.Refresh(); //Update images + prior_value = value; + } +} + +OptionKey::OptionKey(GameStateOptions* g, LocalKeySym from, JButton to) : + WGuiItem(""), from(from), to(to), grabbed(false), g(g), btnMenu(NULL) +{ +} + +void OptionKey::Update(float dt) +{ + if (btnMenu) + btnMenu->Update(dt); +} +void OptionKey::Render() +{ + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT)); + JRenderer * renderer = JRenderer::GetInstance(); + + if (LOCAL_KEY_NONE == from) + { + string msg = _("New binding..."); + mFont->DrawString(msg, (SCREEN_WIDTH - mFont->GetStringWidth(msg.c_str())) / 2, y + 2); + } + else + { + const KeyRep& rep = translateKey(from); + if (rep.second) + renderer->RenderQuad(rep.second, x + 4, y + 3, 0, 16.0f / rep.second->mHeight, 16.0f / rep.second->mHeight); + else + mFont->DrawString(rep.first, x + 4, y + 3, JGETEXT_LEFT); + const KeyRep& rep2 = translateKey(to); + if (rep2.second) + { + float ratio = 16.0f / rep2.second->mHeight; + renderer->RenderQuad(rep2.second, x + width - (ratio * rep2.second->mWidth) - 2, y + 3, 0, ratio, ratio); + } + else + mFont->DrawString(rep2.first, width - 4, y + 3, JGETEXT_RIGHT); + } +} + +bool OptionKey::CheckUserInput(JButton key) +{ + if (btnMenu) + return btnMenu->CheckUserInput(key); + if (JGE_BTN_OK == key) + { + grabbed = true; + g->GrabKeyboard(this); + return true; + } + return false; +} + +static const JButton btnList[] = +{ + JGE_BTN_MENU, + JGE_BTN_CTRL, + JGE_BTN_RIGHT, + JGE_BTN_LEFT, + JGE_BTN_UP, + JGE_BTN_DOWN, + JGE_BTN_OK, + JGE_BTN_CANCEL, + JGE_BTN_PRI, + JGE_BTN_SEC, + JGE_BTN_PREV, + JGE_BTN_NEXT, #ifdef LINUX - JGE_BTN_FULLSCREEN, + JGE_BTN_FULLSCREEN, #endif - JGE_BTN_NONE}; -void OptionKey::KeyPressed(LocalKeySym key) { - from = key; - g->UngrabKeyboard(this); - grabbed = false; + JGE_BTN_NONE +}; - btnMenu = NEW SimpleMenu(0, this, Fonts::MENU_FONT, 80, 10); - for (int i = sizeof(btnList) / sizeof(btnList[0]) - 1; i >= 0; --i) { - const KeyRep& rep = translateKey(btnList[i]); - btnMenu->Add(i, rep.first.c_str()); +void OptionKey::KeyPressed(LocalKeySym key) +{ + from = key; + g->UngrabKeyboard(this); + grabbed = false; + + btnMenu = NEW SimpleMenu(0, this, Fonts::MENU_FONT, 80, 10); + for (int i = sizeof(btnList) / sizeof(btnList[0]) - 1; i >= 0; --i) + { + const KeyRep& rep = translateKey(btnList[i]); + btnMenu->Add(i, rep.first.c_str()); } } -bool OptionKey::isModal() { return grabbed || btnMenu; } +bool OptionKey::isModal() +{ + return grabbed || btnMenu; +} + void OptionKey::Overlay() { - JRenderer * renderer = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(ARGB(255, 0, 0, 0)); - if (grabbed) { - static const float x = 30, y = 45; - renderer->FillRoundRect(x, y, SCREEN_WIDTH - 2*x, 50, 2, ARGB(200, 200, 200, 255)); - string msg = _("Press a key to associate."); - mFont->DrawString(msg, (SCREEN_WIDTH - mFont->GetStringWidth(msg.c_str())) / 2, y + 20); - } - else if (btnMenu) - btnMenu->Render(); + JRenderer * renderer = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(ARGB(255, 0, 0, 0)); + if (grabbed) + { + static const float x = 30, y = 45; + renderer->FillRoundRect(x, y, SCREEN_WIDTH - 2 * x, 50, 2, ARGB(200, 200, 200, 255)); + string msg = _("Press a key to associate."); + mFont->DrawString(msg, (SCREEN_WIDTH - mFont->GetStringWidth(msg.c_str())) / 2, y + 20); + } + else if (btnMenu) + btnMenu->Render(); } -void OptionKey::ButtonPressed(int controllerId, int controlId) { - to = btnList[controlId]; - SAFE_DELETE(btnMenu); - btnMenu = NULL; + +void OptionKey::ButtonPressed(int controllerId, int controlId) +{ + to = btnList[controlId]; + SAFE_DELETE(btnMenu); + btnMenu = NULL; +} + +bool OptionKey::Visible() +{ + return JGE_BTN_NONE != to || LOCAL_KEY_NONE == from || btnMenu != NULL; +} + +bool OptionKey::Selectable() +{ + return JGE_BTN_NONE != to || LOCAL_KEY_NONE == from || btnMenu != NULL; } -bool OptionKey::Visible() { return JGE_BTN_NONE != to || LOCAL_KEY_NONE == from || btnMenu != NULL; } -bool OptionKey::Selectable() { return JGE_BTN_NONE != to || LOCAL_KEY_NONE == from || btnMenu != NULL; } diff --git a/projects/mtg/src/PhaseRing.cpp b/projects/mtg/src/PhaseRing.cpp index 204d7d189..9bfda1b83 100644 --- a/projects/mtg/src/PhaseRing.cpp +++ b/projects/mtg/src/PhaseRing.cpp @@ -5,132 +5,154 @@ #include "Player.h" #include "WEvent.h" - //Parses a string and gives phase numer -int PhaseRing::phaseStrToInt(string s){ - if (s.compare("untap") == 0) return Constants::MTG_PHASE_UNTAP; - if (s.compare("upkeep") == 0)return Constants::MTG_PHASE_UPKEEP; - if (s.compare("draw") == 0)return Constants::MTG_PHASE_DRAW; - if (s.compare("firstmain") == 0)return Constants::MTG_PHASE_FIRSTMAIN; - if (s.compare("combatbegin") == 0)return Constants::MTG_PHASE_COMBATBEGIN; - if (s.compare("combatattackers") == 0)return Constants::MTG_PHASE_COMBATATTACKERS; - if (s.compare("combatblockers") == 0)return Constants::MTG_PHASE_COMBATBLOCKERS; - if (s.compare("combatdamage") == 0)return Constants::MTG_PHASE_COMBATDAMAGE; - if (s.compare("combatend") == 0)return Constants::MTG_PHASE_COMBATEND; - if (s.compare("secondmain") == 0)return Constants::MTG_PHASE_SECONDMAIN; - if (s.compare("endofturn") == 0)return Constants::MTG_PHASE_ENDOFTURN; - if (s.compare("cleanup") == 0)return Constants::MTG_PHASE_CLEANUP; - DebugTrace("PHASERING: Unknown Phase name: " << s); +int PhaseRing::phaseStrToInt(string s) +{ + if (s.compare("untap") == 0) return Constants::MTG_PHASE_UNTAP; + if (s.compare("upkeep") == 0) return Constants::MTG_PHASE_UPKEEP; + if (s.compare("draw") == 0) return Constants::MTG_PHASE_DRAW; + if (s.compare("firstmain") == 0) return Constants::MTG_PHASE_FIRSTMAIN; + if (s.compare("combatbegin") == 0) return Constants::MTG_PHASE_COMBATBEGIN; + if (s.compare("combatattackers") == 0) return Constants::MTG_PHASE_COMBATATTACKERS; + if (s.compare("combatblockers") == 0) return Constants::MTG_PHASE_COMBATBLOCKERS; + if (s.compare("combatdamage") == 0) return Constants::MTG_PHASE_COMBATDAMAGE; + if (s.compare("combatend") == 0) return Constants::MTG_PHASE_COMBATEND; + if (s.compare("secondmain") == 0) return Constants::MTG_PHASE_SECONDMAIN; + if (s.compare("endofturn") == 0) return Constants::MTG_PHASE_ENDOFTURN; + if (s.compare("cleanup") == 0) return Constants::MTG_PHASE_CLEANUP; + DebugTrace("PHASERING: Unknown Phase name: " << s); - return Constants::MTG_PHASE_FIRSTMAIN; + return Constants::MTG_PHASE_FIRSTMAIN; } /* Creates a New phase ring with the default rules */ -PhaseRing::PhaseRing(Player* players[], int nbPlayers){ - for (int i = 0; i < nbPlayers; i++){ - for (int j = 0; j < Constants::NB_MTG_PHASES; j++){ - Phase * phase = NEW Phase(j,players[i]); - addPhase(phase); +PhaseRing::PhaseRing(Player* players[], int nbPlayers) +{ + for (int i = 0; i < nbPlayers; i++) + { + for (int j = 0; j < Constants::NB_MTG_PHASES; j++) + { + Phase * phase = NEW Phase(j, players[i]); + addPhase(phase); + } } - } - current = ring.begin(); + current = ring.begin(); } -PhaseRing::~PhaseRing(){ - list::iterator it; - for (it = ring.begin(); it != ring.end(); it++){ - Phase * currentPhase = *it; - delete(currentPhase); - } +PhaseRing::~PhaseRing() +{ + list::iterator it; + for (it = ring.begin(); it != ring.end(); it++) + { + Phase * currentPhase = *it; + delete (currentPhase); + } } //Tells if next phase will be another Damage phase rather than combat ends -bool PhaseRing::extraDamagePhase(int id){ - GameObserver * g = GameObserver::GetInstance(); - if (id != Constants::MTG_PHASE_COMBATEND) return false; - if (g->combatStep != END_FIRST_STRIKE) return false; - for (int j = 0; j < 2; ++j){ - MTGGameZone * z = g->players[j]->game->inPlay; - for (int i= 0; i < z->nb_cards; ++i){ - MTGCardInstance * card = z->cards[i]; - if ((card->isAttacker() || card->isDefenser()) && !(card->has(Constants::FIRSTSTRIKE) || card->has(Constants::DOUBLESTRIKE))) return true; +bool PhaseRing::extraDamagePhase(int id) +{ + GameObserver * g = GameObserver::GetInstance(); + if (id != Constants::MTG_PHASE_COMBATEND) return false; + if (g->combatStep != END_FIRST_STRIKE) return false; + for (int j = 0; j < 2; ++j) + { + MTGGameZone * z = g->players[j]->game->inPlay; + for (int i = 0; i < z->nb_cards; ++i) + { + MTGCardInstance * card = z->cards[i]; + if ((card->isAttacker() || card->isDefenser()) && !(card->has(Constants::FIRSTSTRIKE) || card->has( + Constants::DOUBLESTRIKE))) return true; + } } - } - return false; + return false; } -const char * PhaseRing::phaseName(int id){ - if (extraDamagePhase(id)) return "Combat Damage (2)"; - return Constants::MTGPhaseNames[id]; +const char * PhaseRing::phaseName(int id) +{ + if (extraDamagePhase(id)) return "Combat Damage (2)"; + return Constants::MTGPhaseNames[id]; } - - -Phase * PhaseRing::getCurrentPhase(){ - if (current == ring.end()){ - current = ring.begin(); - } - return *current; -} - -Phase * PhaseRing::forward(bool sendEvents){ - Phase * cPhaseOld = *current; - if (current != ring.end()) current++; - if (current == ring.end()) current = ring.begin(); - - if (sendEvents) { - //Warn the layers about the phase Change - WEvent * e = NEW WEventPhaseChange(cPhaseOld, *current); - GameObserver::GetInstance()->receiveEvent(e); - } - - return *current; -} - -Phase * PhaseRing::goToPhase(int id, Player * player, bool sendEvents){ - Phase * currentPhase = *current; - while(currentPhase->id !=id || currentPhase->player != player){ //Dangerous, risk for inifinte loop ! - - DebugTrace("PhasingRing: goToPhase called, current phase is " << phaseName(currentPhase->id)); - - currentPhase = forward(sendEvents); - } - return currentPhase; -} - - -int PhaseRing::addPhase(Phase * phase){ - ring.push_back(phase); - return 1; -} - -int PhaseRing::addPhaseBefore(int id, Player* player,int after_id, Player * after_player, int allOccurences){ - int result = 0; - list::iterator it; - for (it = ring.begin(); it != ring.end(); it++){ - Phase * currentPhase = *it; - if (currentPhase->id == after_id && currentPhase->player == after_player){ - result++; - ring.insert(it,NEW Phase(id,player)); - if (!allOccurences) return 1; +Phase * PhaseRing::getCurrentPhase() +{ + if (current == ring.end()) + { + current = ring.begin(); } - } - return result; + return *current; } -int PhaseRing::removePhase (int id, Player * player, int allOccurences){ - int result = 0; - list::iterator it = ring.begin(); - while (it != ring.end()){ - Phase * currentPhase = *it; - if (currentPhase->id == id && currentPhase->player == player){ - if (current == it) current++; //Avoid our cursor to get invalidated - it = ring.erase(it); - delete(currentPhase); - result++; - if (!allOccurences) return 1; - }else{ - it++; + +Phase * PhaseRing::forward(bool sendEvents) +{ + Phase * cPhaseOld = *current; + if (current != ring.end()) current++; + if (current == ring.end()) current = ring.begin(); + + if (sendEvents) + { + //Warn the layers about the phase Change + WEvent * e = NEW WEventPhaseChange(cPhaseOld, *current); + GameObserver::GetInstance()->receiveEvent(e); } - } - return result; + + return *current; +} + +Phase * PhaseRing::goToPhase(int id, Player * player, bool sendEvents) +{ + Phase * currentPhase = *current; + while (currentPhase->id != id || currentPhase->player != player) + { //Dangerous, risk for inifinte loop ! + + DebugTrace("PhasingRing: goToPhase called, current phase is " << phaseName(currentPhase->id)); + + currentPhase = forward(sendEvents); + } + return currentPhase; +} + +int PhaseRing::addPhase(Phase * phase) +{ + ring.push_back(phase); + return 1; +} + +int PhaseRing::addPhaseBefore(int id, Player* player, int after_id, Player * after_player, int allOccurences) +{ + int result = 0; + list::iterator it; + for (it = ring.begin(); it != ring.end(); it++) + { + Phase * currentPhase = *it; + if (currentPhase->id == after_id && currentPhase->player == after_player) + { + result++; + ring.insert(it, NEW Phase(id, player)); + if (!allOccurences) return 1; + } + } + return result; +} +int PhaseRing::removePhase(int id, Player * player, int allOccurences) +{ + int result = 0; + list::iterator it = ring.begin(); + while (it != ring.end()) + { + Phase * currentPhase = *it; + if (currentPhase->id == id && currentPhase->player == player) + { + if (current == it) current++; //Avoid our cursor to get invalidated + it = ring.erase(it); + delete (currentPhase); + result++; + if (!allOccurences) return 1; + } + else + { + it++; + } + } + return result; } diff --git a/projects/mtg/src/PlayGuiObject.cpp b/projects/mtg/src/PlayGuiObject.cpp index 19900a3d8..02939ec4c 100644 --- a/projects/mtg/src/PlayGuiObject.cpp +++ b/projects/mtg/src/PlayGuiObject.cpp @@ -4,45 +4,47 @@ using namespace std; -PlayGuiObject::PlayGuiObject(float desiredHeight, float x, float y, bool hasFocus) : JGuiObject(0), Pos(x, y, 1.0, 0.0, 255) { - defaultHeight = desiredHeight; - mHeight = desiredHeight; - mHasFocus = hasFocus; - type = 0; - wave = 0; +PlayGuiObject::PlayGuiObject(float desiredHeight, float x, float y, bool hasFocus) : + JGuiObject(0), Pos(x, y, 1.0, 0.0, 255) +{ + defaultHeight = desiredHeight; + mHeight = desiredHeight; + mHasFocus = hasFocus; + type = 0; + wave = 0; } -PlayGuiObject::PlayGuiObject(float desiredHeight, const Pos& ref, bool hasFocus) : JGuiObject(0), Pos(ref) { - defaultHeight = desiredHeight; - mHeight = desiredHeight; - mHasFocus = hasFocus; - type = 0; - wave = 0; +PlayGuiObject::PlayGuiObject(float desiredHeight, const Pos& ref, bool hasFocus) : + JGuiObject(0), Pos(ref) +{ + defaultHeight = desiredHeight; + mHeight = desiredHeight; + mHasFocus = hasFocus; + type = 0; + wave = 0; } +void PlayGuiObject::Update(float dt) +{ + if (mHasFocus && mHeight < defaultHeight * 1.2) + { + mHeight += defaultHeight * 0.8f * dt; + // fprintf(stderr, "increasing size to %f - %d", mHeight, GetId() ); -void PlayGuiObject::Update(float dt){ - if (mHasFocus && mHeight < defaultHeight * 1.2) - { - mHeight += defaultHeight * 0.8f * dt; - // fprintf(stderr, "increasing size to %f - %d", mHeight, GetId() ); - - if (mHeight > defaultHeight * 1.2f) - mHeight = defaultHeight * 1.2f; - } - else if (!mHasFocus && mHeight > defaultHeight) - { - mHeight -= defaultHeight * 0.8f * dt; - if (mHeight < defaultHeight) - mHeight = defaultHeight; - } - wave = (wave +2 * (int) (100 * dt) ) % 255; - for (vector::iterator it = effects.begin(); it != effects.end(); ++it) - (*it)->Update(dt); - Pos::Update(dt); + if (mHeight > defaultHeight * 1.2f) mHeight = defaultHeight * 1.2f; + } + else if (!mHasFocus && mHeight > defaultHeight) + { + mHeight -= defaultHeight * 0.8f * dt; + if (mHeight < defaultHeight) mHeight = defaultHeight; + } + wave = (wave + 2 * (int) (100 * dt)) % 255; + for (vector::iterator it = effects.begin(); it != effects.end(); ++it) + (*it)->Update(dt); + Pos::Update(dt); } void PlayGuiObject::Render() { - for (vector::iterator it = effects.begin(); it != effects.end(); ++it) - (*it)->Render(); + for (vector::iterator it = effects.begin(); it != effects.end(); ++it) + (*it)->Render(); } diff --git a/projects/mtg/src/PlayGuiObjectController.cpp b/projects/mtg/src/PlayGuiObjectController.cpp index c8d91d178..379164330 100644 --- a/projects/mtg/src/PlayGuiObjectController.cpp +++ b/projects/mtg/src/PlayGuiObjectController.cpp @@ -7,149 +7,161 @@ int PlayGuiObjectController::showBigCards = 1; -int PlayGuiObjectController::getClosestItem(int direction){ - return getClosestItem(direction, 35); +int PlayGuiObjectController::getClosestItem(int direction) +{ + return getClosestItem(direction, 35); } - -int PlayGuiObjectController::getClosestItem(int direction, float tolerance){ - if (mCount == 0){ - return -1; - } - if (mCount == 1){ - return mCurr; - } - - float maxDist = SCREEN_WIDTH * SCREEN_WIDTH; - PlayGuiObject * current = (PlayGuiObject *)mObjects[mCurr]; - int closest_match = -1; - int available = 0; - float x0, y0, x1, y1; - x0 = current->x; - y0 = current->y; - for (int i=0;ix; - y1 = other->y; - float dist = (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1); - if (dist>=maxDist) continue; - //Potential match ! - int ok = 0; - switch(direction){ - case DIR_DOWN: - if (y1 > y0){ - available = 1; - if (fabs(x0-x1) < tolerance ) ok = 1; - } - break; - case DIR_UP: - if (y1 < y0){ - available = 1; - if (fabs(x0-x1) < tolerance ) ok = 1; - } - break; - case DIR_LEFT: - if (x1 < x0){ - available = 1; - if (fabs(y0-y1) < tolerance ) ok = 1; - } - break; - case DIR_RIGHT: - if (x1 > x0){ - available = 1; - if (fabs(y0-y1) < tolerance ) ok = 1; - } - break; - } - if (ok){ - closest_match = i; - maxDist = dist; - } - } - if (closest_match == -1){ - if (available) return getClosestItem(direction,tolerance+5); - return mCurr; - } - return closest_match; -} - - - -void PlayGuiObjectController::Update(float dt){ - last_user_move +=dt; - for (int i=0;iUpdate(dt); - } - } -} - - -bool PlayGuiObjectController::CheckUserInput(JButton key){ - /* - if (!mCount) - return false; - if (game != NULL){ - if (mActionButton == key){ - if (mObjects[mCurr] != NULL && mObjects[mCurr]->ButtonPressed()){ - game->ButtonPressed(mId, (PlayGuiObject *)mObjects[mCurr]); - return true; - } - } - if (PSP_CTRL_CROSS == key){ - game->cancelCurrentAction(); - return true; - } - } - - last_user_move = 0; - switch (key) +int PlayGuiObjectController::getClosestItem(int direction, float tolerance) +{ + if (mCount == 0) { - case PSP_CTRL_LEFT: - { - int n = getClosestItem(DIR_LEFT); - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_LEFT)) - { - mCurr = n; - mObjects[mCurr]->Entering(); - } - return true; - } - case PSP_CTRL_RIGHT: - { - int n = getClosestItem(DIR_RIGHT); - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_RIGHT)) - { - mCurr = n; - mObjects[mCurr]->Entering(); - } - return true; - } - case PSP_CTRL_UP: - { - int n = getClosestItem(DIR_UP); - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_UP)) - { - mCurr = n; - mObjects[mCurr]->Entering(); - } - return true; - } - case PSP_CTRL_DOWN: - { - int n = getClosestItem(DIR_DOWN); - if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN)) - { - mCurr = n; - mObjects[mCurr]->Entering(); - } - return true; - } - case PSP_CTRL_TRIANGLE: - showBigCards = (showBigCards + 1) % 3; - return true; + return -1; } - */ - return false; + if (mCount == 1) + { + return mCurr; + } + + float maxDist = SCREEN_WIDTH * SCREEN_WIDTH; + PlayGuiObject * current = (PlayGuiObject *) mObjects[mCurr]; + int closest_match = -1; + int available = 0; + float x0, y0, x1, y1; + x0 = current->x; + y0 = current->y; + for (int i = 0; i < mCount; i++) + { + if (i == mCurr) continue; + PlayGuiObject * other = (PlayGuiObject *) mObjects[i]; + x1 = other->x; + y1 = other->y; + float dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1); + if (dist >= maxDist) continue; + //Potential match ! + int ok = 0; + switch (direction) + { + case DIR_DOWN: + if (y1 > y0) + { + available = 1; + if (fabs(x0 - x1) < tolerance) ok = 1; + } + break; + case DIR_UP: + if (y1 < y0) + { + available = 1; + if (fabs(x0 - x1) < tolerance) ok = 1; + } + break; + case DIR_LEFT: + if (x1 < x0) + { + available = 1; + if (fabs(y0 - y1) < tolerance) ok = 1; + } + break; + case DIR_RIGHT: + if (x1 > x0) + { + available = 1; + if (fabs(y0 - y1) < tolerance) ok = 1; + } + break; + } + if (ok) + { + closest_match = i; + maxDist = dist; + } + } + if (closest_match == -1) + { + if (available) return getClosestItem(direction, tolerance + 5); + return mCurr; + } + return closest_match; +} + +void PlayGuiObjectController::Update(float dt) +{ + last_user_move += dt; + for (int i = 0; i < mCount; i++) + { + if (mObjects[i] != NULL) + { + mObjects[i]->Update(dt); + } + } +} + +bool PlayGuiObjectController::CheckUserInput(JButton key) +{ + /* + if (!mCount) + return false; + if (game != NULL){ + if (mActionButton == key){ + if (mObjects[mCurr] != NULL && mObjects[mCurr]->ButtonPressed()){ + game->ButtonPressed(mId, (PlayGuiObject *)mObjects[mCurr]); + return true; + } + } + if (PSP_CTRL_CROSS == key){ + game->cancelCurrentAction(); + return true; + } + } + + last_user_move = 0; + switch (key) + { + case PSP_CTRL_LEFT: + { + int n = getClosestItem(DIR_LEFT); + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_LEFT)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + return true; + } + case PSP_CTRL_RIGHT: + { + int n = getClosestItem(DIR_RIGHT); + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_RIGHT)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + return true; + } + case PSP_CTRL_UP: + { + int n = getClosestItem(DIR_UP); + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_UP)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + return true; + } + case PSP_CTRL_DOWN: + { + int n = getClosestItem(DIR_DOWN); + if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN)) + { + mCurr = n; + mObjects[mCurr]->Entering(); + } + return true; + } + case PSP_CTRL_TRIANGLE: + showBigCards = (showBigCards + 1) % 3; + return true; + } + */ + return false; } diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index 22aa1e1ca..1d59464f5 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -5,122 +5,137 @@ #include "DeckStats.h" #include "ManaCost.h" - - - -Player::Player(MTGDeck * deck, string file, string fileSmall) : Damageable(20){ - deckFile = file; - deckFileSmall = fileSmall; - manaPool = NEW ManaPool(this); - canPutLandsIntoPlay = 1; - nomaxhandsize = 0; - castedspellsthisturn = 0; - castrestrictedspell = 0; - castrestrictedcreature = 0; - onlyonecast = 0; - castcount = 0; - nocreatureinstant = 0; - nospellinstant = 0; - onlyoneinstant = 0; - poisonCount = 0; - damageCount = 0; - preventable = 0; - mAvatar = NULL; - mAvatarTex = NULL; - type_as_damageable = DAMAGEABLE_PLAYER; - playMode = MODE_HUMAN; - if ( deck != NULL ) - { - game = NEW MTGPlayerCards( deck ); - game->setOwner(this); - deckName = deck->meta_name; - } +Player::Player(MTGDeck * deck, string file, string fileSmall) : + Damageable(20) +{ + deckFile = file; + deckFileSmall = fileSmall; + manaPool = NEW ManaPool(this); + canPutLandsIntoPlay = 1; + nomaxhandsize = 0; + castedspellsthisturn = 0; + castrestrictedspell = 0; + castrestrictedcreature = 0; + onlyonecast = 0; + castcount = 0; + nocreatureinstant = 0; + nospellinstant = 0; + onlyoneinstant = 0; + poisonCount = 0; + damageCount = 0; + preventable = 0; + mAvatar = NULL; + mAvatarTex = NULL; + type_as_damageable = DAMAGEABLE_PLAYER; + playMode = MODE_HUMAN; + if (deck != NULL) + { + game = NEW MTGPlayerCards(deck); + game->setOwner(this); + deckName = deck->meta_name; + } } /*Method to call at the end of a game, before all objects involved in the game are destroyed */ -void Player::End(){ - DeckStats::GetInstance()->saveStats(this, opponent(),GameObserver::GetInstance()); +void Player::End() +{ + DeckStats::GetInstance()->saveStats(this, opponent(), GameObserver::GetInstance()); } -Player::~Player(){ - SAFE_DELETE(manaPool); - SAFE_DELETE(game); - resources.Release(mAvatarTex); - mAvatar = NULL; - mAvatarTex = NULL; -} - -void Player::loadAvatar(string file){ - if (mAvatarTex) { +Player::~Player() +{ + SAFE_DELETE(manaPool); + SAFE_DELETE(game); resources.Release(mAvatarTex); mAvatar = NULL; mAvatarTex = NULL; - } - mAvatarTex = resources.RetrieveTexture(file,RETRIEVE_LOCK,TEXTURE_SUB_AVATAR); - if (mAvatarTex) - mAvatar = resources.RetrieveQuad(file,0,0,35,50,"playerAvatar",RETRIEVE_NORMAL,TEXTURE_SUB_AVATAR); - else - mAvatar = NULL; } -const string Player::getDisplayName() const { - GameObserver * g = GameObserver::GetInstance(); - if (this == g->players[0]) return "Player 1"; - return "Player 2"; +void Player::loadAvatar(string file) +{ + if (mAvatarTex) + { + resources.Release(mAvatarTex); + mAvatar = NULL; + mAvatarTex = NULL; + } + mAvatarTex = resources.RetrieveTexture(file, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR); + if (mAvatarTex) + mAvatar = resources.RetrieveQuad(file, 0, 0, 35, 50, "playerAvatar", RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR); + else + mAvatar = NULL; } -MTGInPlay * Player::inPlay(){ - return game->inPlay; +const string Player::getDisplayName() const +{ + GameObserver * g = GameObserver::GetInstance(); + if (this == g->players[0]) return "Player 1"; + return "Player 2"; } -int Player::getId(){ - GameObserver * game = GameObserver::GetInstance(); - for (int i= 0; i < 2; i++){ - if (game->players[i] == this) return i; - } - return -1; +MTGInPlay * Player::inPlay() +{ + return game->inPlay; } -JQuad * Player::getIcon(){ - return mAvatar; +int Player::getId() +{ + GameObserver * game = GameObserver::GetInstance(); + for (int i = 0; i < 2; i++) + { + if (game->players[i] == this) return i; + } + return -1; } -Player * Player::opponent(){ - GameObserver * game = GameObserver::GetInstance(); - if (!game) return NULL; - return this == game->players[0] ? game->players[1] : game->players[0]; +JQuad * Player::getIcon() +{ + return mAvatar; } - -HumanPlayer::HumanPlayer(MTGDeck * deck, string file, string fileSmall) : Player(deck, file, fileSmall) { - loadAvatar("avatar.jpg"); - playMode = MODE_HUMAN; +Player * Player::opponent() +{ + GameObserver * game = GameObserver::GetInstance(); + if (!game) return NULL; + return this == game->players[0] ? game->players[1] : game->players[0]; } - -ManaPool * Player::getManaPool(){ - return manaPool; +HumanPlayer::HumanPlayer(MTGDeck * deck, string file, string fileSmall) : + Player(deck, file, fileSmall) +{ + loadAvatar("avatar.jpg"); + playMode = MODE_HUMAN; } -int Player::afterDamage(){ - return life; +ManaPool * Player::getManaPool() +{ + return manaPool; } -int Player::poisoned(){ - return poisonCount; + +int Player::afterDamage() +{ + return life; } -int Player::damaged(){ - return damageCount; +int Player::poisoned() +{ + return poisonCount; } -int Player::prevented(){ - return preventable; +int Player::damaged() +{ + return damageCount; +} +int Player::prevented() +{ + return preventable; } //Cleanup phase at the end of a turn -void Player::cleanupPhase(){ - game->inPlay->cleanupPhase(); - game->graveyard->cleanupPhase(); +void Player::cleanupPhase() +{ + game->inPlay->cleanupPhase(); + game->graveyard->cleanupPhase(); } ostream& operator<<(ostream& out, const Player& p) { - return out << p.getDisplayName(); + return out << p.getDisplayName(); } diff --git a/projects/mtg/src/PlayerData.cpp b/projects/mtg/src/PlayerData.cpp index 6e202f576..393a45311 100644 --- a/projects/mtg/src/PlayerData.cpp +++ b/projects/mtg/src/PlayerData.cpp @@ -5,79 +5,87 @@ #include -PlayerData::PlayerData(){ - init(); -} -PlayerData::PlayerData(MTGAllCards * allcards){ - init(); - - //COLLECTION - if (allcards) collection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), allcards); +PlayerData::PlayerData() +{ + init(); } -void PlayerData::init() { - collection = NULL; +PlayerData::PlayerData(MTGAllCards * allcards) +{ + init(); - //CREDITS - credits = 3000; //Default value + //COLLECTION + if (allcards) collection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), allcards); +} - std::ifstream file(options.profileFile(PLAYER_SAVEFILE).c_str()); - std::string s; - if(file){ - if(std::getline(file,s)){ - credits = atoi(s.c_str()); - }else{ - //TODO error management +void PlayerData::init() +{ + collection = NULL; + + //CREDITS + credits = 3000; //Default value + + std::ifstream file(options.profileFile(PLAYER_SAVEFILE).c_str()); + std::string s; + if (file) + { + if (std::getline(file, s)) + { + credits = atoi(s.c_str()); + } + else + { + //TODO error management + } + + //Story Saves + while (std::getline(file, s)) + { + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + if (s.size() && s[0] == '#') continue; + size_t i = s.find_first_of("="); + if (i == string::npos) continue; + + string key = s.substr(0, i); + string value = s.substr(i + 1); + if (key.size() < 3) continue; + + if (key[0] != 's') continue; + key = key.substr(2); + storySaves[key] = value; + } + file.close(); } - //Story Saves - while(std::getline(file,s)){ - if (!s.size()) - continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - if (s.size() && s[0] == '#') - continue; - size_t i = s.find_first_of("="); - if (i == string::npos) - continue; + taskList = NEW TaskList(options.profileFile(PLAYER_TASKS).c_str()); +} - string key = s.substr(0,i); - string value = s.substr(i+1); - if (key.size() < 3) - continue; +int PlayerData::save() +{ + std::ofstream file(options.profileFile(PLAYER_SAVEFILE).c_str()); + char writer[512]; + if (file) + { + sprintf(writer, "%i\n", credits); + file << writer; - if(key[0] != 's') - continue; - key = key.substr(2); - storySaves[key]=value; + //Story Saves + for (map::iterator it = storySaves.begin(); it != storySaves.end(); ++it) + { + sprintf(writer, "s %s=%s\n", it->first.c_str(), it->second.c_str()); + file << writer; + } + + file.close(); } - file.close(); - } - - taskList = NEW TaskList(options.profileFile(PLAYER_TASKS).c_str()); + if (collection) collection->save(); + taskList->save(); + return 1; } -int PlayerData::save(){ - std::ofstream file(options.profileFile(PLAYER_SAVEFILE).c_str()); - char writer[512]; - if (file){ - sprintf(writer,"%i\n", credits); - file<::iterator it =storySaves.begin(); it !=storySaves.end(); ++it){ - sprintf(writer,"s %s=%s\n", it->first.c_str(),it->second.c_str()); - file << writer; - } - - file.close(); - } - if (collection) collection->save(); - taskList->save(); - return 1; -} - -PlayerData::~PlayerData(){ - SAFE_DELETE(collection); - SAFE_DELETE(taskList); +PlayerData::~PlayerData() +{ + SAFE_DELETE(collection); + SAFE_DELETE(taskList); } diff --git a/projects/mtg/src/Pos.cpp b/projects/mtg/src/Pos.cpp index 85a3907b9..d8f952fd3 100644 --- a/projects/mtg/src/Pos.cpp +++ b/projects/mtg/src/Pos.cpp @@ -3,25 +3,33 @@ #include "JRenderer.h" #include "Pos.h" -Pos::Pos(float x, float y, float z, float t, float a) : actX(x), actY(y), actZ(z), actT(t), actA(a), x(x), y(y), zoom(z), t(t), alpha(a) {} +Pos::Pos(float x, float y, float z, float t, float a) : + actX(x), actY(y), actZ(z), actT(t), actA(a), x(x), y(y), zoom(z), t(t), alpha(a) +{ +} void Pos::Update(float dt) { - if (dt > 0.05f) - dt = 0.05f; - actX += 10 * dt * (x - actX); - actY += 10 * dt * (y - actY); - actT += 10 * dt * (t - actT); - actZ += 10 * dt * (zoom - actZ); - actA += 10 * dt * (alpha - actA); + if (dt > 0.05f) dt = 0.05f; + actX += 10 * dt * (x - actX); + actY += 10 * dt * (y - actY); + actT += 10 * dt * (t - actT); + actZ += 10 * dt * (zoom - actZ); + actA += 10 * dt * (alpha - actA); } void Pos::UpdateNow() { - actX = x; actY = y; actT = t; actZ = zoom; actA = alpha; + actX = x; + actY = y; + actT = t; + actZ = zoom; + actA = alpha; +} +void Pos::Render() +{ } -void Pos::Render(){} void Pos::Render(JQuad* quad) { - quad->SetColor(ARGB((int)actA, 255, 255, 255)); - JRenderer::GetInstance()->RenderQuad(quad, actX, actY, actT, actZ, actZ); + quad->SetColor(ARGB((int)actA, 255, 255, 255)); + JRenderer::GetInstance()->RenderQuad(quad, actX, actY, actT, actZ, actZ); } diff --git a/projects/mtg/src/PriceList.cpp b/projects/mtg/src/PriceList.cpp index 1874b5fad..66223b837 100644 --- a/projects/mtg/src/PriceList.cpp +++ b/projects/mtg/src/PriceList.cpp @@ -4,103 +4,125 @@ int PriceList::randomKey = 0; -PriceList::PriceList(const char * _filename, MTGAllCards * _collection):collection(_collection){ - filename = _filename; - std::ifstream file(_filename); - std::string cardid; - std::string price; - if(file){ - while(std::getline(file,cardid)){ - std::getline(file,price); - prices[atoi(cardid.c_str())]= atoi(price.c_str()); +PriceList::PriceList(const char * _filename, MTGAllCards * _collection) : + collection(_collection) +{ + filename = _filename; + std::ifstream file(_filename); + std::string cardid; + std::string price; + if (file) + { + while (std::getline(file, cardid)) + { + std::getline(file, price); + prices[atoi(cardid.c_str())] = atoi(price.c_str()); + } + file.close(); } - file.close(); - } - if(randomKey == 0) - randomKey = rand(); + if (randomKey == 0) randomKey = rand(); } - -PriceList::~PriceList(){ +PriceList::~PriceList() +{ } -int PriceList::save(){ - std::ofstream file(filename.c_str()); - char writer[20]; - if (file){ - map::iterator it=prices.begin(); - while(it != prices.end()){ - sprintf(writer,"%i\n%i\n", (*it).first, (*it).second); - it++; - file<::iterator it = prices.begin(); + while (it != prices.end()) + { + sprintf(writer, "%i\n%i\n", (*it).first, (*it).second); + it++; + file << writer; + } + file.close(); } - file.close(); - } - return 1; + return 1; } -int PriceList::getPrice(int cardId){ - map::iterator it = prices.find(cardId); - if (it != prices.end()) return (*it).second; +int PriceList::getPrice(int cardId) +{ + map::iterator it = prices.find(cardId); + if (it != prices.end()) return (*it).second; + + char rarity = collection->getCardById(cardId)->getRarity(); + switch (rarity) + { + case Constants::RARITY_M: + return Constants::PRICE_1M; + break; + case Constants::RARITY_S: + return Constants::PRICE_1S; + break; + case Constants::RARITY_R: + return Constants::PRICE_1R; + break; + case Constants::RARITY_U: + return Constants::PRICE_1U; + break; + case Constants::RARITY_C: + return Constants::PRICE_1C; + break; + case Constants::RARITY_L: + return Constants::PRICE_1L; + break; + default: + return Constants::PRICE_1C; + break; + } - char rarity = collection->getCardById(cardId)->getRarity(); - switch(rarity){ - case Constants::RARITY_M: - return Constants::PRICE_1M; - break; - case Constants::RARITY_S: - return Constants::PRICE_1S; - break; - case Constants::RARITY_R: - return Constants::PRICE_1R; - break; - case Constants::RARITY_U: - return Constants::PRICE_1U; - break; - case Constants::RARITY_C: - return Constants::PRICE_1C; - break; - case Constants::RARITY_L: - return Constants::PRICE_1L; - break; - default: - return Constants::PRICE_1C; - break; - } - } -int PriceList::setPrice(int cardId, int price){ - prices[cardId] = price; - return price; +int PriceList::setPrice(int cardId, int price) +{ + prices[cardId] = price; + return price; } -int PriceList::getSellPrice(int cardid){ - return getPrice(cardid); +int PriceList::getSellPrice(int cardid) +{ + return getPrice(cardid); } -float PriceList::difficultyScalar(float price, int cardid){ - float badluck = (float)(abs(cardid + randomKey) % 201) / 100; //Float between 0 and 2. +float PriceList::difficultyScalar(float price, int cardid) +{ + float badluck = (float) (abs(cardid + randomKey) % 201) / 100; //Float between 0 and 2. - switch(options[Options::ECON_DIFFICULTY].number){ + switch (options[Options::ECON_DIFFICULTY].number) + { case Constants::ECON_EASY: - badluck -= 1.5; price /= 2; break; //Price from .25x to .75x, .25x more likely. - case Constants::ECON_NORMAL: default: - badluck /= 2; break; //price from 1x to 2x, even probability. + badluck -= 1.5; + price /= 2; + break; //Price from .25x to .75x, .25x more likely. + case Constants::ECON_NORMAL: + default: + badluck /= 2; + break; //price from 1x to 2x, even probability. case Constants::ECON_HARD: - price *= 1.5; break; //price from 1.5x to 3x, 3x being twice as likely. - case Constants::ECON_LUCK: - badluck += .25; return price*badluck; break; //Price from .25x to 2.25x, randomly. - } - if(badluck > 1) badluck = 1; - else if(badluck < -1) badluck = -1; - return (price + price * badluck); + price *= 1.5; + break; //price from 1.5x to 3x, 3x being twice as likely. + case Constants::ECON_LUCK: + badluck += .25; + return price * badluck; + break; //Price from .25x to 2.25x, randomly. + } + if (badluck > 1) + badluck = 1; + else if (badluck < -1) badluck = -1; + return (price + price * badluck); } -int PriceList::getPurchasePrice(int cardid){ - float p = difficultyScalar((float)getPrice(cardid),cardid); - if(p < 2) p = 2; //Prevents "Sell for 0 credits" - return (int)p; +int PriceList::getPurchasePrice(int cardid) +{ + float p = difficultyScalar((float) getPrice(cardid), cardid); + if (p < 2) p = 2; //Prevents "Sell for 0 credits" + return (int) p; } -int PriceList::getOtherPrice(int amt){ - float p = difficultyScalar((float)amt,0); - if(p < 2) p = 2; - return (int)p; +int PriceList::getOtherPrice(int amt) +{ + float p = difficultyScalar((float) amt, 0); + if (p < 2) p = 2; + return (int) p; } diff --git a/projects/mtg/src/ReplacementEffects.cpp b/projects/mtg/src/ReplacementEffects.cpp index b8cb4a087..107714215 100644 --- a/projects/mtg/src/ReplacementEffects.cpp +++ b/projects/mtg/src/ReplacementEffects.cpp @@ -4,75 +4,87 @@ #include "MTGCardInstance.h" #include "TargetChooser.h" - - -REDamagePrevention::REDamagePrevention(MTGAbility * source, TargetChooser *tcSource, TargetChooser *tcTarget, int damage, bool oneShot, int typeOfDamage):source(source), tcSource(tcSource), tcTarget(tcTarget), damage(damage), oneShot(oneShot), typeOfDamage(typeOfDamage){ +REDamagePrevention::REDamagePrevention(MTGAbility * source, TargetChooser *tcSource, TargetChooser *tcTarget, int damage, + bool oneShot, int typeOfDamage) : + source(source), tcSource(tcSource), tcTarget(tcTarget), damage(damage), oneShot(oneShot), typeOfDamage(typeOfDamage) +{ } -WEvent * REDamagePrevention::replace (WEvent *event){ - if (!event) return event; - if (!damage) return event; - WEventDamage * e = dynamic_cast(event); - if (!e) return event; - Damage *d = e->damage; - if (d->typeOfDamage != typeOfDamage && typeOfDamage != DAMAGE_ALL_TYPES) return event; - if ((!tcSource || tcSource->canTarget(d->source)) && - (!tcTarget || tcTarget->canTarget(d->target)) - ){ - if (damage == -1){ - d->damage = 0; - delete event; - if (oneShot) damage = 0; - return NULL; +WEvent * REDamagePrevention::replace(WEvent *event) +{ + if (!event) return event; + if (!damage) return event; + WEventDamage * e = dynamic_cast (event); + if (!e) return event; + Damage *d = e->damage; + if (d->typeOfDamage != typeOfDamage && typeOfDamage != DAMAGE_ALL_TYPES) return event; + if ((!tcSource || tcSource->canTarget(d->source)) && (!tcTarget || tcTarget->canTarget(d->target))) + { + if (damage == -1) + { + d->damage = 0; + delete event; + if (oneShot) damage = 0; + return NULL; + } + if (damage >= d->damage) + { + damage -= d->damage; + d->damage = 0; + delete event; + return NULL; + } + d->damage -= damage; + damage = 0; + delete event; + WEventDamage* newEvent = NEW WEventDamage(d); + return newEvent; } - if (damage >= d->damage){ - damage-= d->damage; - d->damage = 0; - delete event; - return NULL; - } - d->damage -= damage; - damage = 0; - delete event; - WEventDamage* newEvent = NEW WEventDamage(d); - return newEvent; - } - return event; + return event; } -REDamagePrevention::~REDamagePrevention(){ - SAFE_DELETE(tcSource); - SAFE_DELETE(tcTarget); +REDamagePrevention::~REDamagePrevention() +{ + SAFE_DELETE(tcSource); + SAFE_DELETE(tcTarget); } -ReplacementEffects::ReplacementEffects(){} +ReplacementEffects::ReplacementEffects() +{ +} -WEvent * ReplacementEffects::replace(WEvent *e){ +WEvent * ReplacementEffects::replace(WEvent *e) +{ list::iterator it; - for ( it=modifiers.begin() ; it != modifiers.end(); it++ ){ - ReplacementEffect *re = *it; - WEvent * newEvent = re->replace(e); - if (!newEvent) return NULL; - if (newEvent != e) return replace(newEvent); + for (it = modifiers.begin(); it != modifiers.end(); it++) + { + ReplacementEffect *re = *it; + WEvent * newEvent = re->replace(e); + if (!newEvent) return NULL; + if (newEvent != e) return replace(newEvent); } return e; } -int ReplacementEffects::add(ReplacementEffect * re){ - modifiers.push_back(re); - return 1; -} - -int ReplacementEffects::remove (ReplacementEffect *re){ - modifiers.remove(re); - return 1; +int ReplacementEffects::add(ReplacementEffect * re) +{ + modifiers.push_back(re); + return 1; } -ReplacementEffects::~ReplacementEffects(){ - list::iterator it; - for ( it=modifiers.begin() ; it != modifiers.end(); it++ ){ - ReplacementEffect *re = *it; - delete(re); +int ReplacementEffects::remove(ReplacementEffect *re) +{ + modifiers.remove(re); + return 1; +} + +ReplacementEffects::~ReplacementEffects() +{ + list::iterator it; + for (it = modifiers.begin(); it != modifiers.end(); it++) + { + ReplacementEffect *re = *it; + delete (re); } modifiers.clear(); } diff --git a/projects/mtg/src/Rules.cpp b/projects/mtg/src/Rules.cpp index 47318618b..d1d99d89a 100644 --- a/projects/mtg/src/Rules.cpp +++ b/projects/mtg/src/Rules.cpp @@ -11,448 +11,555 @@ #include "DeckManager.h" #include "AIPlayer.h" -int Rules::getMTGId(string cardName){ - int cardnb = atoi(cardName.c_str()); - if (cardnb) return cardnb; - if (cardName.compare("*") == 0) return -1; //Any card - MTGCard * card = GameApp::collection->getCardByName(cardName); - if (card) return card->getMTGId(); - DebugTrace("RULES: Can't find card:" << cardName.c_str()); - return 0; +int Rules::getMTGId(string cardName) +{ + int cardnb = atoi(cardName.c_str()); + if (cardnb) return cardnb; + if (cardName.compare("*") == 0) return -1; //Any card + MTGCard * card = GameApp::collection->getCardByName(cardName); + if (card) return card->getMTGId(); + DebugTrace("RULES: Can't find card:" << cardName.c_str()); + return 0; } -MTGCardInstance * Rules::getCardByMTGId(int mtgid){ - GameObserver * g = GameObserver::GetInstance(); - for (int i = 0; i < 2; i++){ - Player * p = g->players[i]; - MTGGameZone * zones[] = {p->game->library,p->game->hand, p->game->inPlay, p->game->graveyard}; - for (int j = 0; j < 4; j++){ - MTGGameZone * zone = zones[j]; - for (int k = 0; k < zone->nb_cards; k++){ - MTGCardInstance * card = zone->cards[k]; - if (!card) return NULL; - if (card->getMTGId() == mtgid) return card; - } - } - } - return NULL; -} - -RulesPlayerData::RulesPlayerData(){ - life = 20; - poisonCount = 0; - damageCount = 0; - preventable = 0; - manapool = NEW ManaCost(); - avatar = ""; -} - -RulesPlayerData::~RulesPlayerData(){ - SAFE_DELETE(manapool); -} - -RulesPlayerZone::RulesPlayerZone(){ -} - -void RulesPlayerZone::add(int cardId){ - cards.push_back(cardId); -} - -RulesState::RulesState(){ - phase = Constants::MTG_PHASE_FIRSTMAIN; - player = 0; -} - -void RulesState::parsePlayerState(int playerId, string s){ - size_t limiter = s.find("="); - if (limiter == string::npos) limiter = s.find(":"); - string areaS; - int area; - if (limiter != string::npos){ - areaS = s.substr(0,limiter); - if (areaS.compare("graveyard") == 0){ - area = 0; - }else if(areaS.compare("library") == 0){ - area = 1; - }else if(areaS.compare("hand") == 0){ - area = 2; - }else if(areaS.compare("inplay") == 0 || areaS.compare("battlefield") == 0 ){ - area = 3; - }else if(areaS.compare("life") == 0){ - playerData[playerId].life = atoi((s.substr(limiter+1)).c_str()); - return; - }else if(areaS.compare("poisonCount") == 0){ - playerData[playerId].poisonCount = atoi((s.substr(limiter+1)).c_str()); - return; - }else if(areaS.compare("damageCount") == 0){ - playerData[playerId].damageCount = atoi((s.substr(limiter+1)).c_str()); - return; - }else if(areaS.compare("preventable") == 0){ - playerData[playerId].preventable = atoi((s.substr(limiter+1)).c_str()); - return; - }else if(areaS.compare("avatar") == 0){ - playerData[playerId].avatar = s.substr(limiter+1); - return; - }else if(areaS.compare("manapool") == 0){ - SAFE_DELETE(playerData[playerId].manapool); - playerData[playerId].manapool = ManaCost::parseManaCost(s.substr(limiter+1)); - return; - }else if(areaS.compare("auto") == 0){ - playerData[playerId].extraRules.push_back(s.substr(limiter+1)); - return; - }else{ - return; // ERROR - } - s = s.substr(limiter+1); - while (s.size()){ - unsigned int value; - limiter = s.find(","); - if (limiter != string::npos){ - value = Rules::getMTGId(s.substr(0,limiter)); - s = s.substr(limiter+1); - }else{ - value = Rules::getMTGId(s); - s = ""; - } - if (value) playerData[playerId].zones[area].add(value); - } - }else{ - //ERROR - } -} - - - - -void Rules::addExtraRules(){ - GameObserver * g = GameObserver::GetInstance(); - - int id = g->mLayers->actionLayer()->getMaxId(); - for (int i = 0; i < 2; ++i){ - Player * p = g->players[i]; - //Trick so that the abilities don't die; - MTGCardInstance::ExtraRules[i].currentZone = p->game->inPlay; - MTGCardInstance::ExtraRules[i].lastController = p; - for (size_t j = 0; j< initState.playerData[i].extraRules.size(); ++j){ - AbilityFactory af; - MTGPlayerCards * hand = NULL; - int handsize = 7; - int difficultyRating = 0; - MTGAbility * a = af.parseMagicLine(initState.playerData[i].extraRules[j], id++, NULL,&MTGCardInstance::ExtraRules[i]); - if(p->playMode != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode != GAME_TYPE_STORY)//keep this out of mimor and other game modes. - { - difficultyRating = DeckManager::getDifficultyRating( g->players[0], g->players[1] ); - } - - if (a){ - if (a->oneShot){ - if(p->isAI() && a->aType == MTGAbility::STANDARD_DRAW && difficultyRating == EASY && p->playMode != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode != GAME_TYPE_STORY)//stupid protections to keep this out of mimor and other game modes. - { - handsize = a->nbcardAmount; - ((AIPlayer *)p)->forceBestAbilityUse = true; - ((AIPlayer *)p)->agressivity += 100; - hand->OptimizedHand(handsize,3,1,3);//easy decks get a major boost, open hand is 2lands,1 creature under 3 mana,3spells under 3 mana. - } - else if(p->isAI() && a->aType == MTGAbility::STANDARD_DRAW && difficultyRating == NORMAL && p->playMode != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode != GAME_TYPE_STORY)//stupid protections to keep this out of mimor and other game modes. - { - handsize = a->nbcardAmount; - hand->OptimizedHand(handsize,1,0,2);//give the Ai deck a tiny boost by giving it 1 land and 2 spells under 3 manacost. - }else{//resolve normally if the deck is listed as hard. - a->resolve(); - } - delete(a); - }else{ - a->addToGame(); +MTGCardInstance * Rules::getCardByMTGId(int mtgid) +{ + GameObserver * g = GameObserver::GetInstance(); + for (int i = 0; i < 2; i++) + { + Player * p = g->players[i]; + MTGGameZone * zones[] = { p->game->library, p->game->hand, p->game->inPlay, p->game->graveyard }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = zones[j]; + for (int k = 0; k < zone->nb_cards; k++) + { + MTGCardInstance * card = zone->cards[k]; + if (!card) return NULL; + if (card->getMTGId() == mtgid) return card; + } } - - } - } - } - - for (size_t j = 0; j< extraRules.size(); ++j){ - AbilityFactory af; - MTGAbility * a = af.parseMagicLine(extraRules[j], id++, NULL,&MTGCardInstance::ExtraRules[0]); - if (a){ - if (a->oneShot){ - a->resolve(); - delete(a); - }else{ - a->addToGame(); - } } - } - -} - -Player * Rules::loadPlayerMomir(int isAI){ - string deckFileSmall = "momir"; - char empty[] = ""; - - MTGDeck * tempDeck = NEW MTGDeck(GameApp::collection); //Autogenerate a momir deck. Leave the "momir.txt" bits below for stats. - tempDeck->addRandomCards(12, 0,0,Constants::RARITY_L,"Forest"); - tempDeck->addRandomCards(12, 0,0,Constants::RARITY_L,"Plains"); - tempDeck->addRandomCards(12, 0,0,Constants::RARITY_L,"Swamp"); - tempDeck->addRandomCards(12, 0,0,Constants::RARITY_L,"Mountain"); - tempDeck->addRandomCards(12, 0,0,Constants::RARITY_L,"Island"); - - Player *player = NULL; - if (!isAI) // Human Player - player = NEW HumanPlayer(tempDeck, options.profileFile("momir.txt","",true).c_str(), deckFileSmall); - else - player = NEW AIMomirPlayer(tempDeck, options.profileFile("momir.txt","",true).c_str(), deckFileSmall, empty); - - delete tempDeck; - return player; -} - -Player * Rules::loadPlayerRandom(int isAI, int mode){ - int color1 = 1 + WRand() % 5; - int color2 = 1 + WRand() % 5; - int color0 = Constants::MTG_COLOR_ARTIFACT; - if (mode == GAME_TYPE_RANDOM1) color2 = color1; - int colors[]={color1,color2,color0}; - int nbcolors = 3; - - string lands[] = {"forest", "forest", "island", "mountain", "swamp", "plains", "forest"}; - - - MTGDeck * tempDeck = NEW MTGDeck(GameApp::collection); - tempDeck->addRandomCards(9,0,0,-1,lands[color1].c_str()); - tempDeck->addRandomCards(9,0,0,-1,lands[color2].c_str()); - tempDeck->addRandomCards(1,0,0,'U',"land"); - tempDeck->addRandomCards(1,0,0,'R',"land"); - tempDeck->addRandomCards(12,0,0,-1,"creature",colors,nbcolors); - tempDeck->addRandomCards(2,0,0,-1,"sorcery",colors,nbcolors); - tempDeck->addRandomCards(2,0,0,-1,"enchantment",colors,nbcolors); - tempDeck->addRandomCards(2,0,0,-1,"instant",colors,nbcolors); - tempDeck->addRandomCards(2,0,0,-1,"artifact",colors,nbcolors); - - string deckFile = "random"; - string deckFileSmall = "random"; - - Player *player = NULL; - if (!isAI) // Human Player - player = NEW HumanPlayer(tempDeck, deckFile, deckFileSmall); - else - player = NEW AIPlayerBaka(tempDeck, deckFile, deckFileSmall, ""); - - return player; -} - - -Player * Rules::initPlayer(int playerId){ - GameObserver * g = GameObserver::GetInstance(); - Player * p = g->players[playerId]; - if (!p) { - int isAI = 1; - if (GameApp::players[playerId] == PLAYER_TYPE_HUMAN) isAI = 0; - switch(gamemode){ - case GAME_TYPE_MOMIR: - return loadPlayerMomir(isAI); - case GAME_TYPE_CLASSIC: - return NULL; //Error for the time being - case GAME_TYPE_RANDOM1: - return loadPlayerRandom(isAI,GAME_TYPE_RANDOM1); - case GAME_TYPE_RANDOM2: - return loadPlayerRandom(isAI,GAME_TYPE_RANDOM2); - } - } - return p; -} - -MTGDeck * Rules::buildDeck( int playerId){ - int nbcards = 0; - MTGDeck * deck = NEW MTGDeck(GameApp::collection); - for (int j = 0; j < 4; j++){ - for (size_t k = 0; k < initState.playerData[playerId].zones[j].cards.size(); k++){ - int cardid = initState.playerData[playerId].zones[j].cards[k]; - deck->add(cardid); - nbcards++; - } - } - if (!nbcards){ - delete(deck); return NULL; - } - return deck; } - -void Rules::initPlayers(){ - GameObserver * g = GameObserver::GetInstance(); - for (int i = 0; i < 2; i++){ - Player * p = initPlayer(i); - g->players[i] = p; - MTGDeck * deck = buildDeck(i); - if (deck) { - p->game->initDeck(deck); - SAFE_DELETE(deck); - p->game->setOwner(p); - } - } +RulesPlayerData::RulesPlayerData() +{ + life = 20; + poisonCount = 0; + damageCount = 0; + preventable = 0; + manapool = NEW ManaCost(); + avatar = ""; } -void Rules::initGame(){ - //Put the GameObserver in the initial state - GameObserver * g = GameObserver::GetInstance(); - DebugTrace("RULES Init Game\n"); +RulesPlayerData::~RulesPlayerData() +{ + SAFE_DELETE(manapool); +} - //Set the current player/phase - g->currentPlayer = g->players[initState.player]; - g->currentActionPlayer = g->currentPlayer; - g->currentPlayerId = initState.player; - g->phaseRing->goToPhase(0, g->currentPlayer, false); - g->phaseRing->goToPhase(initState.phase, g->currentPlayer); - g->currentGamePhase = initState.phase; +RulesPlayerZone::RulesPlayerZone() +{ +} +void RulesPlayerZone::add(int cardId) +{ + cards.push_back(cardId); +} - for (int i = 0; i < 2; i++){ - Player * p = g->players[i]; - p->life = initState.playerData[i].life; - p->poisonCount = initState.playerData[i].poisonCount; - p->damageCount = initState.playerData[i].damageCount; - p->preventable = initState.playerData[i].preventable; - p->getManaPool()->copy(initState.playerData[i].manapool); - if (initState.playerData[i].avatar.size()) { - p->loadAvatar(initState.playerData[i].avatar); - } - MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay}; - for (int j = 0; j < 4; j++){ - MTGGameZone * zone = playerZones[j]; - for (size_t k = 0; k < initState.playerData[i].zones[j].cards.size(); k++){ - MTGCardInstance * card = getCardByMTGId(initState.playerData[i].zones[j].cards[k]); - if (card && zone != p->game->library){ - if (zone == p->game->inPlay){ - MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); - Spell * spell = NEW Spell(copy); - spell->resolve(); - delete spell; - }else{ - if (!p->game->library->hasCard(card)){ - LOG ("RULES ERROR, CARD NOT FOUND IN LIBRARY\n"); - } - p->game->putInZone(card,p->game->library,zone); - } - }else{ - if (!card) { LOG ("RULES ERROR, card is NULL\n"); } +RulesState::RulesState() +{ + phase = Constants::MTG_PHASE_FIRSTMAIN; + player = 0; +} + +void RulesState::parsePlayerState(int playerId, string s) +{ + size_t limiter = s.find("="); + if (limiter == string::npos) limiter = s.find(":"); + string areaS; + int area; + if (limiter != string::npos) + { + areaS = s.substr(0, limiter); + if (areaS.compare("graveyard") == 0) + { + area = 0; } - } - } - } - addExtraRules(); - DebugTrace("RULES Init Game Done !\n"); -} - - - -void RulesPlayerZone::cleanup(){ - cards.clear(); -} - -void RulesPlayerData::cleanup(){ - if (manapool) delete manapool; - manapool = NULL; - manapool = NEW ManaCost(); - for (int i = 0; i < 5; i++){ - zones[i].cleanup(); - } - life=20; - poisonCount=0; - damageCount=0; - preventable=0; -} - -void RulesState::cleanup(){ - for (int i = 0; i < 2; i++){ - playerData[i].cleanup(); - } -} - -void Rules::cleanup(){ - initState.cleanup(); -} - -Rules::Rules(string filename, string _bg){ - bg = _bg; - load(filename); -} - -int Rules::load(string _filename){ - - char filename[4096]; - if (fileExists(_filename.c_str())){ - sprintf(filename, "%s", _filename.c_str()); - }else{ - sprintf(filename, JGE_GET_RES("rules/%s").c_str(), _filename.c_str()); - } - std::ifstream file(filename); - std::string s; - - int state = PARSE_UNDEFINED; - - // std::cout << std::endl << std::endl << "!!!" << file << std::endl << std::endl; - if (!file) return 0; - - cleanup(); - while(std::getline(file,s)){ - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - if (s[0] == '#') continue; - std::transform( s.begin(), s.end(), s.begin(),::tolower ); - if (s.find("include ") == 0) { - load (s.substr(8)); - continue; - } - if (s.compare("[init]") == 0) { - state = PARSE_INIT; - continue; - } - if (s.compare("[players]") == 0) { - state = PARSE_PLAYERS; - continue; - } - if (s.compare("[player1]") == 0) { - state = PARSE_PLAYER1; - continue; - } - if (s.compare("[player2]") == 0) { - state = PARSE_PLAYER2; - continue; - } - - switch(state){ - case PARSE_UNDEFINED: - break; - case PARSE_INIT: - if (s.find("auto=") == 0){ - extraRules.push_back(s.substr(5)); - }else if (s.find("mode=") == 0) { - gamemode = strToGameMode(s.substr(5)); - }else if (s.find("player=") == 0) { - initState.player = atoi(s.substr(7).c_str())-1; - }else{ - initState.phase = PhaseRing::phaseStrToInt(s); + else if (areaS.compare("library") == 0) + { + area = 1; + } + else if (areaS.compare("hand") == 0) + { + area = 2; + } + else if (areaS.compare("inplay") == 0 || areaS.compare("battlefield") == 0) + { + area = 3; + } + else if (areaS.compare("life") == 0) + { + playerData[playerId].life = atoi((s.substr(limiter + 1)).c_str()); + return; + } + else if (areaS.compare("poisonCount") == 0) + { + playerData[playerId].poisonCount = atoi((s.substr(limiter + 1)).c_str()); + return; + } + else if (areaS.compare("damageCount") == 0) + { + playerData[playerId].damageCount = atoi((s.substr(limiter + 1)).c_str()); + return; + } + else if (areaS.compare("preventable") == 0) + { + playerData[playerId].preventable = atoi((s.substr(limiter + 1)).c_str()); + return; + } + else if (areaS.compare("avatar") == 0) + { + playerData[playerId].avatar = s.substr(limiter + 1); + return; + } + else if (areaS.compare("manapool") == 0) + { + SAFE_DELETE(playerData[playerId].manapool); + playerData[playerId].manapool = ManaCost::parseManaCost(s.substr(limiter + 1)); + return; + } + else if (areaS.compare("auto") == 0) + { + playerData[playerId].extraRules.push_back(s.substr(limiter + 1)); + return; + } + else + { + return; // ERROR + } + s = s.substr(limiter + 1); + while (s.size()) + { + unsigned int value; + limiter = s.find(","); + if (limiter != string::npos) + { + value = Rules::getMTGId(s.substr(0, limiter)); + s = s.substr(limiter + 1); + } + else + { + value = Rules::getMTGId(s); + s = ""; + } + if (value) playerData[playerId].zones[area].add(value); } - break; - case PARSE_PLAYER1: - initState.parsePlayerState(0, s); - break; - case PARSE_PLAYER2: - initState.parsePlayerState(1, s); - break; - case PARSE_PLAYERS: - initState.parsePlayerState(0, s); - initState.parsePlayerState(1, s); - break; } - } - file.close(); - return 1; + else + { + //ERROR + } } -int Rules::strToGameMode(string s){ - if (s.compare("momir")==0) return GAME_TYPE_MOMIR; - if (s.compare("random1")==0) return GAME_TYPE_RANDOM1; - if (s.compare("random2")==0) return GAME_TYPE_RANDOM2; - return GAME_TYPE_CLASSIC; +void Rules::addExtraRules() +{ + GameObserver * g = GameObserver::GetInstance(); + + int id = g->mLayers->actionLayer()->getMaxId(); + for (int i = 0; i < 2; ++i) + { + Player * p = g->players[i]; + //Trick so that the abilities don't die; + MTGCardInstance::ExtraRules[i].currentZone = p->game->inPlay; + MTGCardInstance::ExtraRules[i].lastController = p; + for (size_t j = 0; j < initState.playerData[i].extraRules.size(); ++j) + { + AbilityFactory af; + MTGPlayerCards * hand = NULL; + int handsize = 7; + int difficultyRating = 0; + MTGAbility * a = af.parseMagicLine(initState.playerData[i].extraRules[j], id++, NULL, &MTGCardInstance::ExtraRules[i]); + if (p->playMode != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode + != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode + != GAME_TYPE_STORY)//keep this out of mimor and other game modes. + { + difficultyRating = DeckManager::getDifficultyRating(g->players[0], g->players[1]); + } + + if (a) + { + if (a->oneShot) + { + if (p->isAI() && a->aType == MTGAbility::STANDARD_DRAW && difficultyRating == EASY && p->playMode + != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode + != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode + != GAME_TYPE_STORY)//stupid protections to keep this out of mimor and other game modes. + { + handsize = a->nbcardAmount; + ((AIPlayer *) p)->forceBestAbilityUse = true; + ((AIPlayer *) p)->agressivity += 100; + hand->OptimizedHand(handsize, 3, 1, 3);//easy decks get a major boost, open hand is 2lands,1 creature under 3 mana,3spells under 3 mana. + } + else if (p->isAI() && a->aType == MTGAbility::STANDARD_DRAW && difficultyRating == NORMAL && p->playMode + != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode + != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode + != GAME_TYPE_STORY)//stupid protections to keep this out of mimor and other game modes. + { + handsize = a->nbcardAmount; + hand->OptimizedHand(handsize, 1, 0, 2);//give the Ai deck a tiny boost by giving it 1 land and 2 spells under 3 manacost. + } + else + {//resolve normally if the deck is listed as hard. + a->resolve(); + } + delete (a); + } + else + { + a->addToGame(); + } + + } + } + } + + for (size_t j = 0; j < extraRules.size(); ++j) + { + AbilityFactory af; + MTGAbility * a = af.parseMagicLine(extraRules[j], id++, NULL, &MTGCardInstance::ExtraRules[0]); + if (a) + { + if (a->oneShot) + { + a->resolve(); + delete (a); + } + else + { + a->addToGame(); + } + } + } + +} + +Player * Rules::loadPlayerMomir(int isAI) +{ + string deckFileSmall = "momir"; + char empty[] = ""; + + MTGDeck * tempDeck = NEW MTGDeck(GameApp::collection); //Autogenerate a momir deck. Leave the "momir.txt" bits below for stats. + tempDeck->addRandomCards(12, 0, 0, Constants::RARITY_L, "Forest"); + tempDeck->addRandomCards(12, 0, 0, Constants::RARITY_L, "Plains"); + tempDeck->addRandomCards(12, 0, 0, Constants::RARITY_L, "Swamp"); + tempDeck->addRandomCards(12, 0, 0, Constants::RARITY_L, "Mountain"); + tempDeck->addRandomCards(12, 0, 0, Constants::RARITY_L, "Island"); + + Player *player = NULL; + if (!isAI) // Human Player + player = NEW HumanPlayer(tempDeck, options.profileFile("momir.txt", "", true).c_str(), deckFileSmall); + else + player = NEW AIMomirPlayer(tempDeck, options.profileFile("momir.txt", "", true).c_str(), deckFileSmall, empty); + + delete tempDeck; + return player; +} + +Player * Rules::loadPlayerRandom(int isAI, int mode) +{ + int color1 = 1 + WRand() % 5; + int color2 = 1 + WRand() % 5; + int color0 = Constants::MTG_COLOR_ARTIFACT; + if (mode == GAME_TYPE_RANDOM1) color2 = color1; + int colors[] = { color1, color2, color0 }; + int nbcolors = 3; + + string lands[] = { "forest", "forest", "island", "mountain", "swamp", "plains", "forest" }; + + MTGDeck * tempDeck = NEW MTGDeck(GameApp::collection); + tempDeck->addRandomCards(9, 0, 0, -1, lands[color1].c_str()); + tempDeck->addRandomCards(9, 0, 0, -1, lands[color2].c_str()); + tempDeck->addRandomCards(1, 0, 0, 'U', "land"); + tempDeck->addRandomCards(1, 0, 0, 'R', "land"); + tempDeck->addRandomCards(12, 0, 0, -1, "creature", colors, nbcolors); + tempDeck->addRandomCards(2, 0, 0, -1, "sorcery", colors, nbcolors); + tempDeck->addRandomCards(2, 0, 0, -1, "enchantment", colors, nbcolors); + tempDeck->addRandomCards(2, 0, 0, -1, "instant", colors, nbcolors); + tempDeck->addRandomCards(2, 0, 0, -1, "artifact", colors, nbcolors); + + string deckFile = "random"; + string deckFileSmall = "random"; + + Player *player = NULL; + if (!isAI) // Human Player + player = NEW HumanPlayer(tempDeck, deckFile, deckFileSmall); + else + player = NEW AIPlayerBaka(tempDeck, deckFile, deckFileSmall, ""); + + return player; +} + +Player * Rules::initPlayer(int playerId) +{ + GameObserver * g = GameObserver::GetInstance(); + Player * p = g->players[playerId]; + if (!p) + { + int isAI = 1; + if (GameApp::players[playerId] == PLAYER_TYPE_HUMAN) isAI = 0; + switch (gamemode) + { + case GAME_TYPE_MOMIR: + return loadPlayerMomir(isAI); + case GAME_TYPE_CLASSIC: + return NULL; //Error for the time being + case GAME_TYPE_RANDOM1: + return loadPlayerRandom(isAI, GAME_TYPE_RANDOM1); + case GAME_TYPE_RANDOM2: + return loadPlayerRandom(isAI, GAME_TYPE_RANDOM2); + } + } + return p; +} + +MTGDeck * Rules::buildDeck(int playerId) +{ + int nbcards = 0; + MTGDeck * deck = NEW MTGDeck(GameApp::collection); + for (int j = 0; j < 4; j++) + { + for (size_t k = 0; k < initState.playerData[playerId].zones[j].cards.size(); k++) + { + int cardid = initState.playerData[playerId].zones[j].cards[k]; + deck->add(cardid); + nbcards++; + } + } + if (!nbcards) + { + delete (deck); + return NULL; + } + return deck; +} + +void Rules::initPlayers() +{ + GameObserver * g = GameObserver::GetInstance(); + for (int i = 0; i < 2; i++) + { + Player * p = initPlayer(i); + g->players[i] = p; + MTGDeck * deck = buildDeck(i); + if (deck) + { + p->game->initDeck(deck); + SAFE_DELETE(deck); + p->game->setOwner(p); + } + } +} + +void Rules::initGame() +{ + //Put the GameObserver in the initial state + GameObserver * g = GameObserver::GetInstance(); + DebugTrace("RULES Init Game\n"); + + //Set the current player/phase + g->currentPlayer = g->players[initState.player]; + g->currentActionPlayer = g->currentPlayer; + g->currentPlayerId = initState.player; + g->phaseRing->goToPhase(0, g->currentPlayer, false); + g->phaseRing->goToPhase(initState.phase, g->currentPlayer); + g->currentGamePhase = initState.phase; + + for (int i = 0; i < 2; i++) + { + Player * p = g->players[i]; + p->life = initState.playerData[i].life; + p->poisonCount = initState.playerData[i].poisonCount; + p->damageCount = initState.playerData[i].damageCount; + p->preventable = initState.playerData[i].preventable; + p->getManaPool()->copy(initState.playerData[i].manapool); + if (initState.playerData[i].avatar.size()) + { + p->loadAvatar(initState.playerData[i].avatar); + } + MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = playerZones[j]; + for (size_t k = 0; k < initState.playerData[i].zones[j].cards.size(); k++) + { + MTGCardInstance * card = getCardByMTGId(initState.playerData[i].zones[j].cards[k]); + if (card && zone != p->game->library) + { + if (zone == p->game->inPlay) + { + MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); + Spell * spell = NEW Spell(copy); + spell->resolve(); + delete spell; + } + else + { + if (!p->game->library->hasCard(card)) + { + LOG ("RULES ERROR, CARD NOT FOUND IN LIBRARY\n"); + } + p->game->putInZone(card, p->game->library, zone); + } + } + else + { + if (!card) + { + LOG ("RULES ERROR, card is NULL\n"); + } + } + } + } + } + addExtraRules(); +DebugTrace("RULES Init Game Done !\n"); +} + +void RulesPlayerZone::cleanup() +{ + cards.clear(); +} + +void RulesPlayerData::cleanup() +{ + if (manapool) delete manapool; + manapool = NULL; + manapool = NEW ManaCost(); + for (int i = 0; i < 5; i++) + { + zones[i].cleanup(); + } + life = 20; + poisonCount = 0; + damageCount = 0; + preventable = 0; +} + +void RulesState::cleanup() +{ + for (int i = 0; i < 2; i++) + { + playerData[i].cleanup(); + } +} + +void Rules::cleanup() +{ + initState.cleanup(); +} + +Rules::Rules(string filename, string _bg) +{ + bg = _bg; + load(filename); +} + +int Rules::load(string _filename) +{ + + char filename[4096]; + if (fileExists(_filename.c_str())) + { + sprintf(filename, "%s", _filename.c_str()); + } + else + { + sprintf(filename, JGE_GET_RES("rules/%s").c_str(), _filename.c_str()); + } + std::ifstream file(filename); + std::string s; + + int state = PARSE_UNDEFINED; + + // std::cout << std::endl << std::endl << "!!!" << file << std::endl << std::endl; + if (!file) return 0; + + cleanup(); + while (std::getline(file, s)) + { + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + if (s[0] == '#') continue; + std::transform(s.begin(), s.end(), s.begin(), ::tolower); + if (s.find("include ") == 0) + { + load(s.substr(8)); + continue; + } + if (s.compare("[init]") == 0) + { + state = PARSE_INIT; + continue; + } + if (s.compare("[players]") == 0) + { + state = PARSE_PLAYERS; + continue; + } + if (s.compare("[player1]") == 0) + { + state = PARSE_PLAYER1; + continue; + } + if (s.compare("[player2]") == 0) + { + state = PARSE_PLAYER2; + continue; + } + + switch (state) + { + case PARSE_UNDEFINED: + break; + case PARSE_INIT: + if (s.find("auto=") == 0) + { + extraRules.push_back(s.substr(5)); + } + else if (s.find("mode=") == 0) + { + gamemode = strToGameMode(s.substr(5)); + } + else if (s.find("player=") == 0) + { + initState.player = atoi(s.substr(7).c_str()) - 1; + } + else + { + initState.phase = PhaseRing::phaseStrToInt(s); + } + break; + case PARSE_PLAYER1: + initState.parsePlayerState(0, s); + break; + case PARSE_PLAYER2: + initState.parsePlayerState(1, s); + break; + case PARSE_PLAYERS: + initState.parsePlayerState(0, s); + initState.parsePlayerState(1, s); + break; + } + } + file.close(); + return 1; +} + +int Rules::strToGameMode(string s) +{ + if (s.compare("momir") == 0) return GAME_TYPE_MOMIR; + if (s.compare("random1") == 0) return GAME_TYPE_RANDOM1; + if (s.compare("random2") == 0) return GAME_TYPE_RANDOM2; + return GAME_TYPE_CLASSIC; } diff --git a/projects/mtg/src/ShopItem.cpp b/projects/mtg/src/ShopItem.cpp index d68d2569b..429ebbcc8 100644 --- a/projects/mtg/src/ShopItem.cpp +++ b/projects/mtg/src/ShopItem.cpp @@ -6,548 +6,595 @@ #include "../include/Translate.h" #include +float ShopItems::_x1[] = { 79, 19, 27, 103, 154, 187, 102, 144, 198, 133, 183 }; +float ShopItems::_y1[] = { 150, 194, 222, 167, 164, 156, 195, 190, 175, 220, 220 }; +float ShopItems::_x2[] = { 103, 48, 74, 135, 183, 215, 138, 181, 231, 171, 225 }; +float ShopItems::_y2[] = { 155, 179, 218, 165, 166, 155, 195, 186, 177, 225, 216 }; - float ShopItems::_x1[] = { 79, 19, 27,103,154,187,102,144,198,133,183}; - float ShopItems::_y1[] = {150,194,222,167,164,156,195,190,175,220,220}; +float ShopItems::_x3[] = { 48, 61, 9, 96, 139, 190, 81, 146, 187, 97, 191 }; +float ShopItems::_y3[] = { 164, 205, 257, 184, 180, 170, 219, 212, 195, 251, 252 }; - float ShopItems::_x2[] = {103, 48, 74,135,183,215,138,181,231,171,225}; - float ShopItems::_y2[] = {155,179,218,165,166,155,195,186,177,225,216}; +float ShopItems::_x4[] = { 76, 90, 65, 131, 171, 221, 123, 187, 225, 141, 237 }; +float ShopItems::_y4[] = { 169, 188, 250, 182, 182, 168, 220, 208, 198, 259, 245 }; - float ShopItems::_x3[] = { 48, 61, 9, 96,139,190, 81,146,187, 97,191}; - float ShopItems::_y3[] = {164,205,257,184,180,170,219,212,195,251,252}; - - float ShopItems::_x4[] = { 76, 90, 65,131,171,221,123,187,225,141,237}; - float ShopItems::_y4[] = {169,188,250,182,182,168,220,208,198,259,245}; - - -ShopItem::ShopItem(int id, WFont *font, char* text, JQuad * _quad,JQuad * _thumb, float _xy[], bool hasFocus, int _price): JGuiObject(id), mFont(font), mText(text), quad(_quad), thumb(_thumb), price(_price) +ShopItem::ShopItem(int id, WFont *font, char* text, JQuad * _quad, JQuad * _thumb, float _xy[], bool hasFocus, int _price) : + JGuiObject(id), mFont(font), mText(text), quad(_quad), thumb(_thumb), price(_price) { - for (int i = 0; i < 8; ++i){ - xy[i] = _xy[i]; - } - quantity = 10; - card = NULL; - mHasFocus = hasFocus; - mRelease = false; + for (int i = 0; i < 8; ++i) + { + xy[i] = _xy[i]; + } + quantity = 10; + card = NULL; + mHasFocus = hasFocus; + mRelease = false; - mScale = 1.0f; - mTargetScale = 1.0f; + mScale = 1.0f; + mTargetScale = 1.0f; - mesh=NEW hgeDistortionMesh(2,2); - mesh->SetTexture(thumb->mTex); - float x0,y0,w0,h0; - thumb->GetTextureRect(&x0,&y0,&w0,&h0); - mesh->SetTextureRect(x0,y0,w0,h0); - mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); - mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE); - mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE); - mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE); - mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE); - mesh->SetColor(1,1,ARGB(255,100,100,100)); - mesh->SetColor(0,1,ARGB(255,100,100,100)); - mesh->SetColor(1,0,ARGB(255,100,100,100)); - mesh->SetColor(0,0,ARGB(255,200,200,200)); - if (hasFocus) - Entering(); + mesh = NEW hgeDistortionMesh(2, 2); + mesh->SetTexture(thumb->mTex); + float x0, y0, w0, h0; + thumb->GetTextureRect(&x0, &y0, &w0, &h0); + mesh->SetTextureRect(x0, y0, w0, h0); + mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); + mesh->SetDisplacement(0, 0, xy[0], xy[1], HGEDISP_NODE); + mesh->SetDisplacement(1, 0, xy[2] - w0, xy[3], HGEDISP_NODE); + mesh->SetDisplacement(0, 1, xy[4], xy[5] - h0, HGEDISP_NODE); + mesh->SetDisplacement(1, 1, xy[6] - w0, xy[7] - h0, HGEDISP_NODE); + mesh->SetColor(1, 1, ARGB(255,100,100,100)); + mesh->SetColor(0, 1, ARGB(255,100,100,100)); + mesh->SetColor(1, 0, ARGB(255,100,100,100)); + mesh->SetColor(0, 0, ARGB(255,200,200,200)); + if (hasFocus) Entering(); } -ShopItem::ShopItem(int id, WFont *font, int _cardid, float _xy[], bool hasFocus, MTGAllCards * collection, int _price, DeckDataWrapper * ddw): JGuiObject(id), mFont(font), price(_price){ - for (int i = 0; i < 8; ++i){ - xy[i] = _xy[i]; - } - mHasFocus = hasFocus; - mRelease = false; - mScale = 1.0f; - mTargetScale = 1.0f; +ShopItem::ShopItem(int id, WFont *font, int _cardid, float _xy[], bool hasFocus, MTGAllCards * collection, int _price, + DeckDataWrapper * ddw) : + JGuiObject(id), mFont(font), price(_price) +{ + for (int i = 0; i < 8; ++i) + { + xy[i] = _xy[i]; + } + mHasFocus = hasFocus; + mRelease = false; + mScale = 1.0f; + mTargetScale = 1.0f; - if (hasFocus) - Entering(); + if (hasFocus) Entering(); - card = collection->getCardById(_cardid); - updateCount(ddw); + card = collection->getCardById(_cardid); + updateCount(ddw); - quantity = 1 + (rand() % 4); - if (card->getRarity() == Constants::RARITY_L) quantity = 50; - quad = NULL; + quantity = 1 + (rand() % 4); + if (card->getRarity() == Constants::RARITY_L) quantity = 50; + quad = NULL; - mesh = NULL; - thumb = NULL; - updateThumb(); + mesh = NULL; + thumb = NULL; + updateThumb(); } - -int ShopItem::updateCount(DeckDataWrapper * ddw){ - if (!card) return 0; - nameCount = ddw->countByName(card); - return nameCount; +int ShopItem::updateCount(DeckDataWrapper * ddw) +{ + if (!card) return 0; + nameCount = ddw->countByName(card); + return nameCount; } -ShopItem::~ShopItem(){ - OutputDebugString("delete shopitem\n"); - if(thumb) - resources.Release(thumb->mTex); - SAFE_DELETE(mesh); -} - -const char * ShopItem::getText(){ - return mText.c_str(); -} - -void ShopItem::updateThumb(){ - if(card == NULL) - return; - - if(thumb && mRelease) - resources.Release(thumb->mTex); - mRelease = false; - - if(mesh) +ShopItem::~ShopItem() +{ + OutputDebugString("delete shopitem\n"); + if (thumb) resources.Release(thumb->mTex); SAFE_DELETE(mesh); - else if(thumb) +} + +const char * ShopItem::getText() +{ + return mText.c_str(); +} + +void ShopItem::updateThumb() +{ + if (card == NULL) return; + + if (thumb && mRelease) resources.Release(thumb->mTex); + mRelease = false; + + if (mesh) + SAFE_DELETE(mesh); + else if (thumb) SAFE_DELETE(thumb); - thumb = resources.RetrieveCard(card,RETRIEVE_LOCK,TEXTURE_SUB_THUMB); + thumb = resources.RetrieveCard(card, RETRIEVE_LOCK, TEXTURE_SUB_THUMB); #if defined (WIN32) || defined (LINUX) - //On pcs we render the big image if the thumbnail is not available - if (!thumb) thumb = resources.RetrieveCard(card,RETRIEVE_LOCK); + //On pcs we render the big image if the thumbnail is not available + if (!thumb) thumb = resources.RetrieveCard(card,RETRIEVE_LOCK); #endif - if (!thumb) - thumb = CardGui::alternateThumbQuad(card); - else - mRelease = true; + if (!thumb) + thumb = CardGui::alternateThumbQuad(card); + else + mRelease = true; - - if (thumb){ - mesh=NEW hgeDistortionMesh(2,2); - mesh->SetTexture(thumb->mTex); - float x0,y0,w0,h0; - thumb->GetTextureRect(&x0,&y0,&w0,&h0); - mesh->SetTextureRect(x0,y0,w0,h0); - mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); - mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE); - mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE); - mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE); - mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE); - mesh->SetColor(1,1,ARGB(255,100,100,100)); - mesh->SetColor(0,1,ARGB(255,100,100,100)); - mesh->SetColor(1,0,ARGB(255,100,100,100)); - mesh->SetColor(0,0,ARGB(255,200,200,200)); - }else{ - mesh = NULL; - } + if (thumb) + { + mesh = NEW hgeDistortionMesh(2, 2); + mesh->SetTexture(thumb->mTex); + float x0, y0, w0, h0; + thumb->GetTextureRect(&x0, &y0, &w0, &h0); + mesh->SetTextureRect(x0, y0, w0, h0); + mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); + mesh->SetDisplacement(0, 0, xy[0], xy[1], HGEDISP_NODE); + mesh->SetDisplacement(1, 0, xy[2] - w0, xy[3], HGEDISP_NODE); + mesh->SetDisplacement(0, 1, xy[4], xy[5] - h0, HGEDISP_NODE); + mesh->SetDisplacement(1, 1, xy[6] - w0, xy[7] - h0, HGEDISP_NODE); + mesh->SetColor(1, 1, ARGB(255,100,100,100)); + mesh->SetColor(0, 1, ARGB(255,100,100,100)); + mesh->SetColor(1, 0, ARGB(255,100,100,100)); + mesh->SetColor(0, 0, ARGB(255,200,200,200)); + } + else + { + mesh = NULL; + } } -void ShopItem::Render(){ - if (mHasFocus){ - mFont->SetColor(ARGB(255,255,255,0)); - }else{ - mFont->SetColor(ARGB(255,255,255,255)); - } - if (!quantity){ - mFont->SetColor(ARGB(255,128,128,128)); - } - - if (card){ - if (nameCount){ - char buffer[512]; - sprintf(buffer, "%s (%i)", _(card->data->name).c_str(), nameCount ); - mText = buffer; - }else{ - mText = _(card->data->name).c_str(); +void ShopItem::Render() +{ + if (mHasFocus) + { + mFont->SetColor(ARGB(255,255,255,0)); } - } - - JRenderer * renderer = JRenderer::GetInstance(); - - if (mesh){ - mesh->Render(0,0); - }else{ - //ERROR Management - } - if (mHasFocus){ - if (card) quad = resources.RetrieveCard(card); - if (quad){ - float scale = 0.9 * 285/ quad->mHeight; - quad->SetColor(ARGB(255,255,255,255)); - renderer->RenderQuad(quad,SCREEN_WIDTH - 105,SCREEN_HEIGHT/2 - 5,0, scale,scale); - }else{ - if (card) CardGui::alternateRender(card,Pos(SCREEN_WIDTH - 105,SCREEN_HEIGHT/2 - 5,0.9f* 285/250, 0,255)); - + else + { + mFont->SetColor(ARGB(255,255,255,255)); + } + if (!quantity) + { + mFont->SetColor(ARGB(255,128,128,128)); + } + + if (card) + { + if (nameCount) + { + char buffer[512]; + sprintf(buffer, "%s (%i)", _(card->data->name).c_str(), nameCount); + mText = buffer; + } + else + { + mText = _(card->data->name).c_str(); + } + } + + JRenderer * renderer = JRenderer::GetInstance(); + + if (mesh) + { + mesh->Render(0, 0); + } + else + { + //ERROR Management + } + if (mHasFocus) + { + if (card) quad = resources.RetrieveCard(card); + if (quad) + { + float scale = 0.9 * 285 / quad->mHeight; + quad->SetColor(ARGB(255,255,255,255)); + renderer->RenderQuad(quad, SCREEN_WIDTH - 105, SCREEN_HEIGHT / 2 - 5, 0, scale, scale); + } + else + { + if (card) CardGui::alternateRender(card, Pos(SCREEN_WIDTH - 105, SCREEN_HEIGHT / 2 - 5, 0.9f * 285 / 250, 0, 255)); + + } } - } } void ShopItem::Update(float dt) { - if (mScale < mTargetScale){ - mScale += 8.0f*dt; - if (mScale > mTargetScale) - mScale = mTargetScale; - }else if (mScale > mTargetScale){ - mScale -= 8.0f*dt; - if (mScale < mTargetScale) - mScale = mTargetScale; - } + if (mScale < mTargetScale) + { + mScale += 8.0f * dt; + if (mScale > mTargetScale) mScale = mTargetScale; + } + else if (mScale > mTargetScale) + { + mScale -= 8.0f * dt; + if (mScale < mTargetScale) mScale = mTargetScale; + } } - - - void ShopItem::Entering() { - for (int i = 0; i < 2; ++i){ - for (int j = 0; j < 2; ++j){ - mesh->SetColor(i,j,ARGB(255,255,255,255)); + for (int i = 0; i < 2; ++i) + { + for (int j = 0; j < 2; ++j) + { + mesh->SetColor(i, j, ARGB(255,255,255,255)); + } } - } - - mHasFocus = true; - mTargetScale = 1.2f; + mHasFocus = true; + mTargetScale = 1.2f; } - bool ShopItem::Leaving(JButton key) { - mesh->SetColor(1,1,ARGB(255,100,100,100)); - mesh->SetColor(0,1,ARGB(255,100,100,100)); - mesh->SetColor(1,0,ARGB(255,100,100,100)); - mesh->SetColor(0,0,ARGB(255,200,200,200)); + mesh->SetColor(1, 1, ARGB(255,100,100,100)); + mesh->SetColor(0, 1, ARGB(255,100,100,100)); + mesh->SetColor(1, 0, ARGB(255,100,100,100)); + mesh->SetColor(0, 0, ARGB(255,200,200,200)); - mHasFocus = false; - mTargetScale = 1.0f; - return true; + mHasFocus = false; + mTargetScale = 1.0f; + return true; } - bool ShopItem::ButtonPressed() { - return (quantity >0); + return (quantity > 0); } - -ShopItems::ShopItems(int id, JGuiListener* listener, WFont* font, int x, int y, MTGAllCards * _collection, int _setIds[]): JGuiController(id, listener), mX(x), mY(y), mFont(font), collection(_collection){ - mHeight = 0; - showPriceDialog = -1; - dialog = NULL; - pricelist = NEW PriceList(RESPATH"/settings/prices.dat",_collection); - playerdata = NEW PlayerData(_collection); - display = NULL; - for (int i=0; i < SHOP_BOOSTERS; i++){ - setIds[i] = _setIds[i]; - }; - myCollection = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), _collection)); - showCardList = true; - - mBgAA = NULL; - mBgAATex = resources.RetrieveTexture("shop_aliasing.png",RETRIEVE_LOCK); - if(mBgAATex){ - mBgAA = resources.RetrieveQuad("shop_aliasing.png"); - mBgAA->SetTextureRect(0,1,250,119); - } - - lightAlpha = 0; - alphaChange = 0; -} - - - -void ShopItems::Add(int cardid){ - int rnd = (rand() % 20); - int price = pricelist->getPrice(cardid); - price = price + price * (rnd -10)/100; - float xy[] = {_x1[mCount],_y1[mCount],_x2[mCount],_y2[mCount],_x3[mCount],_y3[mCount],_x4[mCount],_y4[mCount]}; - JGuiController::Add(NEW ShopItem(mCount, mFont, cardid, xy, (mCount == 0),collection, price,myCollection)); - mHeight += 22; -} - -void ShopItems::Add(char * text, JQuad * quad,JQuad * thumb, int price){ - float xy[] = {_x1[mCount],_y1[mCount],_x2[mCount],_y2[mCount],_x3[mCount],_y3[mCount],_x4[mCount],_y4[mCount]}; - JGuiController::Add(NEW ShopItem(mCount, mFont, text, quad, thumb, xy, (mCount == 0), price)); - mHeight += 22; -} - -void ShopItems::Update(float dt){ - - if (display){ - display->Update(dt); - }else{ - if (showPriceDialog!=-1){ - ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]); - int price = item->price; - char buffer[4096]; - sprintf(buffer,"%s : %i credits",item->getText(),price); - if(!dialog){ - dialog = NEW SimpleMenu(1,this,Constants::MENU_FONT,SCREEN_WIDTH-300,SCREEN_HEIGHT/2,buffer); - dialog->Add(1,"Yes"); - dialog->Add(2,"No"); - if(options[Options::CHEATMODE].number) { - dialog->Add(3,"*Steal 1,000 credits*"); - } - } - else{ - dialog->Update(dt); - } - }else{ - SAFE_DELETE(dialog); - JGuiController::Update(dt); - } - - } - - alphaChange = (500 - (rand() % 1000)) * dt; - lightAlpha+= alphaChange; - if (lightAlpha < 0) lightAlpha = 0; - if (lightAlpha > 50) lightAlpha = 50; -} - - -void ShopItems::Render(){ - JGuiController::Render(); - JRenderer * r = JRenderer::GetInstance(); - - - if (mBgAA) - r->RenderQuad(mBgAA,0,SCREEN_HEIGHT-127); - - JQuad * quad = resources.RetrieveTempQuad("shop_light.jpg",TEXTURE_SUB_5551); - if (quad){ - r->EnableTextureFilter(false); - r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); - quad->SetColor(ARGB(lightAlpha,255,255,255)); - r->RenderQuad(quad,0,0); - r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - r->EnableTextureFilter(true); - } - - - if (display) display->Render(); - - if (showPriceDialog!=-1){ - if(dialog){ - dialog->Render(); - } - } - - mFont->SetColor(ARGB(255,255,255,255)); - char c[4096]; - r->FillRect(0,SCREEN_HEIGHT-17,SCREEN_WIDTH,17,ARGB(128,0,0,0)); - sprintf(c, "%s", _("[]:other cards").c_str()); - unsigned int len = 4 + mFont->GetStringWidth(c); - mFont->DrawString(c,SCREEN_WIDTH-len,SCREEN_HEIGHT-14); - - char credits[512]; - sprintf(credits,_("credits: %i").c_str(), playerdata->credits); - mFont->SetColor(ARGB(200,0,0,0)); - mFont->DrawString(credits, 5, SCREEN_HEIGHT - 12); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(credits, 5, SCREEN_HEIGHT - 14); - - if(mCurr >= 0){ - mFont->SetColor(ARGB(255,255,255,0)); - ShopItem * item = ((ShopItem *)mObjects[mCurr]); - mFont->DrawString(item->mText.c_str(), SCREEN_WIDTH/2 - 50, SCREEN_HEIGHT - 14,JGETEXT_CENTER); - mFont->SetColor(ARGB(255,255,255,255)); - } - - if (showCardList){ - r->FillRoundRect(290,5, 160, mCount * 20 + 15,5,ARGB(200,0,0,0)); - - for (int i = 0; i< mCount; ++i){ - if (!mObjects[i]) continue; - ShopItem * s = (ShopItem *)(mObjects[i]); - if (i == mCurr) mFont->SetColor(ARGB(255,255,255,0)); - else mFont->SetColor(ARGB(255,255,255,255)); - char buffer[512]; - sprintf(buffer, "%s", s->getText()); - float x = 300; - float y = 10 + 20*i; - mFont->DrawString(buffer,x,y); - } - } -} - -void ShopItems::pricedialog(int id, int mode){ - if (mode){ - showPriceDialog = id; - }else{ +ShopItems::ShopItems(int id, JGuiListener* listener, WFont* font, int x, int y, MTGAllCards * _collection, int _setIds[]) : + JGuiController(id, listener), mX(x), mY(y), mFont(font), collection(_collection) +{ + mHeight = 0; showPriceDialog = -1; - } + dialog = NULL; + pricelist = NEW PriceList(RESPATH"/settings/prices.dat", _collection); + playerdata = NEW PlayerData(_collection); + display = NULL; + for (int i = 0; i < SHOP_BOOSTERS; i++) + { + setIds[i] = _setIds[i]; + }; + myCollection = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), _collection)); + showCardList = true; + + mBgAA = NULL; + mBgAATex = resources.RetrieveTexture("shop_aliasing.png", RETRIEVE_LOCK); + if (mBgAATex) + { + mBgAA = resources.RetrieveQuad("shop_aliasing.png"); + mBgAA->SetTextureRect(0, 1, 250, 119); + } + + lightAlpha = 0; + alphaChange = 0; } -void ShopItems::ButtonPressed(int controllerId, int controlId){ - if (controllerId == 12){ - safeDeleteDisplay(); - return; - } +void ShopItems::Add(int cardid) +{ + int rnd = (rand() % 20); + int price = pricelist->getPrice(cardid); + price = price + price * (rnd - 10) / 100; + float xy[] = { _x1[mCount], _y1[mCount], _x2[mCount], _y2[mCount], _x3[mCount], _y3[mCount], _x4[mCount], _y4[mCount] }; + JGuiController::Add(NEW ShopItem(mCount, mFont, cardid, xy, (mCount == 0), collection, price, myCollection)); + mHeight += 22; +} - ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]); - int price = item->price; - switch(controlId){ - case 1: - if (playerdata->credits >= price){ - playerdata->credits -= price; - if (item->card){ - int rnd = (rand() % 25); - price = price + (rnd * price)/100; - pricelist->setPrice(item->card->getMTGId(),price); - playerdata->collection->add(item->card); - item->quantity--; - myCollection->Add(item->card); - item->nameCount++; - item->price = price; - }else{ - safeDeleteDisplay(); - display = NEW CardDisplay(12,NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT/2,this,NULL,5); +void ShopItems::Add(char * text, JQuad * quad, JQuad * thumb, int price) +{ + float xy[] = { _x1[mCount], _y1[mCount], _x2[mCount], _y2[mCount], _x3[mCount], _y3[mCount], _x4[mCount], _y4[mCount] }; + JGuiController::Add(NEW ShopItem(mCount, mFont, text, quad, thumb, xy, (mCount == 0), price)); + mHeight += 22; +} - MTGDeck * tempDeck = NEW MTGDeck(playerdata->collection->database); - int rare_or_mythic = Constants::RARITY_R; - int rnd = rand() % 8; - if (rnd == 0) rare_or_mythic = Constants::RARITY_M; - int sets[] = {setIds[showPriceDialog]}; - MTGSetInfo* si = setlist.getInfo(setIds[showPriceDialog]); +void ShopItems::Update(float dt) +{ - tempDeck->addRandomCards(si->booster[MTGSetInfo::RARE], sets,1,rare_or_mythic); - tempDeck->addRandomCards(si->booster[MTGSetInfo::UNCOMMON], sets,1,Constants::RARITY_U); - tempDeck->addRandomCards(si->booster[MTGSetInfo::COMMON], sets,1,Constants::RARITY_C); - tempDeck->addRandomCards(si->booster[MTGSetInfo::LAND], sets,1,Constants::RARITY_L); - - //Check for duplicates. Does not guarentee none, just makes them extremely unlikely. - //Code is kind of inefficient, but shouldn't be used often enough to matter. - int loops=0; - for(map::iterator it = tempDeck->cards.begin();it!= tempDeck->cards.end() && loops < 15;it++,loops++){ - int dupes = it->second - 1; - if(dupes <= 0) - continue; - - for(int x=0;xremove(it->first); - - int rarity = (int) tempDeck->database->getCardById(it->first)->getRarity(); - tempDeck->addRandomCards(dupes,sets,1,rarity); - it = tempDeck->cards.begin(); - } - - playerdata->collection->add(tempDeck); - myCollection->Add(tempDeck); - - for (int j = 0; j < mCount; j++){ - ShopItem * si = ((ShopItem *)mObjects[j]); - si->updateCount(myCollection); - } - - int i = 0; - for(int cycle=0;cycle<4;cycle++) - for (map::iterator it = tempDeck->cards.begin(); it!=tempDeck->cards.end(); it++){ - MTGCard * c = tempDeck->getCardById(it->first); - char rarity = c->getRarity(); - if((cycle == 0 && rarity == Constants::RARITY_L) - || (cycle == 1 && rarity == Constants::RARITY_C) - || (cycle == 2 && rarity == Constants::RARITY_U) - || (cycle == 3 && (rarity == Constants::RARITY_R || rarity == Constants::RARITY_M))) - for (int j = 0; j < it->second; j++){ - MTGCardInstance * card = NEW MTGCardInstance(c, NULL); - displayCards[i] = card; - display->AddCard(card); - i++; + if (display) + { + display->Update(dt); + } + else + { + if (showPriceDialog != -1) + { + ShopItem * item = ((ShopItem *) mObjects[showPriceDialog]); + int price = item->price; + char buffer[4096]; + sprintf(buffer, "%s : %i credits", item->getText(), price); + if (!dialog) + { + dialog = NEW SimpleMenu(1, this, Constants::MENU_FONT, SCREEN_WIDTH - 300, SCREEN_HEIGHT / 2, buffer); + dialog->Add(1, "Yes"); + dialog->Add(2, "No"); + if (options[Options::CHEATMODE].number) + { + dialog->Add(3, "*Steal 1,000 credits*"); + } + } + else + { + dialog->Update(dt); } } - delete tempDeck; - } - //Check if we just scored an award... - if(myCollection && myCollection->totalPrice() > 10000){ - GameOptionAward * goa = dynamic_cast(&options[Options::AWARD_COLLECTOR]); - if(goa) - goa->giveAward(); - } - showPriceDialog = -1; - }else{ - //error not enough money + else + { + SAFE_DELETE(dialog); + JGuiController::Update(dt); + } + } - break; - case 2: - if (item->card){ - int rnd = (rand() % 25); - price = price - (rnd * price)/100; - pricelist->setPrice(item->card->getMTGId(),price); + + alphaChange = (500 - (rand() % 1000)) * dt; + lightAlpha += alphaChange; + if (lightAlpha < 0) lightAlpha = 0; + if (lightAlpha > 50) lightAlpha = 50; +} + +void ShopItems::Render() +{ + JGuiController::Render(); + JRenderer * r = JRenderer::GetInstance(); + + if (mBgAA) r->RenderQuad(mBgAA, 0, SCREEN_HEIGHT - 127); + + JQuad * quad = resources.RetrieveTempQuad("shop_light.jpg", TEXTURE_SUB_5551); + if (quad) + { + r->EnableTextureFilter(false); + r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); + quad->SetColor(ARGB(lightAlpha,255,255,255)); + r->RenderQuad(quad, 0, 0); + r->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + r->EnableTextureFilter(true); + } + + if (display) display->Render(); + + if (showPriceDialog != -1) + { + if (dialog) + { + dialog->Render(); + } + } + + mFont->SetColor(ARGB(255,255,255,255)); + char c[4096]; + r->FillRect(0, SCREEN_HEIGHT - 17, SCREEN_WIDTH, 17, ARGB(128,0,0,0)); + sprintf(c, "%s", _("[]:other cards").c_str()); + unsigned int len = 4 + mFont->GetStringWidth(c); + mFont->DrawString(c, SCREEN_WIDTH - len, SCREEN_HEIGHT - 14); + + char credits[512]; + sprintf(credits, _("credits: %i").c_str(), playerdata->credits); + mFont->SetColor(ARGB(200,0,0,0)); + mFont->DrawString(credits, 5, SCREEN_HEIGHT - 12); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(credits, 5, SCREEN_HEIGHT - 14); + + if (mCurr >= 0) + { + mFont->SetColor(ARGB(255,255,255,0)); + ShopItem * item = ((ShopItem *) mObjects[mCurr]); + mFont->DrawString(item->mText.c_str(), SCREEN_WIDTH / 2 - 50, SCREEN_HEIGHT - 14, JGETEXT_CENTER); + mFont->SetColor(ARGB(255,255,255,255)); + } + + if (showCardList) + { + r->FillRoundRect(290, 5, 160, mCount * 20 + 15, 5, ARGB(200,0,0,0)); + + for (int i = 0; i < mCount; ++i) + { + if (!mObjects[i]) continue; + ShopItem * s = (ShopItem *) (mObjects[i]); + if (i == mCurr) + mFont->SetColor(ARGB(255,255,255,0)); + else + mFont->SetColor(ARGB(255,255,255,255)); + char buffer[512]; + sprintf(buffer, "%s", s->getText()); + float x = 300; + float y = 10 + 20 * i; + mFont->DrawString(buffer, x, y); + } } - showPriceDialog = -1; - break; - case 3: // (PSY) Cheatmode: get free money - playerdata->credits += 1000; - break; - } } - -void ShopItems::safeDeleteDisplay(){ - if (!display) return; - for (int i = 0; i < display->mCount; i++){ - delete displayCards[i]; - } - SAFE_DELETE(display); +void ShopItems::pricedialog(int id, int mode) +{ + if (mode) + { + showPriceDialog = id; + } + else + { + showPriceDialog = -1; + } } -void ShopItems::saveAll(){ - savePriceList(); - playerdata->save(); +void ShopItems::ButtonPressed(int controllerId, int controlId) +{ + if (controllerId == 12) + { + safeDeleteDisplay(); + return; + } + + ShopItem * item = ((ShopItem *) mObjects[showPriceDialog]); + int price = item->price; + switch (controlId) + { + case 1: + if (playerdata->credits >= price) + { + playerdata->credits -= price; + if (item->card) + { + int rnd = (rand() % 25); + price = price + (rnd * price) / 100; + pricelist->setPrice(item->card->getMTGId(), price); + playerdata->collection->add(item->card); + item->quantity--; + myCollection->Add(item->card); + item->nameCount++; + item->price = price; + } + else + { + safeDeleteDisplay(); + display = NEW CardDisplay(12, NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT / 2, this, NULL, 5); + + MTGDeck * tempDeck = NEW MTGDeck(playerdata->collection->database); + int rare_or_mythic = Constants::RARITY_R; + int rnd = rand() % 8; + if (rnd == 0) rare_or_mythic = Constants::RARITY_M; + int sets[] = { setIds[showPriceDialog] }; + MTGSetInfo* si = setlist.getInfo(setIds[showPriceDialog]); + + tempDeck->addRandomCards(si->booster[MTGSetInfo::RARE], sets, 1, rare_or_mythic); + tempDeck->addRandomCards(si->booster[MTGSetInfo::UNCOMMON], sets, 1, Constants::RARITY_U); + tempDeck->addRandomCards(si->booster[MTGSetInfo::COMMON], sets, 1, Constants::RARITY_C); + tempDeck->addRandomCards(si->booster[MTGSetInfo::LAND], sets, 1, Constants::RARITY_L); + + //Check for duplicates. Does not guarentee none, just makes them extremely unlikely. + //Code is kind of inefficient, but shouldn't be used often enough to matter. + int loops = 0; + for (map::iterator it = tempDeck->cards.begin(); it != tempDeck->cards.end() && loops < 15; it++, loops++) + { + int dupes = it->second - 1; + if (dupes <= 0) continue; + + for (int x = 0; x < dupes; x++) + tempDeck->remove(it->first); + + int rarity = (int) tempDeck->database->getCardById(it->first)->getRarity(); + tempDeck->addRandomCards(dupes, sets, 1, rarity); + it = tempDeck->cards.begin(); + } + + playerdata->collection->add(tempDeck); + myCollection->Add(tempDeck); + + for (int j = 0; j < mCount; j++) + { + ShopItem * si = ((ShopItem *) mObjects[j]); + si->updateCount(myCollection); + } + + int i = 0; + for (int cycle = 0; cycle < 4; cycle++) + for (map::iterator it = tempDeck->cards.begin(); it != tempDeck->cards.end(); it++) + { + MTGCard * c = tempDeck->getCardById(it->first); + char rarity = c->getRarity(); + if ((cycle == 0 && rarity == Constants::RARITY_L) || (cycle == 1 && rarity == Constants::RARITY_C) + || (cycle == 2 && rarity == Constants::RARITY_U) || (cycle == 3 && (rarity + == Constants::RARITY_R || rarity == Constants::RARITY_M))) for (int j = 0; j < it->second; j++) + { + MTGCardInstance * card = NEW MTGCardInstance(c, NULL); + displayCards[i] = card; + display->AddCard(card); + i++; + } + } + delete tempDeck; + } + //Check if we just scored an award... + if (myCollection && myCollection->totalPrice() > 10000) + { + GameOptionAward * goa = dynamic_cast (&options[Options::AWARD_COLLECTOR]); + if (goa) goa->giveAward(); + } + showPriceDialog = -1; + } + else + { + //error not enough money + } + break; + case 2: + if (item->card) + { + int rnd = (rand() % 25); + price = price - (rnd * price) / 100; + pricelist->setPrice(item->card->getMTGId(), price); + } + showPriceDialog = -1; + break; + case 3: // (PSY) Cheatmode: get free money + playerdata->credits += 1000; + break; + } } -void ShopItems::savePriceList(){ - pricelist->save(); +void ShopItems::safeDeleteDisplay() +{ + if (!display) return; + for (int i = 0; i < display->mCount; i++) + { + delete displayCards[i]; + } + SAFE_DELETE(display); } -ShopItems::~ShopItems(){ - SAFE_DELETE(pricelist); - SAFE_DELETE(playerdata); - SAFE_DELETE(dialog); - safeDeleteDisplay(); - SAFE_DELETE(myCollection); - resources.Release(mBgAATex); +void ShopItems::saveAll() +{ + savePriceList(); + playerdata->save(); +} + +void ShopItems::savePriceList() +{ + pricelist->save(); +} + +ShopItems::~ShopItems() +{ + SAFE_DELETE(pricelist); + SAFE_DELETE(playerdata); + SAFE_DELETE(dialog); + safeDeleteDisplay(); + SAFE_DELETE(myCollection); + resources.Release(mBgAATex); } ostream& ShopItem::toString(ostream& out) const { - return out << "ShopItem ::: mHasFocus : " << mHasFocus - << " ; mFont : " << mFont - << " ; mText : " << mText - << " ; quad : " << quad - << " ; thumb : " << thumb - << " ; mScale : " << mScale - << " ; mTargetScale : " << mTargetScale - << " ; nameCount : " << nameCount - << " ; quantity : " << quantity - << " ; card : " << card - << " ; price : " << price; + return out << "ShopItem ::: mHasFocus : " << mHasFocus << " ; mFont : " << mFont << " ; mText : " << mText << " ; quad : " + << quad << " ; thumb : " << thumb << " ; mScale : " << mScale << " ; mTargetScale : " << mTargetScale + << " ; nameCount : " << nameCount << " ; quantity : " << quantity << " ; card : " << card << " ; price : " + << price; } -bool ShopItems::CheckUserInput(JButton key){ - if (display && display->CheckUserInput(key)) - return true; - if (showPriceDialog == -1) { - JButton buttons[] = {JGE_BTN_LEFT, JGE_BTN_DOWN, JGE_BTN_RIGHT, JGE_BTN_UP, JGE_BTN_OK}; - for (int i = 0; i < 5; ++i) - if (key == buttons[i]) - showCardList = false; +bool ShopItems::CheckUserInput(JButton key) +{ + if (display && display->CheckUserInput(key)) return true; + if (showPriceDialog == -1) + { + JButton buttons[] = { JGE_BTN_LEFT, JGE_BTN_DOWN, JGE_BTN_RIGHT, JGE_BTN_UP, JGE_BTN_OK }; + for (int i = 0; i < 5; ++i) + if (key == buttons[i]) showCardList = false; - if (key == JGE_BTN_CANCEL) { - options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; - vector::iterator it; - for(it=mObjects.begin();it!=mObjects.end();it++){ - ShopItem * si = dynamic_cast(*it); - if(si) - si->updateThumb(); + if (key == JGE_BTN_CANCEL) + { + options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; + vector::iterator it; + for (it = mObjects.begin(); it != mObjects.end(); it++) + { + ShopItem * si = dynamic_cast (*it); + if (si) si->updateThumb(); + } + return true; + } + if (key == JGE_BTN_SEC) + { + showCardList = !showCardList; + return true; } - return true; } - if (key == JGE_BTN_SEC){ - showCardList = !showCardList; - return true; - } - } - else if(dialog) - return dialog->CheckUserInput(key); + else if (dialog) return dialog->CheckUserInput(key); - return JGuiController::CheckUserInput(key); + return JGuiController::CheckUserInput(key); } diff --git a/projects/mtg/src/SimpleMenu.cpp b/projects/mtg/src/SimpleMenu.cpp index 1fc951c81..c06d7a2a1 100644 --- a/projects/mtg/src/SimpleMenu.cpp +++ b/projects/mtg/src/SimpleMenu.cpp @@ -8,10 +8,10 @@ namespace { - const float kPoleWidth = 7; - const float kVerticalMargin = 16; - const float kHorizontalMargin = 30; - const float kLineHeight = 20; + const float kPoleWidth = 7; + const float kVerticalMargin = 16; + const float kHorizontalMargin = 30; + const float kLineHeight = 20; } JQuad* SimpleMenu::spadeR = NULL; @@ -25,162 +25,184 @@ JTexture* SimpleMenu::sideTex = NULL; WFont* SimpleMenu::titleFont = NULL; hgeParticleSystem* SimpleMenu::stars = NULL; -SimpleMenu::SimpleMenu(int id, JGuiListener* listener, int fontId, float x, float y, const char * _title, int _maxItems): JGuiController(id, listener), fontId(fontId){ - autoTranslate = true; - mHeight = 2 * kVerticalMargin; - mWidth = 0; - mX = x; - mY = y; - title = _(_title); - startId = 0; - maxItems = _maxItems; - selectionT = 0; - timeOpen = 0; - closed = false; - selectionTargetY = selectionY = y + kVerticalMargin; +SimpleMenu::SimpleMenu(int id, JGuiListener* listener, int fontId, float x, float y, const char * _title, int _maxItems) : + JGuiController(id, listener), fontId(fontId) +{ + autoTranslate = true; + mHeight = 2 * kVerticalMargin; + mWidth = 0; + mX = x; + mY = y; + title = _(_title); + startId = 0; + maxItems = _maxItems; + selectionT = 0; + timeOpen = 0; + closed = false; + selectionTargetY = selectionY = y + kVerticalMargin; - JRenderer* renderer = JRenderer::GetInstance(); + JRenderer* renderer = JRenderer::GetInstance(); - if (!spadeLTex) spadeLTex= resources.RetrieveTexture("spade_ul.png", RETRIEVE_MANAGE); - if (!spadeRTex) spadeRTex = resources.RetrieveTexture("spade_ur.png", RETRIEVE_MANAGE); - if (!jewelTex) jewelTex= renderer->CreateTexture(5, 5, TEX_TYPE_USE_VRAM); - if (!sideTex) sideTex = resources.RetrieveTexture("menuside.png", RETRIEVE_MANAGE); - if (NULL == spadeL) spadeL = resources.RetrieveQuad("spade_ul.png", 0, 0, 11, 11, "spade_ul", RETRIEVE_MANAGE); - if (NULL == spadeR) spadeR = resources.RetrieveQuad("spade_ur.png", 0, 0, 11, 11, "spade_ur", RETRIEVE_MANAGE); - if (NULL == jewel) jewel = NEW JQuad(jewelTex, 1, 1, 3, 3); - if (NULL == side) side = resources.RetrieveQuad("menuside.png", 1, 1, 1, 7,"menuside", RETRIEVE_MANAGE); + if (!spadeLTex) spadeLTex = resources.RetrieveTexture("spade_ul.png", RETRIEVE_MANAGE); + if (!spadeRTex) spadeRTex = resources.RetrieveTexture("spade_ur.png", RETRIEVE_MANAGE); + if (!jewelTex) jewelTex = renderer->CreateTexture(5, 5, TEX_TYPE_USE_VRAM); + if (!sideTex) sideTex = resources.RetrieveTexture("menuside.png", RETRIEVE_MANAGE); + if (NULL == spadeL) spadeL = resources.RetrieveQuad("spade_ul.png", 0, 0, 11, 11, "spade_ul", RETRIEVE_MANAGE); + if (NULL == spadeR) spadeR = resources.RetrieveQuad("spade_ur.png", 0, 0, 11, 11, "spade_ur", RETRIEVE_MANAGE); + if (NULL == jewel) jewel = NEW JQuad(jewelTex, 1, 1, 3, 3); + if (NULL == side) side = resources.RetrieveQuad("menuside.png", 1, 1, 1, 7, "menuside", RETRIEVE_MANAGE); - if (NULL == stars) - stars = NEW hgeParticleSystem(resources.RetrievePSI("stars.psi", resources.GetQuad("stars"))); + if (NULL == stars) stars = NEW hgeParticleSystem(resources.RetrievePSI("stars.psi", resources.GetQuad("stars"))); - stars->FireAt(mX, mY); + stars->FireAt(mX, mY); } void SimpleMenu::drawHorzPole(float x, float y, float width) { - JRenderer* renderer = JRenderer::GetInstance(); + JRenderer* renderer = JRenderer::GetInstance(); - float offset = (spadeR->mWidth - kPoleWidth) / 2; - renderer->RenderQuad(side, x, y, 0, width); - spadeR->SetHFlip(true); - spadeL->SetHFlip(false); - renderer->RenderQuad(spadeR, x - offset, y - offset); - renderer->RenderQuad(spadeL, x - offset + width, y - offset); + float offset = (spadeR->mWidth - kPoleWidth) / 2; + renderer->RenderQuad(side, x, y, 0, width); + spadeR->SetHFlip(true); + spadeL->SetHFlip(false); + renderer->RenderQuad(spadeR, x - offset, y - offset); + renderer->RenderQuad(spadeL, x - offset + width, y - offset); - renderer->RenderQuad(jewel, x, y - 1); - renderer->RenderQuad(jewel, x + width - 1, y - 1); + renderer->RenderQuad(jewel, x, y - 1); + renderer->RenderQuad(jewel, x + width - 1, y - 1); } void SimpleMenu::drawVertPole(float x, float y, float height) { - JRenderer* renderer = JRenderer::GetInstance(); + JRenderer* renderer = JRenderer::GetInstance(); - float offset = (spadeR->mHeight - kPoleWidth) / 2; - renderer->RenderQuad(side, x + kPoleWidth, y, M_PI/2, height); - spadeR->SetHFlip(false); - spadeL->SetHFlip(true); - renderer->RenderQuad(spadeR, x + kPoleWidth + offset, y - offset, M_PI/2); - renderer->RenderQuad(spadeL, x + kPoleWidth + offset, y - offset + height, M_PI/2); + float offset = (spadeR->mHeight - kPoleWidth) / 2; + renderer->RenderQuad(side, x + kPoleWidth, y, M_PI / 2, height); + spadeR->SetHFlip(false); + spadeL->SetHFlip(true); + renderer->RenderQuad(spadeR, x + kPoleWidth + offset, y - offset, M_PI / 2); + renderer->RenderQuad(spadeL, x + kPoleWidth + offset, y - offset + height, M_PI / 2); - renderer->RenderQuad(jewel, x - 1, y - 1); - renderer->RenderQuad(jewel, x - 1, y + height - 1); + renderer->RenderQuad(jewel, x - 1, y - 1); + renderer->RenderQuad(jewel, x - 1, y + height - 1); } -void SimpleMenu::Render() { - WFont * titleFont = resources.GetWFont(Fonts::SMALLFACE_FONT); - WFont * mFont = resources.GetWFont(fontId); - if (0 == mWidth) { - float sY = mY + kVerticalMargin; - for (int i = startId; i < startId + mCount; ++i) { - float width = (static_cast(mObjects[i]))->GetWidth(); - if (mWidth < width) mWidth = width; +void SimpleMenu::Render() +{ + WFont * titleFont = resources.GetWFont(Fonts::SMALLFACE_FONT); + WFont * mFont = resources.GetWFont(fontId); + if (0 == mWidth) + { + float sY = mY + kVerticalMargin; + for (int i = startId; i < startId + mCount; ++i) + { + float width = (static_cast (mObjects[i]))->GetWidth(); + if (mWidth < width) mWidth = width; + } + if ((!title.empty()) && (mWidth < titleFont->GetStringWidth(title.c_str()))) mWidth = titleFont->GetStringWidth( + title.c_str()); + mWidth += 2 * kHorizontalMargin; + for (int i = startId; i < startId + mCount; ++i) + { + float y = mY + kVerticalMargin + i * kLineHeight; + SimpleMenuItem * smi = static_cast (mObjects[i]); + smi->Relocate(mX + mWidth / 2, y); + if (smi->hasFocus()) sY = y; + } + stars->Fire(); + selectionTargetY = selectionY = sY; + timeOpen = 0; } - if ((!title.empty()) && (mWidth < titleFont->GetStringWidth(title.c_str()))) mWidth = titleFont->GetStringWidth(title.c_str()); - mWidth += 2*kHorizontalMargin; - for (int i = startId; i < startId + mCount; ++i) { - float y = mY + kVerticalMargin + i * kLineHeight; - SimpleMenuItem * smi = static_cast(mObjects[i]); - smi->Relocate(mX + mWidth / 2, y); - if (smi->hasFocus()) sY = y; + + JRenderer * renderer = JRenderer::GetInstance(); + + float height = mHeight; + if (timeOpen < 1) height *= timeOpen > 0 ? timeOpen : -timeOpen; + + renderer->FillRect(mX, mY, mWidth, height, ARGB(180,0,0,0)); + + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + drawVertPole(mX, mY - 16, height + 32); + drawVertPole(mX + mWidth, mY - 16, height + 32); + drawHorzPole(mX - 16, mY, mWidth + 32); + drawHorzPole(mX - 25, mY + height, mWidth + 50); + + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); + stars->Render(); + renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + + mFont->SetScale(1.0f); + if (!title.empty()) titleFont->DrawString(title.c_str(), mX + mWidth / 2, mY - 3, JGETEXT_CENTER); + for (int i = startId; i < startId + maxItems; i++) + { + if (i > mCount - 1) break; + if ((static_cast (mObjects[i]))->mY - kLineHeight * startId < mY + height - kLineHeight + 7) + { + if (static_cast (mObjects[i])->hasFocus()) + { + resources.GetWFont(Fonts::MAIN_FONT)->DrawString(static_cast (mObjects[i])->desc.c_str(), mX + + mWidth + 10, mY + 15); + mFont->SetColor(ARGB(255,255,255,0)); + } + else + mFont->SetColor(ARGB(150,255,255,255)); + (static_cast (mObjects[i]))->RenderWithOffset(-kLineHeight * startId); + } } - stars->Fire(); - selectionTargetY = selectionY = sY; - timeOpen = 0; - } - - JRenderer * renderer = JRenderer::GetInstance(); - - float height = mHeight; - if (timeOpen < 1) height *= timeOpen > 0 ? timeOpen : -timeOpen; - - renderer->FillRect(mX, mY, mWidth, height, ARGB(180,0,0,0)); - - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - drawVertPole(mX, mY - 16, height + 32); - drawVertPole(mX + mWidth, mY - 16, height + 32); - drawHorzPole(mX - 16, mY, mWidth + 32); - drawHorzPole(mX - 25, mY + height, mWidth + 50); - - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); - stars->Render(); - renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - - mFont->SetScale(1.0f); - if (!title.empty()) - titleFont->DrawString(title.c_str(), mX+mWidth/2, mY - 3, JGETEXT_CENTER); - for (int i = startId; i < startId + maxItems ; i++){ - if (i > mCount-1) break; - if ((static_cast(mObjects[i]))->mY - kLineHeight * startId < mY + height - kLineHeight + 7) { - if (static_cast(mObjects[i])->hasFocus()){ - resources.GetWFont(Fonts::MAIN_FONT)->DrawString(static_cast(mObjects[i])->desc.c_str(),mX+mWidth+10,mY+15); - mFont->SetColor(ARGB(255,255,255,0)); - } else - mFont->SetColor(ARGB(150,255,255,255)); - (static_cast(mObjects[i]))->RenderWithOffset(-kLineHeight*startId); - } - } } -void SimpleMenu::Update(float dt){ - JGuiController::Update(dt); - if (mCurr > startId + maxItems-1) - startId = mCurr - maxItems +1; - else if (mCurr < startId) - startId = mCurr; - stars->Update(dt); - selectionT += 3*dt; - selectionY += (selectionTargetY - selectionY) * 8 * dt; - stars->MoveTo(mX + kHorizontalMargin + ((mWidth-2 * kHorizontalMargin) * (1+cos(selectionT))/2), - selectionY + 5 * cos( selectionT * 2.35f ) + kLineHeight / 2 - kLineHeight * startId); - if (timeOpen < 0) { - timeOpen += dt * 10; - if (timeOpen >= 0) { timeOpen = 0; closed = true; stars->FireAt(mX, mY); } - } else { - closed = false; - timeOpen += dt * 10; - } +void SimpleMenu::Update(float dt) +{ + JGuiController::Update(dt); + if (mCurr > startId + maxItems - 1) + startId = mCurr - maxItems + 1; + else if (mCurr < startId) startId = mCurr; + stars->Update(dt); + selectionT += 3 * dt; + selectionY += (selectionTargetY - selectionY) * 8 * dt; + stars->MoveTo(mX + kHorizontalMargin + ((mWidth - 2 * kHorizontalMargin) * (1 + cos(selectionT)) / 2), selectionY + 5 * cos( + selectionT * 2.35f) + kLineHeight / 2 - kLineHeight * startId); + if (timeOpen < 0) + { + timeOpen += dt * 10; + if (timeOpen >= 0) + { + timeOpen = 0; + closed = true; + stars->FireAt(mX, mY); + } + } + else + { + closed = false; + timeOpen += dt * 10; + } } -void SimpleMenu::Add(int id, const char * text,string desc, bool forceFocus){ - SimpleMenuItem * smi = NEW SimpleMenuItem(this, id, fontId, text, 0, mY + kVerticalMargin + mCount*kLineHeight, (mCount == 0), autoTranslate); - smi->desc = desc; - JGuiController::Add(smi); - if (mCount <= maxItems) mHeight += kLineHeight; - if (forceFocus){ - mObjects[mCurr]->Leaving(JGE_BTN_DOWN); - mCurr = mCount-1; - smi->Entering(); - } +void SimpleMenu::Add(int id, const char * text, string desc, bool forceFocus) +{ + SimpleMenuItem * smi = NEW SimpleMenuItem(this, id, fontId, text, 0, mY + kVerticalMargin + mCount * kLineHeight, + (mCount == 0), autoTranslate); + smi->desc = desc; + JGuiController::Add(smi); + if (mCount <= maxItems) mHeight += kLineHeight; + if (forceFocus) + { + mObjects[mCurr]->Leaving(JGE_BTN_DOWN); + mCurr = mCount - 1; + smi->Entering(); + } } void SimpleMenu::Close() { - timeOpen = -1.0; - stars->Stop(true); + timeOpen = -1.0; + stars->Stop(true); } -void SimpleMenu::destroy(){ - SAFE_DELETE(SimpleMenu::jewel); - SAFE_DELETE(SimpleMenu::stars); - SAFE_DELETE(SimpleMenu::jewelTex); +void SimpleMenu::destroy() +{ + SAFE_DELETE(SimpleMenu::jewel); + SAFE_DELETE(SimpleMenu::stars); + SAFE_DELETE(SimpleMenu::jewelTex); } diff --git a/projects/mtg/src/SimpleMenuItem.cpp b/projects/mtg/src/SimpleMenuItem.cpp index 9e30ea08b..54b3e5b01 100644 --- a/projects/mtg/src/SimpleMenuItem.cpp +++ b/projects/mtg/src/SimpleMenuItem.cpp @@ -4,91 +4,87 @@ #include "Translate.h" #include "WResourceManager.h" -SimpleMenuItem::SimpleMenuItem(SimpleMenu* _parent, int id, int fontId, string text, float x, float y, bool hasFocus, bool autoTranslate): JGuiObject(id), parent(_parent), fontId(fontId), mX(x), mY(y) +SimpleMenuItem::SimpleMenuItem(SimpleMenu* _parent, int id, int fontId, string text, float x, float y, bool hasFocus, bool autoTranslate) : + JGuiObject(id), parent(_parent), fontId(fontId), mX(x), mY(y) { - if (autoTranslate) mText = _(text); - else mText = text; - mHasFocus = hasFocus; + if (autoTranslate) + mText = _(text); + else + mText = text; + mHasFocus = hasFocus; - mScale = 1.0f; - mTargetScale = 1.0f; + mScale = 1.0f; + mTargetScale = 1.0f; - if (hasFocus) - Entering(); + if (hasFocus) Entering(); } - void SimpleMenuItem::RenderWithOffset(float yOffset) { - WFont * mFont = resources.GetWFont(fontId); - mFont->DrawString(mText.c_str(), mX, mY + yOffset, JGETEXT_CENTER); + WFont * mFont = resources.GetWFont(fontId); + mFont->DrawString(mText.c_str(), mX, mY + yOffset, JGETEXT_CENTER); } void SimpleMenuItem::Render() { - RenderWithOffset(0); + RenderWithOffset(0); } void SimpleMenuItem::Update(float dt) { if (mScale < mTargetScale) { - mScale += 8.0f*dt; - if (mScale > mTargetScale) - mScale = mTargetScale; + mScale += 8.0f * dt; + if (mScale > mTargetScale) mScale = mTargetScale; } - else if (mScale > mTargetScale) + else if (mScale > mTargetScale) { - mScale -= 8.0f*dt; - if (mScale < mTargetScale) - mScale = mTargetScale; - } + mScale -= 8.0f * dt; + if (mScale < mTargetScale) mScale = mTargetScale; + } } - void SimpleMenuItem::Entering() { - mHasFocus = true; - parent->selectionTargetY = mY; + mHasFocus = true; + parent->selectionTargetY = mY; } - bool SimpleMenuItem::Leaving(JButton key) { - mHasFocus = false; - return true; + mHasFocus = false; + return true; } - bool SimpleMenuItem::ButtonPressed() { - return true; + return true; } void SimpleMenuItem::Relocate(float x, float y) { - mX = x; - mY = y; + mX = x; + mY = y; } float SimpleMenuItem::GetWidth() { - WFont * mFont = resources.GetWFont(fontId); - mFont->SetScale(1.0); - return mFont->GetStringWidth(mText.c_str()); + WFont * mFont = resources.GetWFont(fontId); + mFont->SetScale(1.0); + return mFont->GetStringWidth(mText.c_str()); } bool SimpleMenuItem::hasFocus() { - return mHasFocus; + return mHasFocus; } ostream& SimpleMenuItem::toString(ostream& out) const { - return out << "SimpleMenuItem ::: mHasFocus : " << mHasFocus - << " ; parent : " << parent - << " ; mText : " << mText - << " ; mScale : " << mScale - << " ; mTargetScale : " << mTargetScale - << " ; mX,mY : " << mX << "," << mY; + return out << "SimpleMenuItem ::: mHasFocus : " << mHasFocus + << " ; parent : " << parent + << " ; mText : " << mText + << " ; mScale : " << mScale + << " ; mTargetScale : " << mTargetScale + << " ; mX,mY : " << mX << "," << mY; } diff --git a/projects/mtg/src/SimplePad.cpp b/projects/mtg/src/SimplePad.cpp index 2f385b57c..125f64602 100644 --- a/projects/mtg/src/SimplePad.cpp +++ b/projects/mtg/src/SimplePad.cpp @@ -5,7 +5,6 @@ #include "GameApp.h" #include "Translate.h" - #define ALPHA_COLUMNS 8 #define ALPHA_ROWS 8 @@ -14,417 +13,422 @@ #define KPD_LEFT 2 #define KPD_RIGHT 3 -SimpleKey::SimpleKey( string _ds, int _id){ - displayValue = _ds; id = _id; - for(int x=0;x<4;x++) - adjacency[x] = KPD_NOWHERE; +SimpleKey::SimpleKey(string _ds, int _id) +{ + displayValue = _ds; + id = _id; + for (int x = 0; x < 4; x++) + adjacency[x] = KPD_NOWHERE; } -void SimplePad::linkKeys(int from, int to, int dir){ +void SimplePad::linkKeys(int from, int to, int dir) +{ - if(keys[from] && keys[to]){ - keys[from]->adjacency[dir] = to; - switch(dir){ - case KPD_UP: - case KPD_LEFT: - dir++; - break; - default: - dir--; - } - keys[to]->adjacency[dir] = from; - } + if (keys[from] && keys[to]) + { + keys[from]->adjacency[dir] = to; + switch (dir) + { + case KPD_UP: + case KPD_LEFT: + dir++; + break; + default: + dir--; + } + keys[to]->adjacency[dir] = from; + } } -SimplePad::SimplePad(){ - nbitems = 0; - bActive = false; - selected = 0; - priorKey = 0; - cursor = 0; - bShowCancel = false; - bShowNumpad = false; - bCapslock = true; - char buf[2]; - buf[1] = '\0'; - SimpleKey * k; +SimplePad::SimplePad() +{ + nbitems = 0; + bActive = false; + selected = 0; + priorKey = 0; + cursor = 0; + bShowCancel = false; + bShowNumpad = false; + bCapslock = true; + char buf[2]; + buf[1] = '\0'; + SimpleKey * k; - for(int x=0;x KPD_A) - k->adjacency[KPD_LEFT] = idx-1; - if(idx < KPD_Z) - k->adjacency[KPD_RIGHT] = idx+1; - if(idx > ALPHA_COLUMNS) - k->adjacency[KPD_UP] = idx-1-ALPHA_COLUMNS; - else - k->adjacency[KPD_UP] = KPD_INPUT; - if(idx < 25-ALPHA_COLUMNS) - k->adjacency[KPD_DOWN] = idx+1+ALPHA_COLUMNS; - } + if (idx > KPD_A) k->adjacency[KPD_LEFT] = idx - 1; + if (idx < KPD_Z) k->adjacency[KPD_RIGHT] = idx + 1; + if (idx > ALPHA_COLUMNS) + k->adjacency[KPD_UP] = idx - 1 - ALPHA_COLUMNS; + else + k->adjacency[KPD_UP] = KPD_INPUT; + if (idx < 25 - ALPHA_COLUMNS) k->adjacency[KPD_DOWN] = idx + 1 + ALPHA_COLUMNS; + } - Add(_("Spacebar"),KPD_SPACE); - - for(int x=25-ALPHA_COLUMNS;x<26;x++) - keys[x]->adjacency[KPD_DOWN] = KPD_SPACE; + Add(_("Spacebar"), KPD_SPACE); - k=Add(_("Confirm"),KPD_OK); - keys[KPD_Z]->adjacency[KPD_RIGHT] = KPD_OK; - k->adjacency[KPD_UP] = KPD_CAPS; - k->adjacency[KPD_LEFT] = KPD_Z; - k->adjacency[KPD_DOWN] = KPD_CANCEL; + for (int x = 25 - ALPHA_COLUMNS; x < 26; x++) + keys[x]->adjacency[KPD_DOWN] = KPD_SPACE; - k=Add(_("Cancel"),KPD_CANCEL); - k->adjacency[KPD_UP] = KPD_OK; - k->adjacency[KPD_LEFT] = KPD_SPACE; + k = Add(_("Confirm"), KPD_OK); + keys[KPD_Z]->adjacency[KPD_RIGHT] = KPD_OK; + k->adjacency[KPD_UP] = KPD_CAPS; + k->adjacency[KPD_LEFT] = KPD_Z; + k->adjacency[KPD_DOWN] = KPD_CANCEL; - k=Add(_("Del"),KPD_DEL); - keys[KPD_I]->adjacency[KPD_RIGHT] = KPD_DEL; - k->adjacency[KPD_UP] = KPD_9; - k->adjacency[KPD_DOWN] = KPD_CAPS; - k->adjacency[KPD_LEFT] = KPD_I; - - k=Add(_("Caps"),KPD_CAPS); - keys[KPD_R]->adjacency[KPD_RIGHT] = KPD_CAPS; - keys[KPD_R]->adjacency[KPD_DOWN] = KPD_Z; - k->adjacency[KPD_UP] = KPD_DEL; - k->adjacency[KPD_DOWN] = KPD_OK; - k->adjacency[KPD_LEFT] = KPD_R; + k = Add(_("Cancel"), KPD_CANCEL); + k->adjacency[KPD_UP] = KPD_OK; + k->adjacency[KPD_LEFT] = KPD_SPACE; + k = Add(_("Del"), KPD_DEL); + keys[KPD_I]->adjacency[KPD_RIGHT] = KPD_DEL; + k->adjacency[KPD_UP] = KPD_9; + k->adjacency[KPD_DOWN] = KPD_CAPS; + k->adjacency[KPD_LEFT] = KPD_I; - for(int x=0;x<10;x++){ - buf[0] = '0'+x; - Add(buf,KPD_0+x); - if(x < 8) - linkKeys(KPD_0+x,KPD_A+x,KPD_DOWN); - if(x > 0) - linkKeys(KPD_0+x,KPD_0+x-1,KPD_LEFT); - } + k = Add(_("Caps"), KPD_CAPS); + keys[KPD_R]->adjacency[KPD_RIGHT] = KPD_CAPS; + keys[KPD_R]->adjacency[KPD_DOWN] = KPD_Z; + k->adjacency[KPD_UP] = KPD_DEL; + k->adjacency[KPD_DOWN] = KPD_OK; + k->adjacency[KPD_LEFT] = KPD_R; - keys[KPD_8]->adjacency[KPD_DOWN] = KPD_DEL; - keys[KPD_9]->adjacency[KPD_DOWN] = KPD_DEL; + for (int x = 0; x < 10; x++) + { + buf[0] = '0' + x; + Add(buf, KPD_0 + x); + if (x < 8) linkKeys(KPD_0 + x, KPD_A + x, KPD_DOWN); + if (x > 0) linkKeys(KPD_0 + x, KPD_0 + x - 1, KPD_LEFT); + } - keys[KPD_0]->adjacency[KPD_LEFT] = KPD_NOWHERE; - keys[KPD_A]->adjacency[KPD_LEFT] = KPD_NOWHERE; - keys[KPD_J]->adjacency[KPD_LEFT] = KPD_NOWHERE; - keys[KPD_S]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_8]->adjacency[KPD_DOWN] = KPD_DEL; + keys[KPD_9]->adjacency[KPD_DOWN] = KPD_DEL; + + keys[KPD_0]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_A]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_J]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_S]->adjacency[KPD_LEFT] = KPD_NOWHERE; } SimplePad::~SimplePad() { - for(int x=0;x= KPD_MAX) return NULL; -SimpleKey * SimplePad::Add(string display, unsigned char id){ - if(nbitems >= KPD_MAX) - return NULL; - - keys[nbitems++] = NEW SimpleKey(display,id); - return keys[nbitems-1]; + keys[nbitems++] = NEW SimpleKey(display, id); + return keys[nbitems - 1]; } -void SimplePad::pressKey(unsigned char key){ - string input = ""; +void SimplePad::pressKey(unsigned char key) +{ + string input = ""; - if(isalpha(key)) { - if(bCapslock) - input += toupper(key); - else - input += key; - - if(cursor < buffer.size()) - cursor++; + if (isalpha(key)) + { + if (bCapslock) + input += toupper(key); + else + input += key; - buffer.insert(cursor,input); + if (cursor < buffer.size()) cursor++; - //Auto swap capitalization - if(bCapslock && buffer.size() == 1) - bCapslock = !bCapslock; - } - else if(key == KPD_SPACE){ - if(cursor < buffer.size()) - cursor++; - buffer.insert(cursor," "); - } - else if(key == KPD_CAPS) - bCapslock = !bCapslock; - else if(key == KPD_DEL) { - if(!buffer.size()) - return; + buffer.insert(cursor, input); - if(cursor >= buffer.size()) { - cursor = buffer.size(); - buffer = buffer.substr(0,cursor-1); + //Auto swap capitalization + if (bCapslock && buffer.size() == 1) bCapslock = !bCapslock; + } + else if (key == KPD_SPACE) + { + if (cursor < buffer.size()) cursor++; + buffer.insert(cursor, " "); + } + else if (key == KPD_CAPS) + bCapslock = !bCapslock; + else if (key == KPD_DEL) + { + if (!buffer.size()) return; + + if (cursor >= buffer.size()) + { + cursor = buffer.size(); + buffer = buffer.substr(0, cursor - 1); + } + else + buffer = buffer.substr(0, cursor) + buffer.substr(cursor + 1); + + cursor--; + } + else if (key == KPD_OK) + Finish(); + else if (key == KPD_CANCEL) + { + bCanceled = true; + Finish(); } - else - buffer = buffer.substr(0,cursor) + buffer.substr(cursor+1); - - cursor--; - } - else if(key == KPD_OK) - Finish(); - else if(key == KPD_CANCEL) { - bCanceled = true; - Finish(); - } } void SimplePad::MoveSelection(unsigned char moveto) { - if(!bShowNumpad && moveto >= KPD_0 && moveto <= KPD_9 ) - moveto = KPD_INPUT; - else if(!bShowCancel && moveto == KPD_CANCEL ) - moveto = KPD_SPACE; + if (!bShowNumpad && moveto >= KPD_0 && moveto <= KPD_9) + moveto = KPD_INPUT; + else if (!bShowCancel && moveto == KPD_CANCEL) moveto = KPD_SPACE; - if (selected < KPD_MAX && selected >= 0) - priorKey = selected; + if (selected < KPD_MAX && selected >= 0) priorKey = selected; - if (moveto < KPD_MAX) - selected = moveto; - else if (moveto == KPD_INPUT) - selected = KPD_INPUT; + if (moveto < KPD_MAX) + selected = moveto; + else if (moveto == KPD_INPUT) selected = KPD_INPUT; } -void SimplePad::Update(float dt){ - JGE * mEngine = JGE::GetInstance(); - JButton key = mEngine->ReadButton(); +void SimplePad::Update(float dt) +{ + JGE * mEngine = JGE::GetInstance(); + JButton key = mEngine->ReadButton(); - //Start button changes capslock setting. - if (key == JGE_BTN_MENU) - { - if (selected != KPD_OK) - selected = KPD_OK; - else - Finish(); - } - else if (key == JGE_BTN_CTRL) - bCapslock = !bCapslock; - - if (selected == KPD_SPACE){ - if (bShowCancel && mEngine->GetButtonClick(JGE_BTN_RIGHT)) - selected = KPD_CANCEL; - else if (key == JGE_BTN_LEFT || key == JGE_BTN_RIGHT - || key == JGE_BTN_UP || key == JGE_BTN_DOWN) - selected = priorKey; - } //Moving within/from the text field. - else if (selected == KPD_INPUT){ - if (key == JGE_BTN_DOWN ) - selected = priorKey; - if (key == JGE_BTN_LEFT && cursor > 0) cursor--; - else if (key == JGE_BTN_RIGHT && cursor < buffer.size()) cursor++; - } - else if (selected >= 0 && keys[selected]){ - if (key == JGE_BTN_LEFT) - MoveSelection(keys[selected]->adjacency[KPD_LEFT]); - else if (key == JGE_BTN_RIGHT) - MoveSelection(keys[selected]->adjacency[KPD_RIGHT]); - if (key == JGE_BTN_DOWN) - MoveSelection(keys[selected]->adjacency[KPD_DOWN]); - else if (key == JGE_BTN_UP) - MoveSelection(keys[selected]->adjacency[KPD_UP]); - } - - - //These bits require a valid key... - if (selected >= 0 && selected < nbitems && keys[selected]) - if (key == JGE_BTN_OK) - pressKey(keys[selected]->id); - if (buffer.size() > 0 && key == JGE_BTN_SEC) - buffer = buffer.substr(0, buffer.size() - 1); - if (buffer.size() && key == JGE_BTN_PREV) { - if (cursor > 0) cursor--; - } - else if (key == JGE_BTN_NEXT) { - if (cursor < buffer.size()) - cursor++; - else { - buffer += ' '; - cursor = buffer.size(); + //Start button changes capslock setting. + if (key == JGE_BTN_MENU) + { + if (selected != KPD_OK) + selected = KPD_OK; + else + Finish(); } - } + else if (key == JGE_BTN_CTRL) bCapslock = !bCapslock; - mX = 50; - mY = 50; + if (selected == KPD_SPACE) + { + if (bShowCancel && mEngine->GetButtonClick(JGE_BTN_RIGHT)) + selected = KPD_CANCEL; + else if (key == JGE_BTN_LEFT || key == JGE_BTN_RIGHT || key == JGE_BTN_UP || key == JGE_BTN_DOWN) selected = priorKey; + } //Moving within/from the text field. + else if (selected == KPD_INPUT) + { + if (key == JGE_BTN_DOWN) selected = priorKey; + if (key == JGE_BTN_LEFT && cursor > 0) + cursor--; + else if (key == JGE_BTN_RIGHT && cursor < buffer.size()) cursor++; + } + else if (selected >= 0 && keys[selected]) + { + if (key == JGE_BTN_LEFT) + MoveSelection(keys[selected]->adjacency[KPD_LEFT]); + else if (key == JGE_BTN_RIGHT) MoveSelection(keys[selected]->adjacency[KPD_RIGHT]); + if (key == JGE_BTN_DOWN) + MoveSelection(keys[selected]->adjacency[KPD_DOWN]); + else if (key == JGE_BTN_UP) MoveSelection(keys[selected]->adjacency[KPD_UP]); + } - //Clear input buffer. - mEngine->ResetInput(); + //These bits require a valid key... + if (selected >= 0 && selected < nbitems && keys[selected]) if (key == JGE_BTN_OK) pressKey(keys[selected]->id); + if (buffer.size() > 0 && key == JGE_BTN_SEC) buffer = buffer.substr(0, buffer.size() - 1); + if (buffer.size() && key == JGE_BTN_PREV) + { + if (cursor > 0) cursor--; + } + else if (key == JGE_BTN_NEXT) + { + if (cursor < buffer.size()) + cursor++; + else + { + buffer += ' '; + cursor = buffer.size(); + } + } + + mX = 50; + mY = 50; + + //Clear input buffer. + mEngine->ResetInput(); } -void SimplePad::Start(string value, string * _dest) { - bActive = true; - bCanceled=false; - buffer = value; - original = buffer; - dest = _dest; - cursor = buffer.size(); - //Clear input buffer. - JGE * mEngine = JGE::GetInstance(); - mEngine->ResetInput(); -} - -string SimplePad::Finish() { - bActive = false; - - //Clear input buffer. - JGE * mEngine = JGE::GetInstance(); - mEngine->ResetInput(); - - //Return result. - if(bCanceled){ - dest = NULL; - return original; - }else{ //Strip trailing spaces. - string whitespaces (" \t\f\v\n\r"); - size_t found=buffer.find_last_not_of(whitespaces); - if (found!=string::npos) - buffer.erase(found+1); - else - buffer = ""; - } - - if(dest != NULL){ - dest->clear(); dest->insert(0,buffer); - dest = NULL; - } - return buffer; -} - -void SimplePad::Render(){ - //This could use some cleaning up to make margins more explicit - WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); - - float offX = 0, offY = 0; - float kH = mFont->GetHeight(); - float hSpacing = mFont->GetStringWidth("W"); - float rowLen = mFont->GetStringWidth("JKLMNOPQR") + 14*7; - float vSpacing = 0; - float kW = hSpacing; - - JRenderer * renderer = JRenderer::GetInstance(); - - - vSpacing = kH+8; - - - offY = vSpacing; - if(bShowNumpad) - offY += kH+14; - //Draw Keypad Background. - renderer->FillRoundRect(mX-kW,mY-kH,(kW+12)*13,(kH+14)*5+offY,2,ARGB(180,0,0,0)); - offY = vSpacing; - //Draw text entry bubble - renderer->FillRoundRect(mX-kW/2,mY+offY,(kW+12)*11+kW/2,kH,2,ARGB(255,255,255,255)); - - //Draw text-entry title, if we've got one. - if(title != ""){ - mFont->DrawString(_(title.c_str()),mX,mY); - } - mY+=kH+12; - - //Draw cursor. - if(cursor < buffer.size()) - { - kW = mFont->GetStringWidth(buffer.substr(cursor,1).c_str()); - renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cursor).c_str()),mY+kH-4, - kW,4,2,ARGB(150,150,150,0)); - } - else - { +void SimplePad::Start(string value, string * _dest) +{ + bActive = true; + bCanceled = false; + buffer = value; + original = buffer; + dest = _dest; cursor = buffer.size(); - renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cursor).c_str()),mY+kH-4, - kW,4,2,ARGB(150,150,150,0)); - } - - mFont->SetColor(ARGB(255,0,0,0)); - mFont->DrawString(buffer.c_str(),mX,mY); - offY += kH + 12; + //Clear input buffer. + JGE * mEngine = JGE::GetInstance(); + mEngine->ResetInput(); +} - if(!bShowNumpad) - vSpacing -= kH + 12; - - for(int x=0;x= KPD_0 && x <= KPD_9 && !bShowNumpad)) - continue; - - switch(x){ - case KPD_0: - offX = 0; - offY = vSpacing; - break; - case KPD_A: - offX = 0; - offY = vSpacing+(kH+12)*1; - break; - case KPD_J: - offX = 0; - offY = vSpacing+(kH+12)*2; - break; - case KPD_S: - offX = 0; - offY = vSpacing+(kH+12)*3; - break; - case KPD_SPACE: - offX = 0; - offY = vSpacing+(kH+12)*4; - break; - case KPD_OK: - offX = rowLen + hSpacing; - offY = vSpacing+(kH+12)*3; - break; - case KPD_CANCEL: - offX = rowLen + hSpacing; - offY = vSpacing+(kH+12)*4; - break; - case KPD_DEL: - offX = rowLen + hSpacing; - offY = vSpacing+(kH+12)*1; - break; - case KPD_CAPS: - offX = rowLen + hSpacing; - offY = vSpacing+(kH+12)*2; - break; - } + //Clear input buffer. + JGE * mEngine = JGE::GetInstance(); + mEngine->ResetInput(); - kW = mFont->GetStringWidth(keys[x]->displayValue.c_str()); - //Render a key. - if(x != selected){ - renderer->FillRoundRect(mX+offX-4,mY+offY-4,kW+8,kH+4,2,ARGB(180,50,50,50)); - mFont->SetColor(ARGB(255,255,255,0)); - } - else{ - renderer->FillRoundRect(mX+offX-4,mY+offY-4,kW+8,kH+4,2,ARGB(255,100,100,100)); - mFont->SetColor(ARGB(255,255,255,255)); - } - - char vkey[2]; - vkey[1] = '\0'; - vkey[0] = keys[x]->id; - - - if(isalpha(vkey[0])) { - if(bCapslock) vkey[0] = toupper(vkey[0]); - mFont->DrawString(vkey,mX+offX,mY+offY); - } - else - mFont->DrawString(keys[x]->displayValue.c_str(),mX+offX,mY+offY); - offX += kW + 14; + //Return result. + if (bCanceled) + { + dest = NULL; + return original; } + else + { //Strip trailing spaces. + string whitespaces(" \t\f\v\n\r"); + size_t found = buffer.find_last_not_of(whitespaces); + if (found != string::npos) + buffer.erase(found + 1); + else + buffer = ""; + } + + if (dest != NULL) + { + dest->clear(); + dest->insert(0, buffer); + dest = NULL; + } + return buffer; } -unsigned int SimplePad::cursorPos(){ - if(cursor > buffer.size()) - return buffer.size(); +void SimplePad::Render() +{ + //This could use some cleaning up to make margins more explicit + WFont * mFont = resources.GetWFont(Fonts::MENU_FONT); - return cursor; + float offX = 0, offY = 0; + float kH = mFont->GetHeight(); + float hSpacing = mFont->GetStringWidth("W"); + float rowLen = mFont->GetStringWidth("JKLMNOPQR") + 14 * 7; + float vSpacing = 0; + float kW = hSpacing; + + JRenderer * renderer = JRenderer::GetInstance(); + + vSpacing = kH + 8; + + offY = vSpacing; + if (bShowNumpad) offY += kH + 14; + //Draw Keypad Background. + renderer->FillRoundRect(mX - kW, mY - kH, (kW + 12) * 13, (kH + 14) * 5 + offY, 2, ARGB(180,0,0,0)); + offY = vSpacing; + //Draw text entry bubble + renderer->FillRoundRect(mX - kW / 2, mY + offY, (kW + 12) * 11 + kW / 2, kH, 2, ARGB(255,255,255,255)); + + //Draw text-entry title, if we've got one. + if (title != "") + { + mFont->DrawString(_(title.c_str()), mX, mY); + } + mY += kH + 12; + + //Draw cursor. + if (cursor < buffer.size()) + { + kW = mFont->GetStringWidth(buffer.substr(cursor, 1).c_str()); + renderer->FillRoundRect(mX + mFont->GetStringWidth(buffer.substr(0, cursor).c_str()), mY + kH - 4, kW, 4, 2, + ARGB(150,150,150,0)); + } + else + { + cursor = buffer.size(); + renderer->FillRoundRect(mX + mFont->GetStringWidth(buffer.substr(0, cursor).c_str()), mY + kH - 4, kW, 4, 2, + ARGB(150,150,150,0)); + } + + mFont->SetColor(ARGB(255,0,0,0)); + mFont->DrawString(buffer.c_str(), mX, mY); + offY += kH + 12; + + if (!bShowNumpad) vSpacing -= kH + 12; + + for (int x = 0; x < nbitems; x++) + if (keys[x]) + { + + if ((x == KPD_CANCEL && !bShowCancel) || (x >= KPD_0 && x <= KPD_9 && !bShowNumpad)) continue; + + switch (x) + { + case KPD_0: + offX = 0; + offY = vSpacing; + break; + case KPD_A: + offX = 0; + offY = vSpacing + (kH + 12) * 1; + break; + case KPD_J: + offX = 0; + offY = vSpacing + (kH + 12) * 2; + break; + case KPD_S: + offX = 0; + offY = vSpacing + (kH + 12) * 3; + break; + case KPD_SPACE: + offX = 0; + offY = vSpacing + (kH + 12) * 4; + break; + case KPD_OK: + offX = rowLen + hSpacing; + offY = vSpacing + (kH + 12) * 3; + break; + case KPD_CANCEL: + offX = rowLen + hSpacing; + offY = vSpacing + (kH + 12) * 4; + break; + case KPD_DEL: + offX = rowLen + hSpacing; + offY = vSpacing + (kH + 12) * 1; + break; + case KPD_CAPS: + offX = rowLen + hSpacing; + offY = vSpacing + (kH + 12) * 2; + break; + } + + kW = mFont->GetStringWidth(keys[x]->displayValue.c_str()); + //Render a key. + if (x != selected) + { + renderer->FillRoundRect(mX + offX - 4, mY + offY - 4, kW + 8, kH + 4, 2, ARGB(180,50,50,50)); + mFont->SetColor(ARGB(255,255,255,0)); + } + else + { + renderer->FillRoundRect(mX + offX - 4, mY + offY - 4, kW + 8, kH + 4, 2, ARGB(255,100,100,100)); + mFont->SetColor(ARGB(255,255,255,255)); + } + + char vkey[2]; + vkey[1] = '\0'; + vkey[0] = keys[x]->id; + + if (isalpha(vkey[0])) + { + if (bCapslock) vkey[0] = toupper(vkey[0]); + mFont->DrawString(vkey, mX + offX, mY + offY); + } + else + mFont->DrawString(keys[x]->displayValue.c_str(), mX + offX, mY + offY); + offX += kW + 14; + } +} + +unsigned int SimplePad::cursorPos() +{ + if (cursor > buffer.size()) return buffer.size(); + + return cursor; } diff --git a/projects/mtg/src/StoryFlow.cpp b/projects/mtg/src/StoryFlow.cpp index 17d68c899..ed4c180a3 100644 --- a/projects/mtg/src/StoryFlow.cpp +++ b/projects/mtg/src/StoryFlow.cpp @@ -11,7 +11,6 @@ #include "WFont.h" #include - #define LINE_SPACE 2 #define SPACE_BEFORE_CHOICES 10 @@ -21,564 +20,657 @@ bool StoryReward::rewardSoundPlayed = false; bool StoryReward::rewardsEnabled = true; MTGDeck * StoryReward::collection = NULL; -StoryDialogElement::StoryDialogElement(float x, float y, int id): JGuiObject(id), mX(x),mY(y) { +StoryDialogElement::StoryDialogElement(float x, float y, int id) : + JGuiObject(id), mX(x), mY(y) +{ } -StoryText::StoryText(string text, float _mX, float _mY, string _align, int _font, int id):StoryDialogElement(_mX,_mY, id), text(text), font(_font) { - align = JGETEXT_LEFT; - if (_align.compare("center") == 0) { - align = JGETEXT_CENTER; - if (mX == 0) - mX = SCREEN_WIDTH/2; - }else if (_align.compare("right") == 0) { - align = JGETEXT_RIGHT; - if (mX == 0) - mX = SCREEN_WIDTH - 10; - } - if (align == JGETEXT_LEFT && mX <= 0){ - mX += 10; //left margin - } +StoryText::StoryText(string text, float _mX, float _mY, string _align, int _font, int id) : + StoryDialogElement(_mX, _mY, id), text(text), font(_font) +{ + align = JGETEXT_LEFT; + if (_align.compare("center") == 0) + { + align = JGETEXT_CENTER; + if (mX == 0) mX = SCREEN_WIDTH / 2; + } + else if (_align.compare("right") == 0) + { + align = JGETEXT_RIGHT; + if (mX == 0) mX = SCREEN_WIDTH - 10; + } + if (align == JGETEXT_LEFT && mX <= 0) + { + mX += 10; //left margin + } } -void StoryText::Render() { - WFont * mFont = resources.GetWFont(font); - mFont->SetColor(ARGB(200,255,255,255)); - mFont->SetScale(1.0); - mFont->DrawString(text.c_str(), mX, mY, align); +void StoryText::Render() +{ + WFont * mFont = resources.GetWFont(font); + mFont->SetColor(ARGB(200,255,255,255)); + mFont->SetScale(1.0); + mFont->DrawString(text.c_str(), mX, mY, align); } -float StoryText::getHeight() { - WFont * mFont = resources.GetWFont(font); - return mFont->GetHeight(); +float StoryText::getHeight() +{ + WFont * mFont = resources.GetWFont(font); + return mFont->GetHeight(); } - void StoryText::Update(float dt){ +void StoryText::Update(float dt) +{ //Nothing for now - } +} - - StoryReward::StoryReward(string _type, string _value, string text, float _mX, float _mY, string _align, int _font, int id):StoryText(text,_mX,_mY, _align, _font, id) { - type = STORY_REWARD_CREDITS; - if (_type.compare("unlockset") == 0) { - type = STORY_REWARD_SET; - } else if (_type.compare("card") == 0) { - type = STORY_REWARD_CARD; - } - value = _value; - rewardDone = 0; +StoryReward::StoryReward(string _type, string _value, string text, float _mX, float _mY, string _align, int _font, int id) : + StoryText(text, _mX, _mY, _align, _font, id) +{ + type = STORY_REWARD_CREDITS; + if (_type.compare("unlockset") == 0) + { + type = STORY_REWARD_SET; + } + else if (_type.compare("card") == 0) + { + type = STORY_REWARD_CARD; + } + value = _value; + rewardDone = 0; } -void StoryReward::Render(){ - if (rewardDone <=0) - return; - StoryText::Render(); +void StoryReward::Render() +{ + if (rewardDone <= 0) return; + StoryText::Render(); } -void StoryReward::Update(float dt){ - if (rewardDone) - return; +void StoryReward::Update(float dt) +{ + if (rewardDone) return; int result = 0; - switch (type){ + switch (type) + { case STORY_REWARD_CREDITS: - result = Credits::addCreditBonus(atoi(value.c_str())); - break; + result = Credits::addCreditBonus(atoi(value.c_str())); + break; case STORY_REWARD_SET: - { - if (value.size()) { - result = Credits::unlockSetByName(value); - } else { - result = Credits::unlockRandomSet(true); + { + if (value.size()) + { + result = Credits::unlockSetByName(value); + } + else + { + result = Credits::unlockRandomSet(true); } if (!result) break; MTGSetInfo * si = setlist.getInfo(result - 1); - if(si) { - string unlockedString = si->getName(); - size_t pos = text.find("${SET}"); - if (pos != string::npos) { - text.replace(pos,pos + 6,unlockedString); - } + if (si) + { + string unlockedString = si->getName(); + size_t pos = text.find("${SET}"); + if (pos != string::npos) + { + text.replace(pos, pos + 6, unlockedString); + } } break; - } + } case STORY_REWARD_CARD: - { + { int cardId = 0; MTGCard * card = NULL; - if (value.size()) { - card = GameApp::collection->getCardByName(value); - if (card) { - cardId = card->getId(); - } - } else { - cardId = GameApp::collection->randomCardId(); - card = GameApp::collection->getCardById(cardId); + if (value.size()) + { + card = GameApp::collection->getCardByName(value); + if (card) + { + cardId = card->getId(); + } } - + else + { + cardId = GameApp::collection->randomCardId(); + card = GameApp::collection->getCardById(cardId); + } + if (!cardId) break; - if (!collection) { - collection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), GameApp::collection); + if (!collection) + { + collection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), GameApp::collection); } result = Credits::addCardToCollection(cardId, collection); size_t pos = text.find("${CARD}"); - if (pos != string::npos && card) { - text.replace(pos,pos + 7,card->data->getName()); + if (pos != string::npos && card) + { + text.replace(pos, pos + 7, card->data->getName()); } break; - } + } default: - break; + break; } - if (!result) { - rewardDone = -1; - return; + if (!result) + { + rewardDone = -1; + return; } - if (!rewardsEnabled) { - rewardDone = -1; - return; + if (!rewardsEnabled) + { + rewardDone = -1; + return; } - if (!rewardSoundPlayed && options[Options::SFXVOLUME].number > 0){ - JSample * sample = resources.RetrieveSample("bonus.wav"); - if (sample){ - JSoundSystem::GetInstance()->PlaySample(sample); - } - rewardSoundPlayed = 1; + if (!rewardSoundPlayed && options[Options::SFXVOLUME].number > 0) + { + JSample * sample = resources.RetrieveSample("bonus.wav"); + if (sample) + { + JSoundSystem::GetInstance()->PlaySample(sample); + } + rewardSoundPlayed = 1; } rewardDone = 1; - } +} - ostream& StoryText::toString(ostream& out) const +ostream& StoryText::toString(ostream& out) const { - return out << "StoryText ::: text : " << text; + return out << "StoryText ::: text : " << text; } - StoryImage::StoryImage(string img, float mX, float mY):StoryDialogElement(mX,mY), img(img) { +StoryImage::StoryImage(string img, float mX, float mY) : + StoryDialogElement(mX, mY), img(img) +{ } -void StoryImage::Render() { - JQuad * quad = resources.RetrieveTempQuad(img); - if (quad) { - float x = mX; - if (mX == -1) { - x = SCREEN_WIDTH/2; - quad->SetHotSpot(quad->mWidth/2, 0); +void StoryImage::Render() +{ + JQuad * quad = resources.RetrieveTempQuad(img); + if (quad) + { + float x = mX; + if (mX == -1) + { + x = SCREEN_WIDTH / 2; + quad->SetHotSpot(quad->mWidth / 2, 0); + } + JRenderer::GetInstance()->RenderQuad(quad, x, mY); } - JRenderer::GetInstance()->RenderQuad(quad,x, mY); - } } -float StoryImage::getHeight() { -JQuad * quad = resources.RetrieveQuad(img); - if (quad) { - return quad->mHeight; - } - return 0; +float StoryImage::getHeight() +{ + JQuad * quad = resources.RetrieveQuad(img); + if (quad) + { + return quad->mHeight; + } + return 0; } - void StoryImage::Update(float dt){ +void StoryImage::Update(float dt) +{ //Nothing for now - } +} - ostream& StoryImage::toString(ostream& out) const +ostream& StoryImage::toString(ostream& out) const { - return out << "StoryImage ::: img : " << img; + return out << "StoryImage ::: img : " << img; } -StoryPage::StoryPage(StoryFlow * mParent):mParent(mParent){ -} - - -void StoryChoice::Render() +StoryPage::StoryPage(StoryFlow * mParent) : + mParent(mParent) { - WFont * mFont = resources.GetWFont(font); - mFont->SetColor(ARGB(200,255,255,255)); - if (mHasFocus) mFont->SetColor(ARGB(255,255,255,0)); - mFont->SetScale(mScale); - mFont->DrawString(text.c_str(), mX, mY, align); } -float StoryChoice::getHeight() { - WFont * mFont = resources.GetWFont(font); - return mFont->GetHeight() * mScale; +void StoryChoice::Render() +{ + WFont * mFont = resources.GetWFont(font); + mFont->SetColor(ARGB(200,255,255,255)); + if (mHasFocus) mFont->SetColor(ARGB(255,255,255,0)); + mFont->SetScale(mScale); + mFont->DrawString(text.c_str(), mX, mY, align); } -void StoryChoice::Update(float dt) +float StoryChoice::getHeight() +{ + WFont * mFont = resources.GetWFont(font); + return mFont->GetHeight() * mScale; +} + +void StoryChoice::Update(float dt) { if (mScale < mTargetScale) { - mScale += 8.0f*dt; - if (mScale > mTargetScale) - mScale = mTargetScale; + mScale += 8.0f * dt; + if (mScale > mTargetScale) mScale = mTargetScale; } - else if (mScale > mTargetScale) + else if (mScale > mTargetScale) { - mScale -= 8.0f*dt; - if (mScale < mTargetScale) - mScale = mTargetScale; - } + mScale -= 8.0f * dt; + if (mScale < mTargetScale) mScale = mTargetScale; + } } - void StoryChoice::Entering() { - mHasFocus = true; - mTargetScale = 1.2f; + mHasFocus = true; + mTargetScale = 1.2f; } - -bool StoryChoice::Leaving(JButton key) +bool StoryChoice::Leaving(JButton key) { - mHasFocus = false; - mTargetScale = 1.0f; - return true; + mHasFocus = false; + mTargetScale = 1.0f; + return true; } - bool StoryChoice::ButtonPressed() { - return true; + return true; } - - bool StoryChoice::hasFocus() { - return mHasFocus; + return mHasFocus; } ostream& StoryChoice::toString(ostream& out) const { - return out << "StoryChoice ::: mHasFocus : " << mHasFocus; + return out << "StoryChoice ::: mHasFocus : " << mHasFocus; } - -StoryChoice::StoryChoice(string pageId, string text, int JGOid, float mX, float mY, string _align, int _font, bool hasFocus):StoryText(text, mX, mY, _align, _font, JGOid),pageId(pageId),mHasFocus(hasFocus){ +StoryChoice::StoryChoice(string pageId, string text, int JGOid, float mX, float mY, string _align, int _font, bool hasFocus) : + StoryText(text, mX, mY, _align, _font, JGOid), pageId(pageId), mHasFocus(hasFocus) +{ mScale = 1.0f; - mTargetScale = 1.0f; - if(hasFocus) mTargetScale = 1.2f; + mTargetScale = 1.0f; + if (hasFocus) mTargetScale = 1.2f; } //Actually loads a duel -void StoryDuel::init(){ - Player * players[2]; +void StoryDuel::init() +{ + Player * players[2]; - char folder[255], deckFile[255],deckFileSmall[255]; - sprintf(folder, JGE_GET_RES(CAMPAIGNS_FOLDER"%s/%s").c_str() ,mParent->folder.c_str(), pageId.c_str()); + char folder[255], deckFile[255], deckFileSmall[255]; + sprintf(folder, JGE_GET_RES(CAMPAIGNS_FOLDER"%s/%s").c_str(), mParent->folder.c_str(), pageId.c_str()); - sprintf(deckFile, "%s/deck.txt", folder); - MTGDeck * tempDeck = NEW MTGDeck(deckFile, GameApp::collection); - sprintf(deckFileSmall, "campaign_%s", mParent->folder.c_str()); - players[0] = NEW HumanPlayer(tempDeck, deckFile, deckFileSmall); - SAFE_DELETE(tempDeck); + sprintf(deckFile, "%s/deck.txt", folder); + MTGDeck * tempDeck = NEW MTGDeck(deckFile, GameApp::collection); + sprintf(deckFileSmall, "campaign_%s", mParent->folder.c_str()); + players[0] = NEW HumanPlayer(tempDeck, deckFile, deckFileSmall); + SAFE_DELETE(tempDeck); - sprintf(deckFile,"%s/opponent_deck.txt", folder); - tempDeck = NEW MTGDeck(deckFile, GameApp::collection); - sprintf(deckFileSmall, "campaign_ennemy_%s_%s", mParent->folder.c_str(), pageId.c_str()); - players[1] = NEW AIPlayerBaka(tempDeck, deckFile, deckFileSmall, "baka.jpg"); - SAFE_DELETE(tempDeck); + sprintf(deckFile, "%s/opponent_deck.txt", folder); + tempDeck = NEW MTGDeck(deckFile, GameApp::collection); + sprintf(deckFileSmall, "campaign_ennemy_%s_%s", mParent->folder.c_str(), pageId.c_str()); + players[1] = NEW AIPlayerBaka(tempDeck, deckFile, deckFileSmall, "baka.jpg"); + SAFE_DELETE(tempDeck); - string rulesFile = folder; - rulesFile.append("/rules.txt"); - rules = NEW Rules(rulesFile, bg); + string rulesFile = folder; + rulesFile.append("/rules.txt"); + rules = NEW Rules(rulesFile, bg); - GameObserver::Init(players, 2); - game = GameObserver::GetInstance(); - rules->gamemode = GAME_TYPE_STORY; - game->startGame(rules); -} -StoryDuel::StoryDuel(TiXmlElement* root,StoryFlow * mParent): StoryPage(mParent) { - game = NULL; - rules = NULL; - pageId = root->Attribute("id"); - for (TiXmlNode* node = root->FirstChild(); node; node = node->NextSibling()) { - TiXmlElement* element = node->ToElement(); - if (element) { - const char* textC = element->GetText(); - if (strcmp(element->Value(), "onwin")==0) { - onWin = textC; - } - else if (strcmp(element->Value(), "onlose")==0) { - onLose = textC; - } else if (strcmp(element->Value(), "bg")==0) { - string text = textC; - bg = string("campaigns/").append(mParent->folder).append("/").append(text); - if (!fileExists(bg.c_str())) bg = text; - } else { - StoryPage::loadElement(element); //Father - } - } - } + GameObserver::Init(players, 2); + game = GameObserver::GetInstance(); + rules->gamemode = GAME_TYPE_STORY; + game->startGame(rules); } -StoryDuel::~StoryDuel(){ - SAFE_DELETE(rules); - if(game)GameObserver::EndInstance(); - game=NULL; -} - -void StoryDuel::Update(float dt){ - if (!game) init(); - game->Update(dt); - if (game->gameOver){ - if (game->gameOver == game->players[1]) mParent->gotoPage(onWin); - else mParent->gotoPage(onLose); - GameObserver::EndInstance(); - game=NULL; - } -} - -void StoryDuel::Render(){ - if(!game) return; - game->Render(); -} - -string StoryPage::safeAttribute(TiXmlElement* element, string attribute) { - string s; - if (element->Attribute(attribute.c_str())){ - s = element->Attribute(attribute.c_str()); - } - return s; -} - -int StoryPage::loadElement(TiXmlElement* element) { - if (!element) return 0; - const char* textC = element->GetText(); - string text = textC; - if (strcmp(element->Value(), "music")==0) { - musicFile = string("campaigns/").append(mParent->folder).append("/").append(text); - if (!fileExists(musicFile.c_str())) - musicFile = text; - return 1; - } - return 0; -} - -StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent):StoryPage(mParent), JGuiListener(), JGuiController(1,NULL) { - - currentY = 0; - - for (TiXmlNode* node = root->FirstChild(); node; node = node->NextSibling()) { - TiXmlElement* element = node->ToElement(); - if (element) { - string sX = safeAttribute(element, "x"); - float x = static_cast(atof(sX.c_str())); - if (x > 0 && x < 1){ - x = SCREEN_WIDTH_F * x; +StoryDuel::StoryDuel(TiXmlElement* root, StoryFlow * mParent) : + StoryPage(mParent) +{ + game = NULL; + rules = NULL; + pageId = root->Attribute("id"); + for (TiXmlNode* node = root->FirstChild(); node; node = node->NextSibling()) + { + TiXmlElement* element = node->ToElement(); + if (element) + { + const char* textC = element->GetText(); + if (strcmp(element->Value(), "onwin") == 0) + { + onWin = textC; + } + else if (strcmp(element->Value(), "onlose") == 0) + { + onLose = textC; + } + else if (strcmp(element->Value(), "bg") == 0) + { + string text = textC; + bg = string("campaigns/").append(mParent->folder).append("/").append(text); + if (!fileExists(bg.c_str())) bg = text; + } + else + { + StoryPage::loadElement(element); //Father + } } - string sY = safeAttribute(element,"y"); - float y = static_cast(atof(sY.c_str())); - if (y > 0 && y < 1){ - y = SCREEN_HEIGHT_F * y; - } - string align = safeAttribute(element,"align"); - const char* textC = element->GetText(); - string text = textC; - string sFont = safeAttribute(element,"font"); - int font = atoi(sFont.c_str()); + } +} - if (strcmp(element->Value(), "text")==0) { - graphics.push_back(NEW StoryText(text,x,y,align, font)); - } - else if (strcmp(element->Value(), "title")==0) { - graphics.push_back(NEW StoryText(text,x,y,"center", Fonts::MENU_FONT)); - } - else if (strcmp(element->Value(), "img")==0) { - //special case to force center - if (sX.compare("") == 0 ){ - x = -1; - } - string img = string("campaigns/").append(mParent->folder).append("/").append(text); - graphics.push_back(NEW StoryImage(img,x,y)); - } - else if (strcmp(element->Value(), "answer")==0){ - string id = element->Attribute("goto"); - if (!align.size()) align = "center"; - int i = mObjects.size(); - StoryChoice * sc = NEW StoryChoice(id,text,i,x, y , align, font, (i==0)); - graphics.push_back(sc); - Add(sc); - }else if (strcmp(element->Value(), "reward")==0){ - string type = safeAttribute(element,"type"); - string value = safeAttribute(element,"value"); - graphics.push_back(NEW StoryReward(type, value, text,x,y,align, font)); - }else { - StoryPage::loadElement(element); //Father +StoryDuel::~StoryDuel() +{ + SAFE_DELETE(rules); + if (game) GameObserver::EndInstance(); + game = NULL; +} + +void StoryDuel::Update(float dt) +{ + if (!game) init(); + game->Update(dt); + if (game->gameOver) + { + if (game->gameOver == game->players[1]) + mParent->gotoPage(onWin); + else + mParent->gotoPage(onLose); + GameObserver::EndInstance(); + game = NULL; + } +} + +void StoryDuel::Render() +{ + if (!game) return; + game->Render(); +} + +string StoryPage::safeAttribute(TiXmlElement* element, string attribute) +{ + string s; + if (element->Attribute(attribute.c_str())) + { + s = element->Attribute(attribute.c_str()); + } + return s; +} + +int StoryPage::loadElement(TiXmlElement* element) +{ + if (!element) return 0; + const char* textC = element->GetText(); + string text = textC; + if (strcmp(element->Value(), "music") == 0) + { + musicFile = string("campaigns/").append(mParent->folder).append("/").append(text); + if (!fileExists(musicFile.c_str())) musicFile = text; + return 1; + } + return 0; +} + +StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent) : + StoryPage(mParent), JGuiListener(), JGuiController(1, NULL) +{ + + currentY = 0; + + for (TiXmlNode* node = root->FirstChild(); node; node = node->NextSibling()) + { + TiXmlElement* element = node->ToElement(); + if (element) + { + string sX = safeAttribute(element, "x"); + float x = static_cast (atof(sX.c_str())); + if (x > 0 && x < 1) + { + x = SCREEN_WIDTH_F * x; + } + string sY = safeAttribute(element, "y"); + float y = static_cast (atof(sY.c_str())); + if (y > 0 && y < 1) + { + y = SCREEN_HEIGHT_F * y; + } + string align = safeAttribute(element, "align"); + const char* textC = element->GetText(); + string text = textC; + string sFont = safeAttribute(element, "font"); + int font = atoi(sFont.c_str()); + + if (strcmp(element->Value(), "text") == 0) + { + graphics.push_back(NEW StoryText(text, x, y, align, font)); + } + else if (strcmp(element->Value(), "title") == 0) + { + graphics.push_back(NEW StoryText(text, x, y, "center", Fonts::MENU_FONT)); + } + else if (strcmp(element->Value(), "img") == 0) + { + //special case to force center + if (sX.compare("") == 0) + { + x = -1; + } + string img = string("campaigns/").append(mParent->folder).append("/").append(text); + graphics.push_back(NEW StoryImage(img, x, y)); + } + else if (strcmp(element->Value(), "answer") == 0) + { + string id = element->Attribute("goto"); + if (!align.size()) align = "center"; + int i = mObjects.size(); + StoryChoice * sc = NEW StoryChoice(id, text, i, x, y, align, font, (i == 0)); + graphics.push_back(sc); + Add(sc); + } + else if (strcmp(element->Value(), "reward") == 0) + { + string type = safeAttribute(element, "type"); + string value = safeAttribute(element, "value"); + graphics.push_back(NEW StoryReward(type, value, text, x, y, align, font)); + } + else + { + StoryPage::loadElement(element); //Father + } } - } - } - this->mListener = this; + } + this->mListener = this; } -void StoryDialog::Update(float dt){ - for (size_t i = 0; i < graphics.size(); ++i){ - graphics[i]->Update(dt); - } +void StoryDialog::Update(float dt) +{ + for (size_t i = 0; i < graphics.size(); ++i) + { + graphics[i]->Update(dt); + } - if (StoryReward::collection) { - StoryReward::collection->save(); - SAFE_DELETE(StoryReward::collection); - } + if (StoryReward::collection) + { + StoryReward::collection->save(); + SAFE_DELETE(StoryReward::collection); + } - JButton key = mEngine->ReadButton(); - CheckUserInput(key); + JButton key = mEngine->ReadButton(); + CheckUserInput(key); } - -void StoryDialog::RenderElement(StoryDialogElement * elmt) { +void StoryDialog::RenderElement(StoryDialogElement * elmt) +{ float mYBackup = elmt->mY; - if (! elmt->mY) elmt->mY = currentY; - if (elmt->mY == -1) { - elmt->mY = previousY; + if (!elmt->mY) elmt->mY = currentY; + if (elmt->mY == -1) + { + elmt->mY = previousY; } elmt->Render(); previousY = currentY; - currentY = elmt->mY + elmt->getHeight() + LINE_SPACE; + currentY = elmt->mY + elmt->getHeight() + LINE_SPACE; elmt->mY = mYBackup; } -void StoryDialog::Render() { - currentY = 2; - previousY = currentY; - for (size_t i = 0; i < graphics.size(); ++i){ - StoryDialogElement * elmt = (StoryDialogElement *)(graphics[i]); - if (mCount && elmt == mObjects[0]) - currentY += SPACE_BEFORE_CHOICES; - RenderElement(elmt); - } +void StoryDialog::Render() +{ + currentY = 2; + previousY = currentY; + for (size_t i = 0; i < graphics.size(); ++i) + { + StoryDialogElement * elmt = (StoryDialogElement *) (graphics[i]); + if (mCount && elmt == mObjects[0]) currentY += SPACE_BEFORE_CHOICES; + RenderElement(elmt); + } } -void StoryDialog::ButtonPressed(int controllerid,int controlid) { - mParent->gotoPage(((StoryChoice *)mObjects[controlid])->pageId); +void StoryDialog::ButtonPressed(int controllerid, int controlid) +{ + mParent->gotoPage(((StoryChoice *) mObjects[controlid])->pageId); } -StoryDialog::~StoryDialog(){ - mCount = 0; //avoid parent deleting - for (size_t i = 0; i < graphics.size(); ++i){ - delete(graphics[i]); - } +StoryDialog::~StoryDialog() +{ + mCount = 0; //avoid parent deleting + for (size_t i = 0; i < graphics.size(); ++i) + { + delete (graphics[i]); + } } - -StoryFlow::StoryFlow(string folder): folder(folder){ - string path = "campaigns/"; - path.append(folder).append("/story.xml"); - parse(path); +StoryFlow::StoryFlow(string folder) : + folder(folder) +{ + string path = "campaigns/"; + path.append(folder).append("/story.xml"); + parse(path); } - -StoryPage * StoryFlow::loadPage(TiXmlElement* element){ - TiXmlNode* typeNode = element->FirstChild("type"); - if (!typeNode) return NULL; - StoryPage * result = NULL; - const char* type = typeNode->ToElement()->GetText(); - if (strcmp(type, "duel")==0){ - result = NEW StoryDuel(element,this); - }else{ - result = NEW StoryDialog(element,this); - } - return result; +StoryPage * StoryFlow::loadPage(TiXmlElement* element) +{ + TiXmlNode* typeNode = element->FirstChild("type"); + if (!typeNode) return NULL; + StoryPage * result = NULL; + const char* type = typeNode->ToElement()->GetText(); + if (strcmp(type, "duel") == 0) + { + result = NEW StoryDuel(element, this); + } + else + { + result = NEW StoryDialog(element, this); + } + return result; } - // -bool StoryFlow::_gotoPage(string id){ - StoryReward::rewardSoundPlayed = false; - if (pages.find(id) == pages.end()) { - return false; - } - currentPageId = id; - if (pages[currentPageId]->musicFile.size()) { - GameApp::playMusic(pages[currentPageId]->musicFile); - } - return true; +bool StoryFlow::_gotoPage(string id) +{ + StoryReward::rewardSoundPlayed = false; + if (pages.find(id) == pages.end()) + { + return false; + } + currentPageId = id; + if (pages[currentPageId]->musicFile.size()) + { + GameApp::playMusic(pages[currentPageId]->musicFile); + } + return true; } -bool StoryFlow::gotoPage(string id){ - StoryReward::rewardsEnabled = true; - return _gotoPage(id); +bool StoryFlow::gotoPage(string id) +{ + StoryReward::rewardsEnabled = true; + return _gotoPage(id); } -bool StoryFlow::loadPageId(string id) { - StoryReward::rewardsEnabled = false; - return _gotoPage(id); +bool StoryFlow::loadPageId(string id) +{ + StoryReward::rewardsEnabled = false; + return _gotoPage(id); } bool StoryFlow::parse(string path) { - JFileSystem *fileSystem = JFileSystem::GetInstance(); - if (!fileSystem) return false; + JFileSystem *fileSystem = JFileSystem::GetInstance(); + if (!fileSystem) return false; - if (!fileSystem->OpenFile(path.c_str())) return false; + if (!fileSystem->OpenFile(path.c_str())) return false; - int size = fileSystem->GetFileSize(); - char *xmlBuffer = NEW char[size]; - fileSystem->ReadFile(xmlBuffer, size); + int size = fileSystem->GetFileSize(); + char *xmlBuffer = NEW char[size]; + fileSystem->ReadFile(xmlBuffer, size); - TiXmlDocument doc; - doc.Parse(xmlBuffer); + TiXmlDocument doc; + doc.Parse(xmlBuffer); - fileSystem->CloseFile(); - delete[] xmlBuffer; + fileSystem->CloseFile(); + delete[] xmlBuffer; - for (TiXmlNode* node = doc.FirstChild(); node; node = node->NextSibling()) { - TiXmlElement* element = node->ToElement(); - if (element != NULL) { - if (strcmp(element->Value(), "page")==0) { - string id = element->Attribute("id"); + for (TiXmlNode* node = doc.FirstChild(); node; node = node->NextSibling()) + { + TiXmlElement* element = node->ToElement(); + if (element != NULL) + { + if (strcmp(element->Value(), "page") == 0) + { + string id = element->Attribute("id"); - DebugTrace("parsing " << id << "..."); + DebugTrace("parsing " << id << "..."); - StoryPage * sp = loadPage(element); - pages[id] = sp; - if (!currentPageId.size()) gotoPage(id); - } - else { - //Error - } - } - } + StoryPage * sp = loadPage(element); + pages[id] = sp; + if (!currentPageId.size()) gotoPage(id); + } + else + { + //Error + } + } + } - //autoLoad - PlayerData * pd = NEW PlayerData(); - map::iterator it = pd->storySaves.find(folder); - if (it!=pd->storySaves.end()) { - if (it->second.compare("End") !=0) - loadPageId(it->second); - } - SAFE_DELETE(pd); + //autoLoad + PlayerData * pd = NEW PlayerData(); + map::iterator it = pd->storySaves.find(folder); + if (it != pd->storySaves.end()) + { + if (it->second.compare("End") != 0) loadPageId(it->second); + } + SAFE_DELETE(pd); - return true; + return true; } -void StoryFlow::Update(float dt){ - pages[currentPageId]->Update(dt); +void StoryFlow::Update(float dt) +{ + pages[currentPageId]->Update(dt); } -void StoryFlow::Render(){ - pages[currentPageId]->Render(); +void StoryFlow::Render() +{ + pages[currentPageId]->Render(); } -StoryFlow::~StoryFlow(){ - for (map::iterator i = pages.begin(); i != pages.end(); ++i){ - SAFE_DELETE(i->second); - } - pages.clear(); - - //autoSave progress - PlayerData * pd = NEW PlayerData(); - pd->storySaves[folder] = currentPageId; - pd->save(); - SAFE_DELETE(pd); +StoryFlow::~StoryFlow() +{ + for (map::iterator i = pages.begin(); i != pages.end(); ++i) + { + SAFE_DELETE(i->second); + } + pages.clear(); + + //autoSave progress + PlayerData * pd = NEW PlayerData(); + pd->storySaves[folder] = currentPageId; + pd->save(); + SAFE_DELETE(pd); } diff --git a/projects/mtg/src/StyleManager.cpp b/projects/mtg/src/StyleManager.cpp index 797b9417d..b7c9d5cb6 100644 --- a/projects/mtg/src/StyleManager.cpp +++ b/projects/mtg/src/StyleManager.cpp @@ -9,139 +9,155 @@ #include "StyleManager.h" #include "../../../JGE/src/tinyxml/tinyxml.h" -void StyleManager::killRules(){ +void StyleManager::killRules() +{ activeStyle = ""; vector::iterator i; - for(i=rules.begin();i!=rules.end();i++) + for (i = rules.begin(); i != rules.end(); i++) SAFE_DELETE(*i); rules.clear(); - map::iterator mi; - for(mi=styles.begin();mi!=styles.end();mi++){ + map::iterator mi; + for (mi = styles.begin(); mi != styles.end(); mi++) + { SAFE_DELETE(mi->second); } styles.clear(); } -StyleManager::StyleManager(){ +StyleManager::StyleManager() +{ loadRules(); } -StyleManager::~StyleManager(){ +StyleManager::~StyleManager() +{ killRules(); } - -string WStyle::stylized(string filename){ - if(mapping.find(filename) != mapping.end()) - return mapping[filename]; - return filename; +string WStyle::stylized(string filename) +{ + if (mapping.find(filename) != mapping.end()) return mapping[filename]; + return filename; } -void StyleManager::loadRules(){ - killRules(); - //TODO Placeholder until XML format available. - string filename = JGE_GET_RES(resources.graphicsFile("style.txt")); - TiXmlDocument xmlfile(filename.c_str()); - if(!xmlfile.LoadFile()) + +void StyleManager::loadRules() +{ + killRules(); + //TODO Placeholder until XML format available. + string filename = JGE_GET_RES(resources.graphicsFile("style.txt")); + TiXmlDocument xmlfile(filename.c_str()); + if (!xmlfile.LoadFile()) return; + TiXmlHandle hDoc(&xmlfile); + TiXmlElement * pRule; + for (pRule = hDoc.FirstChildElement().Element(); pRule != NULL; pRule = pRule->NextSiblingElement()) + { + //root should be "pack" + string tag = pRule->Value(); + std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); + if (tag == "activebg") + { + //After validating, handle actual loading. + TiXmlElement * pSlot; + const char * holder = NULL; + holder = pRule->Attribute("source"); + if (holder) + playerSrc = atoi(holder); + else + playerSrc = -1; + + for (pSlot = pRule->FirstChildElement(); pSlot != NULL; pSlot = pSlot->NextSiblingElement()) + { + //Load slot. + tag = pSlot->Value(); + std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); + if (tag != "case") continue; + + WStyleRule * r = NEW WStyleRule(); + rules.push_back(r); + + holder = pSlot->Attribute("rule"); + if (holder) r->filter = holder; + r->style = pSlot->GetText(); + } + } + else if (tag == "style") + { + TiXmlElement * pSlot; + const char * holder = NULL; + holder = pRule->Attribute("name"); + if (!holder) continue; + string sname = holder; + WStyle * s = NEW WStyle(); + + for (pSlot = pRule->FirstChildElement(); pSlot != NULL; pSlot = pSlot->NextSiblingElement()) + { + + tag = pSlot->Value(); + std::transform(tag.begin(), tag.end(), tag.begin(), ::tolower); + if (tag.size() && pSlot->GetText()) s->mapping[tag] = pSlot->GetText(); + } + if (styles[sname]) + SAFE_DELETE(styles[sname]); + styles[sname] = s; + + } + } + + determineActive(NULL, NULL); return; - TiXmlHandle hDoc(&xmlfile); - TiXmlElement * pRule; - for(pRule = hDoc.FirstChildElement().Element();pRule!=NULL;pRule=pRule->NextSiblingElement()){ - //root should be "pack" - string tag = pRule->Value(); - std::transform(tag.begin(),tag.end(),tag.begin(),::tolower); - if(tag == "activebg"){ - //After validating, handle actual loading. - TiXmlElement * pSlot; - const char * holder = NULL; - holder = pRule->Attribute("source"); - if(holder) playerSrc = atoi(holder); else playerSrc = -1; - - for (pSlot=pRule->FirstChildElement();pSlot!=NULL;pSlot=pSlot->NextSiblingElement()){ - //Load slot. - tag = pSlot->Value(); - std::transform(tag.begin(),tag.end(),tag.begin(),::tolower); - if(tag != "case") continue; - - WStyleRule * r = NEW WStyleRule(); - rules.push_back(r); - - holder = pSlot->Attribute("rule"); - if(holder) r->filter = holder; - r->style = pSlot->GetText(); - } - } else if(tag == "style"){ - TiXmlElement * pSlot; - const char * holder = NULL; - holder = pRule->Attribute("name"); - if(!holder) continue; - string sname = holder; - WStyle * s = NEW WStyle(); - - for (pSlot=pRule->FirstChildElement();pSlot!=NULL;pSlot=pSlot->NextSiblingElement()){ - - tag = pSlot->Value(); - std::transform(tag.begin(),tag.end(),tag.begin(),::tolower); - if(tag.size() && pSlot->GetText()) - s->mapping[tag] = pSlot->GetText(); - } - if(styles[sname]) SAFE_DELETE(styles[sname]); - styles[sname] = s; - - - } - } - - determineActive(NULL,NULL); - return; } -WStyle * StyleManager::get() { - if(styles.find(activeStyle) != styles.end()) - return styles[activeStyle]; - return NULL; -}; +WStyle * StyleManager::get() +{ + if (styles.find(activeStyle) != styles.end()) return styles[activeStyle]; + return NULL; +} + void StyleManager::determineActive(MTGDeck * p1, MTGDeck * p2) { - string check = options[Options::GUI_STYLE].str; - if(check.size() && styles.find(check) != styles.end()){ - string prior = activeStyle; - activeStyle = check; - if(prior != activeStyle) - resources.Refresh(); - return; - } - topRule = -1; topSize = 0; - - MTGDeck * tempDeck = NEW MTGDeck(GameApp::collection); - if(p1 && playerSrc != 2) tempDeck->add(p1); - if(p2 && playerSrc != 1) tempDeck->add(p2); - WCFilterFactory * ff = WCFilterFactory::GetInstance(); + string check = options[Options::GUI_STYLE].str; + if (check.size() && styles.find(check) != styles.end()) + { + string prior = activeStyle; + activeStyle = check; + if (prior != activeStyle) resources.Refresh(); + return; + } + topRule = -1; + topSize = 0; - if(tempDeck){ - DeckDataWrapper * ddw = NEW DeckDataWrapper(tempDeck); - for(int r=0;r<(int)rules.size();r++){ - ddw->clearFilters(); - ddw->addFilter(ff->Construct(rules[r]->filter)); - ddw->validate(); - int ct = ddw->getCount(WSrcDeck::FILTERED_COPIES); - if(ct > topSize) { - topRule = r; - topSize = ct; - } - } - delete tempDeck; - delete ddw; - } - - string prior = activeStyle; - activeStyle = ""; - if(topRule >= 0){ - map::iterator mi = styles.find(rules[topRule]->style); - if(mi != styles.end()) - activeStyle = mi->first; - } - if(prior != activeStyle) - resources.Refresh(); - -} \ No newline at end of file + MTGDeck * tempDeck = NEW MTGDeck(GameApp::collection); + if (p1 && playerSrc != 2) tempDeck->add(p1); + if (p2 && playerSrc != 1) tempDeck->add(p2); + WCFilterFactory * ff = WCFilterFactory::GetInstance(); + + if (tempDeck) + { + DeckDataWrapper * ddw = NEW DeckDataWrapper(tempDeck); + for (int r = 0; r < (int) rules.size(); r++) + { + ddw->clearFilters(); + ddw->addFilter(ff->Construct(rules[r]->filter)); + ddw->validate(); + int ct = ddw->getCount(WSrcDeck::FILTERED_COPIES); + if (ct > topSize) + { + topRule = r; + topSize = ct; + } + } + delete tempDeck; + delete ddw; + } + + string prior = activeStyle; + activeStyle = ""; + if (topRule >= 0) + { + map::iterator mi = styles.find(rules[topRule]->style); + if (mi != styles.end()) activeStyle = mi->first; + } + if (prior != activeStyle) resources.Refresh(); + +} diff --git a/projects/mtg/src/Subtypes.cpp b/projects/mtg/src/Subtypes.cpp index 684729111..4111c553f 100644 --- a/projects/mtg/src/Subtypes.cpp +++ b/projects/mtg/src/Subtypes.cpp @@ -4,36 +4,39 @@ Subtypes * Subtypes::subtypesList = NEW Subtypes(); - -Subtypes::Subtypes(){ - //Add the more common types, so that they can be accessed through ints - //these should be added in the same order as the enum defined in subtypes.h!!! - find("Creature"); - find("Enchantment"); - find("Sorcery"); - find("Instant"); - find("Land"); - find("Artifact"); - find("Legendary"); +Subtypes::Subtypes() +{ + //Add the more common types, so that they can be accessed through ints + //these should be added in the same order as the enum defined in subtypes.h!!! + find("Creature"); + find("Enchantment"); + find("Sorcery"); + find("Instant"); + find("Land"); + find("Artifact"); + find("Legendary"); } -int Subtypes::find(string value, bool forceAdd){ - if (value[0]>=97 && value[0]<=122) value[0]-=32; //Poor man's camelcase. We assume strings we get are either Camelcased or lowercase - map::iterator it = values.find(value); - if (it != values.end()) return it->second; - if (!forceAdd) return 0; - int id = (int)(valuesById.size() + 1); - values[value] = id; - valuesById.push_back(value); - return id; +int Subtypes::find(string value, bool forceAdd) +{ + if (value[0] >= 97 && value[0] <= 122) value[0] -= 32; //Poor man's camelcase. We assume strings we get are either Camelcased or lowercase + map::iterator it = values.find(value); + if (it != values.end()) return it->second; + if (!forceAdd) return 0; + int id = (int) (valuesById.size() + 1); + values[value] = id; + valuesById.push_back(value); + return id; } -int Subtypes::find(const char * subtype, bool forceAdd){ - string value = subtype; - return find(value, forceAdd); +int Subtypes::find(const char * subtype, bool forceAdd) +{ + string value = subtype; + return find(value, forceAdd); } -string Subtypes::find(unsigned int id){ - if (valuesById.size() < id || !id) return ""; - return valuesById[id - 1]; +string Subtypes::find(unsigned int id) +{ + if (valuesById.size() < id || !id) return ""; + return valuesById[id - 1]; } diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index d2995150a..3a848f397 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -8,832 +8,1066 @@ #include "Counters.h" #include "WEvent.h" +TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInstance * card, MTGAbility * ability) +{ + if (!s.size()) return NULL; -TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInstance * card, MTGAbility * ability){ - if (!s.size()) return NULL; + int zones[10]; + int nbzones = 0; + size_t found; + bool other = false; - int zones[10]; - int nbzones = 0; - size_t found; - bool other = false; + found = s.find("mytgt"); + if (found == 0) + { + MTGCardInstance * target = card->target; + if (ability) target = (MTGCardInstance *) (ability->target); + return NEW CardTargetChooser(target, card); + }; - found = s.find("mytgt"); - if (found == 0){ - MTGCardInstance * target = card->target; - if (ability) target = (MTGCardInstance *) (ability->target); - return NEW CardTargetChooser(target,card); - }; + found = s.find("opponent"); + if (found == 0) + { + int maxtargets = 1; + Player * opponent = card->controller()->opponent(); + return NEW PlayerTargetChooser(card, maxtargets, opponent); + }; - found = s.find("opponent"); - if (found == 0){ - int maxtargets = 1; - Player * opponent = card->controller()->opponent(); - return NEW PlayerTargetChooser(card,maxtargets,opponent); - }; - - found = s.find("controller"); - if (found == 0){ - int maxtargets = 1; - Player * controller = card->controller(); - return NEW PlayerTargetChooser(card,maxtargets,controller); - }; + found = s.find("controller"); + if (found == 0) + { + int maxtargets = 1; + Player * controller = card->controller(); + return NEW PlayerTargetChooser(card, maxtargets, controller); + }; - found = s.find("other "); - if (found == 0){ - other = true; - s=s.substr(6); - } - - found = s.find("trigger"); - if (found == 0){ - if (s.length() > 7 && s.find("[") == 7) { - string s1 = s.substr(7,s.find("]")); - if (s1.find("to") != string::npos) return NEW TriggerTargetChooser(WEvent::TARGET_TO); - if (s1.find("from") != string::npos) return NEW TriggerTargetChooser(WEvent::TARGET_FROM); + found = s.find("other "); + if (found == 0) + { + other = true; + s = s.substr(6); } - return NEW TriggerTargetChooser(1); - } - found = s.find("player"); - if (found != string::npos){ + found = s.find("trigger"); + if (found == 0) + { + if (s.length() > 7 && s.find("[") == 7) + { + string s1 = s.substr(7, s.find("]")); + if (s1.find("to") != string::npos) return NEW TriggerTargetChooser(WEvent::TARGET_TO); + if (s1.find("from") != string::npos) return NEW TriggerTargetChooser(WEvent::TARGET_FROM); + } + return NEW TriggerTargetChooser(1); + } + + found = s.find("player"); + if (found != string::npos) + { + int maxtargets = 1; + size_t several = s.find_first_of('s', 5); + if (several != string::npos) maxtargets = -1; + found = s.find("creature"); + if (found != string::npos) return NEW DamageableTargetChooser(card, maxtargets, other); //Any Damageable target (player, creature) + return NEW PlayerTargetChooser(card, maxtargets); //Any player + } + + string s1; + found = s.find("|"); + if (found != string::npos) + { + string s2; + s1 = s.substr(0, found); + s2 = s.substr(found + 1); + while (s2.size()) + { + found = s2.find(","); + string zoneName; + if (found != string::npos) + { + zoneName = s2.substr(0, found); + s2 = s2.substr(found + 1); + } + else + { + zoneName = s2; + s2 = ""; + } + zones[nbzones] = MTGGameZone::MY_BATTLEFIELD; + + if (zoneName.compare("*") == 0) + { + zones[nbzones] = MTGGameZone::ALL_ZONES; + } + else if (zoneName.compare("graveyard") == 0) + { + zones[nbzones] = MTGGameZone::MY_GRAVEYARD; + nbzones++; + zones[nbzones] = MTGGameZone::OPPONENT_GRAVEYARD; + } + else if (zoneName.compare("battlefield") == 0 || zoneName.compare("inplay") == 0) + { + zones[nbzones] = MTGGameZone::MY_BATTLEFIELD; + nbzones++; + zones[nbzones] = MTGGameZone::OPPONENT_BATTLEFIELD; + } + else if (zoneName.compare("nonbattlezone") == 0) + { + zones[nbzones] = MTGGameZone::MY_GRAVEYARD; + nbzones++; + zones[nbzones] = MTGGameZone::OPPONENT_GRAVEYARD; + nbzones++; + zones[nbzones] = MTGGameZone::MY_LIBRARY; + nbzones++; + zones[nbzones] = MTGGameZone::OPPONENT_LIBRARY; + nbzones++; + zones[nbzones] = MTGGameZone::MY_HAND; + nbzones++; + zones[nbzones] = MTGGameZone::OPPONENT_HAND; + nbzones++; + zones[nbzones] = MTGGameZone::MY_EXILE; + nbzones++; + zones[nbzones] = MTGGameZone::OPPONENT_EXILE; + } + else if (zoneName.compare("stack") == 0) + { + zones[nbzones] = MTGGameZone::MY_STACK; + nbzones++; + zones[nbzones] = MTGGameZone::OPPONENT_STACK; + } + else + { + int zone = MTGGameZone::zoneStringToId(zoneName); + if (zone) zones[nbzones] = zone; + } + nbzones++; + } + } + else + { + s1 = s; + nbzones = 2; + zones[0] = MTGGameZone::MY_BATTLEFIELD; + zones[1] = MTGGameZone::OPPONENT_BATTLEFIELD; + } + + TargetChooser * tc = NULL; int maxtargets = 1; - size_t several = s.find_first_of('s',5); - if (several != string::npos) maxtargets = -1; - found = s.find("creature"); - if (found != string::npos) return NEW DamageableTargetChooser(card,maxtargets,other); //Any Damageable target (player, creature) - return NEW PlayerTargetChooser(card,maxtargets); //Any player - } + CardDescriptor * cd = NULL; - string s1; - found = s.find("|"); - if (found != string::npos){ - string s2; - s1 = s.substr(0,found); - s2 = s.substr(found+1); - while(s2.size()){ - found = s2.find(","); - string zoneName; - if (found != string::npos){ - zoneName = s2.substr(0,found); - s2 = s2.substr(found+1); - }else{ - zoneName = s2; - s2 = ""; - } - zones[nbzones] = MTGGameZone::MY_BATTLEFIELD; - - if(zoneName.compare("*") == 0){ - zones[nbzones] = MTGGameZone::ALL_ZONES; - }else if(zoneName.compare("graveyard") == 0){ - zones[nbzones] = MTGGameZone::MY_GRAVEYARD; - nbzones++; - zones[nbzones] = MTGGameZone::OPPONENT_GRAVEYARD; - }else if(zoneName.compare("battlefield") == 0 || zoneName.compare("inplay") == 0){ - zones[nbzones] = MTGGameZone::MY_BATTLEFIELD; - nbzones++; - zones[nbzones] = MTGGameZone::OPPONENT_BATTLEFIELD; - }else if(zoneName.compare("nonbattlezone") == 0){ - zones[nbzones] = MTGGameZone::MY_GRAVEYARD; - nbzones++; - zones[nbzones] = MTGGameZone::OPPONENT_GRAVEYARD; - nbzones++; - zones[nbzones] = MTGGameZone::MY_LIBRARY; - nbzones++; - zones[nbzones] = MTGGameZone::OPPONENT_LIBRARY; - nbzones++; - zones[nbzones] = MTGGameZone::MY_HAND; - nbzones++; - zones[nbzones] = MTGGameZone::OPPONENT_HAND; - nbzones++; - zones[nbzones] = MTGGameZone::MY_EXILE; - nbzones++; - zones[nbzones] = MTGGameZone::OPPONENT_EXILE; - }else if(zoneName.compare("stack") == 0){ - zones[nbzones] = MTGGameZone::MY_STACK; - nbzones++; - zones[nbzones] = MTGGameZone::OPPONENT_STACK; - }else{ - int zone = MTGGameZone::zoneStringToId(zoneName); - if (zone) zones[nbzones] = zone; - } - nbzones++; - } - }else{ - s1 = s; - nbzones = 2; - zones[0]= MTGGameZone::MY_BATTLEFIELD; - zones[1]= MTGGameZone::OPPONENT_BATTLEFIELD; - } - - TargetChooser * tc = NULL; - int maxtargets = 1; - CardDescriptor * cd = NULL; - - while(s1.size()){ - found = s1.find(","); - string typeName; - if (found != string::npos){ - typeName = s1.substr(0,found); - s1 = s1.substr(found+1); - }else{ - typeName = s1; - s1 = ""; - } - - //Advanced cards caracteristics ? - found = typeName.find("["); - if (found != string::npos){ - int nbminuses = 0; - int end = typeName.find("]"); - string attributes = typeName.substr(found+1,end-found-1); - cd = NEW CardDescriptor(); - while(attributes.size()){ - size_t found2 = attributes.find(";"); - string attribute; - if (found2 != string::npos){ - cd->mode = CD_OR; - attribute = attributes.substr(0,found2); - attributes = attributes.substr(found2+1); - }else{ - attribute = attributes; - attributes = ""; + while (s1.size()) + { + found = s1.find(","); + string typeName; + if (found != string::npos) + { + typeName = s1.substr(0, found); + s1 = s1.substr(found + 1); } - int minus = 0; - if (attribute[0] == '-'){ - minus = 1; - nbminuses++; - attribute=attribute.substr(1); + else + { + typeName = s1; + s1 = ""; } - int comparisonMode = COMPARISON_NONE; - int comparisonCriterion = 0; - if (attribute.size() > 1){ - size_t operatorPosition = attribute.find("=",1); - if (operatorPosition != string::npos){ - comparisonCriterion = atoi(attribute.substr(operatorPosition+1,attribute.size()-operatorPosition-1).c_str()); - switch (attribute[operatorPosition-1]){ - case '<': - if (minus){ - comparisonMode = COMPARISON_GREATER; - }else{ - comparisonMode = COMPARISON_AT_MOST; + + //Advanced cards caracteristics ? + found = typeName.find("["); + if (found != string::npos) + { + int nbminuses = 0; + int end = typeName.find("]"); + string attributes = typeName.substr(found + 1, end - found - 1); + cd = NEW CardDescriptor(); + while (attributes.size()) + { + size_t found2 = attributes.find(";"); + string attribute; + if (found2 != string::npos) + { + cd->mode = CD_OR; + attribute = attributes.substr(0, found2); + attributes = attributes.substr(found2 + 1); } - operatorPosition--; - break; - case '>': - if (minus){ - comparisonMode = COMPARISON_LESS; - }else{ - comparisonMode = COMPARISON_AT_LEAST; + else + { + attribute = attributes; + attributes = ""; } - operatorPosition--; - break; - default: - if (minus){ - comparisonMode = COMPARISON_UNEQUAL; - }else{ - comparisonMode = COMPARISON_EQUAL; + int minus = 0; + if (attribute[0] == '-') + { + minus = 1; + nbminuses++; + attribute = attribute.substr(1); + } + int comparisonMode = COMPARISON_NONE; + int comparisonCriterion = 0; + if (attribute.size() > 1) + { + size_t operatorPosition = attribute.find("=", 1); + if (operatorPosition != string::npos) + { + comparisonCriterion = atoi( + attribute.substr(operatorPosition + 1, attribute.size() - operatorPosition - 1).c_str()); + switch (attribute[operatorPosition - 1]) + { + case '<': + if (minus) + { + comparisonMode = COMPARISON_GREATER; + } + else + { + comparisonMode = COMPARISON_AT_MOST; + } + operatorPosition--; + break; + case '>': + if (minus) + { + comparisonMode = COMPARISON_LESS; + } + else + { + comparisonMode = COMPARISON_AT_LEAST; + } + operatorPosition--; + break; + default: + if (minus) + { + comparisonMode = COMPARISON_UNEQUAL; + } + else + { + comparisonMode = COMPARISON_EQUAL; + } + } + attribute = attribute.substr(0, operatorPosition); + } + } + + //Attacker + if (attribute.find("attacking") != string::npos) + { + if (minus) + { + cd->attacker = -1; + } + else + { + cd->attacker = 1; + } + } + //Blocker + else if (attribute.find("blocking") != string::npos) + { + if (minus) + { + cd->defenser = &MTGCardInstance::NoCard; + } + else + { + cd->defenser = &MTGCardInstance::AnyCard; + } + } + //Tapped, untapped + else if (attribute.find("tapped") != string::npos) + { + if (minus) + { + cd->unsecureSetTapped(-1); + } + else + { + cd->unsecureSetTapped(1); + } + //Token + } + else if (attribute.find("token") != string::npos) + { + if (minus) + { + cd->isToken = -1; + } + else + { + cd->isToken = 1; + } + //put in its zone this turn + } + else if (attribute.find("fresh") != string::npos) + { + if (minus) + { + cd->unsecuresetfresh(-1); + } + else + { + cd->unsecuresetfresh(1); + } + //Power restrictions + } + else if (attribute.find("power") != string::npos) + { + cd->setPower(comparisonCriterion); + cd->powerComparisonMode = comparisonMode; + //Toughness restrictions + } + else if (attribute.find("toughness") != string::npos) + { + cd->setToughness(comparisonCriterion); + cd->toughnessComparisonMode = comparisonMode; + //Manacost restrictions + } + else if (attribute.find("manacost") != string::npos) + { + cd->convertedManacost = comparisonCriterion; + cd->manacostComparisonMode = comparisonMode; + //Counter Restrictions + } + else if (attribute.find("counter") != string::npos) + { + if (attribute.find("{any}") != string::npos) + { + cd->anyCounter = 1; + } + else + { + size_t start = attribute.find("{"); + size_t end = attribute.find("}"); + string counterString = attribute.substr(start + 1, end - start - 1); + AbilityFactory abf; + Counter * counter = abf.parseCounter(counterString, card); + if (counter) + { + cd->counterName = counter->name; + cd->counterNB = counter->nb; + cd->counterPower = counter->power; + cd->counterToughness = counter->toughness; + delete (counter); + } + if (minus) + { + cd->counterComparisonMode = COMPARISON_LESS; + } + else + { + cd->counterComparisonMode = COMPARISON_AT_LEAST; + } + } + } + else + { + int attributefound = 0; + //Colors + for (int cid = 1; cid < Constants::MTG_NB_COLORS - 1; cid++) + { //remove Artifact and Land from the loop + if (attribute.find(Constants::MTGColorStrings[cid]) != string::npos) + { + attributefound = 1; + if (minus) + { + cd->colors[cid] = -1; + } + else + { + cd->colors[cid] = 1; + } + } + } + if (!attributefound) + { + //Abilities + for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++) + { + if (attribute.find(Constants::MTGBasicAbilities[j]) != string::npos) + { + attributefound = 1; + if (minus) + { + cd->basicAbilities[j] = -1; + } + else + { + cd->basicAbilities[j] = 1; + } + } + } + } + + if (!attributefound) + { + //Subtypes + if (minus) + { + cd->setNegativeSubtype(attribute); + } + else + { + cd->setSubtype(attribute); + } + } } } - attribute = attribute.substr(0,operatorPosition); - } + if (nbminuses) cd->mode = CD_AND; + typeName = typeName.substr(0, found); } + //X targets allowed ? + if (typeName.at(typeName.length() - 1) == 's' && !Subtypes::subtypesList->find(typeName, false) && typeName.compare("this") + != 0) + { + typeName = typeName.substr(0, typeName.length() - 1); + maxtargets = -1; + } + if (cd) + { + if (!tc) + { + if (typeName.compare("*") != 0) cd->setSubtype(typeName); - //Attacker - if (attribute.find("attacking") != string::npos){ - if (minus){ - cd->attacker = -1; - }else{ - cd->attacker = 1; - } - } - //Blocker - else if (attribute.find("blocking") != string::npos){ - if (minus){ - cd->defenser = & MTGCardInstance::NoCard; - }else{ - cd->defenser = & MTGCardInstance::AnyCard; - } - } - //Tapped, untapped - else if (attribute.find("tapped") != string::npos){ - if (minus){ - cd->unsecureSetTapped(-1); - }else{ - cd->unsecureSetTapped(1); - } - //Token - }else if (attribute.find("token") != string::npos){ - if (minus){ - cd->isToken = -1; - }else{ - cd->isToken = 1; - } - //put in its zone this turn - }else if (attribute.find("fresh") != string::npos){ - if (minus){ - cd->unsecuresetfresh(-1); - }else{ - cd->unsecuresetfresh(1); - } - //Power restrictions - }else if (attribute.find("power") != string::npos){ - cd->setPower(comparisonCriterion); - cd->powerComparisonMode = comparisonMode; - //Toughness restrictions - }else if (attribute.find("toughness") != string::npos){ - cd->setToughness(comparisonCriterion); - cd->toughnessComparisonMode = comparisonMode; - //Manacost restrictions - }else if (attribute.find("manacost") != string::npos){ - cd->convertedManacost = comparisonCriterion; - cd->manacostComparisonMode = comparisonMode; - //Counter Restrictions - }else if (attribute.find("counter") != string::npos) { - if (attribute.find("{any}") != string::npos) { - cd->anyCounter = 1; - }else{ - size_t start = attribute.find("{"); - size_t end = attribute.find("}"); - string counterString = attribute.substr(start+1,end-start-1); - AbilityFactory abf; - Counter * counter = abf.parseCounter(counterString,card); - if (counter) { - cd->counterName = counter->name; - cd->counterNB = counter->nb; - cd->counterPower = counter->power; - cd->counterToughness = counter->toughness; - delete(counter); + tc = NEW DescriptorTargetChooser(cd, zones, nbzones, card, maxtargets, other); } - if (minus) { - cd->counterComparisonMode = COMPARISON_LESS; - }else{ - cd->counterComparisonMode = COMPARISON_AT_LEAST; + else + { + delete (cd); + return NULL; } - } - }else{ - int attributefound = 0; - //Colors - for (int cid = 1; cid < Constants::MTG_NB_COLORS - 1; cid++){ //remove Artifact and Land from the loop - if (attribute.find(Constants::MTGColorStrings[cid]) != string::npos){ - attributefound = 1; - if (minus){ - cd->colors[cid] = -1; - }else{ - cd->colors[cid] = 1; - } - } - } - if (!attributefound){ - //Abilities - for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ - if (attribute.find(Constants::MTGBasicAbilities[j]) != string::npos){ - attributefound = 1; - if (minus){ - cd->basicAbilities[j] = -1; - }else{ - cd->basicAbilities[j] = 1; - } - } - } - } - - if (!attributefound){ - //Subtypes - if (minus){ - cd->setNegativeSubtype(attribute); - }else{ - cd->setSubtype(attribute); - } - } } - } - if (nbminuses) cd->mode = CD_AND; - typeName = typeName.substr(0,found); - } - //X targets allowed ? - if (typeName.at(typeName.length()-1) == 's' && !Subtypes::subtypesList->find(typeName,false) && typeName.compare("this")!=0){ - typeName = typeName.substr(0,typeName.length()-1); - maxtargets = -1; - } - if (cd){ - if (!tc){ - if (typeName.compare("*")!=0) cd->setSubtype(typeName); - - tc = NEW DescriptorTargetChooser(cd,zones,nbzones,card,maxtargets,other); - }else{ - delete(cd); - return NULL; - } - }else{ - if (!tc){ - if (typeName.compare("*")==0){ - return NEW TargetZoneChooser(zones, nbzones,card, maxtargets,other); - }else if (typeName.compare("this")==0){ - return NEW CardTargetChooser(card,card,zones, nbzones); - }else{ - tc = NEW TypeTargetChooser(typeName.c_str(), zones, nbzones, card,maxtargets,other); + else + { + if (!tc) + { + if (typeName.compare("*") == 0) + { + return NEW TargetZoneChooser(zones, nbzones, card, maxtargets, other); + } + else if (typeName.compare("this") == 0) + { + return NEW CardTargetChooser(card, card, zones, nbzones); + } + else + { + tc = NEW TypeTargetChooser(typeName.c_str(), zones, nbzones, card, maxtargets, other); + } + } + else + { + ((TypeTargetChooser *) tc)->addType(typeName.c_str()); + tc->maxtargets = maxtargets; + } } - }else{ - ((TypeTargetChooser *)tc)->addType(typeName.c_str()); - tc->maxtargets = maxtargets; - } } - } - return tc; + return tc; } -TargetChooser * TargetChooserFactory::createTargetChooser(MTGCardInstance * card){ - int id = card->getId(); - string s = card->spellTargetType; - if (card->alias){ - id = card->alias; - //TODO load target as well... ? - } - TargetChooser * tc = createTargetChooser(s, card); - if (tc) return tc; - //Any target than cannot be defined automatically is determined by its id - switch (id){ +TargetChooser * TargetChooserFactory::createTargetChooser(MTGCardInstance * card) +{ + int id = card->getId(); + string s = card->spellTargetType; + if (card->alias) + { + id = card->alias; + //TODO load target as well... ? + } + TargetChooser * tc = createTargetChooser(s, card); + if (tc) return tc; + //Any target than cannot be defined automatically is determined by its id + switch (id) + { //Spell - case 1224: //Spell blast + case 1224: //Spell blast { #if defined (WIN32) || defined (LINUX) - DebugTrace("Counter Spell !\n"); + DebugTrace("Counter Spell !\n"); #endif - return NEW SpellTargetChooser(card); + return NEW SpellTargetChooser(card); } - //Spell Or Permanent - case 1282: //ChaosLace - case 1152: //DeathLace - case 1358: //PureLace - case 1227: //ThoughLace - case 1257: //Lifelace + //Spell Or Permanent + case 1282: //ChaosLace + case 1152: //DeathLace + case 1358: //PureLace + case 1227: //ThoughLace + case 1257: //Lifelace { - return NEW SpellOrPermanentTargetChooser(card); + return NEW SpellOrPermanentTargetChooser(card); } - //Red Spell or Permanent - case 1191: //Blue Elemental Blast + //Red Spell or Permanent + case 1191: //Blue Elemental Blast { - return NEW SpellOrPermanentTargetChooser(card,Constants::MTG_COLOR_RED); + return NEW SpellOrPermanentTargetChooser(card, Constants::MTG_COLOR_RED); } - //Blue Spell or Permanent - case 1312: //Red Elemental Blast + //Blue Spell or Permanent + case 1312: //Red Elemental Blast { - return NEW SpellOrPermanentTargetChooser(card,Constants::MTG_COLOR_BLUE); + return NEW SpellOrPermanentTargetChooser(card, Constants::MTG_COLOR_BLUE); } - //Damage History - case 1344: //Eye for an Eye + //Damage History + case 1344: //Eye for an Eye { - return NEW DamageTargetChooser(card,-1,1,RESOLVED_OK); + return NEW DamageTargetChooser(card, -1, 1, RESOLVED_OK); } - default: + default: { - return NULL; + return NULL; + } } - } } - -TargetChooser::TargetChooser(MTGCardInstance * card, int _maxtargets, bool _other): TargetsList(){ - forceTargetListReady = 0; - source = card; - targetter = card; - maxtargets = _maxtargets; - other = _other; +TargetChooser::TargetChooser(MTGCardInstance * card, int _maxtargets, bool _other) : + TargetsList() +{ + forceTargetListReady = 0; + source = card; + targetter = card; + maxtargets = _maxtargets; + other = _other; } //Default targetter : every card can be targetted, unless it is protected from the targetter card // For spells that do not "target" a specific card, set targetter to NULL -bool TargetChooser::canTarget(Targetable * target){ - if (!target) return false; - if (target->typeAsTarget() == TARGET_CARD){ - MTGCardInstance * card = (MTGCardInstance *) target; - if (other){ - MTGCardInstance * tempcard = card; - while (tempcard) { - if (tempcard == source) return false; - tempcard = tempcard->previous; - } - } - if (source && targetter && card->isInPlay() && (card->has(Constants::SHROUD)|| card->protectedAgainst(targetter) )) return false; - if (source && targetter && card->isInPlay() && (targetter->controller() != card->controller()) && (card->has(Constants::OPPONENTSHROUD) || card->protectedAgainst(targetter))) return false; - return true; - } - else if (target->typeAsTarget() == TARGET_STACKACTION) - return true; - return false; -} - - -int TargetChooser::addTarget(Targetable * target){ - if (canTarget(target)){ - TargetsList::addTarget(target); - } - - return targetsReadyCheck(); -} - - -int TargetChooser::ForceTargetListReady(){ - int state = targetsReadyCheck() ; - if (state == TARGET_OK){ - forceTargetListReady = 1; - } - return forceTargetListReady; -} - -int TargetChooser::targetsReadyCheck(){ - if (cursor == 0){ - return TARGET_NOK; - } - if (full()){ - return TARGET_OK_FULL; - } - if (!ready()){ - return TARGET_OK_NOT_READY; - } - return TARGET_OK; -} - -int TargetChooser::targetListSet(){ - int state = targetsReadyCheck(); - if (state == TARGET_OK_FULL || forceTargetListReady){ - return 1; - } - return 0; -} - -bool TargetChooser::validTargetsExist(){ - for (int i = 0; i < 2; ++i){ - Player *p = GameObserver::GetInstance()->players[i]; - if (canTarget(p)) return true; - MTGGameZone * zones[] = {p->game->inPlay,p->game->graveyard,p->game->hand,p->game->library}; - for (int k = 0; k < 4; k++){ - MTGGameZone * z = zones[k]; - if (targetsZone(z)){ - for (int j = 0; j < z->nb_cards; j++){ - if (canTarget(z->cards[j])) return true; +bool TargetChooser::canTarget(Targetable * target) +{ + if (!target) return false; + if (target->typeAsTarget() == TARGET_CARD) + { + MTGCardInstance * card = (MTGCardInstance *) target; + if (other) + { + MTGCardInstance * tempcard = card; + while (tempcard) + { + if (tempcard == source) return false; + tempcard = tempcard->previous; + } } - } + if (source && targetter && card->isInPlay() && (card->has(Constants::SHROUD) || card->protectedAgainst(targetter))) return false; + if (source && targetter && card->isInPlay() && (targetter->controller() != card->controller()) && (card->has( + Constants::OPPONENTSHROUD) || card->protectedAgainst(targetter))) return false; + return true; } - } - return false; + else if (target->typeAsTarget() == TARGET_STACKACTION) return true; + return false; } -/** - a specific Card -**/ -CardTargetChooser::CardTargetChooser(MTGCardInstance * _card, MTGCardInstance * source,int * _zones, int _nbzones):TargetZoneChooser(_zones,_nbzones,source){ - validTarget = _card; +int TargetChooser::addTarget(Targetable * target) +{ + if (canTarget(target)) + { + TargetsList::addTarget(target); + } + + return targetsReadyCheck(); } -bool CardTargetChooser::canTarget(Targetable * target ){ - if (!target) return false; - if (target->typeAsTarget() != TARGET_CARD) return false; - if (!nbzones && !TargetChooser::canTarget(target)) return false; - if (nbzones && !TargetZoneChooser::canTarget(target)) return false; - MTGCardInstance * card = (MTGCardInstance *) target; - while (card) { - if (card == validTarget) return true; - card = card->previous; - } - return false; +int TargetChooser::ForceTargetListReady() +{ + int state = targetsReadyCheck(); + if (state == TARGET_OK) + { + forceTargetListReady = 1; + } + return forceTargetListReady; } - CardTargetChooser * CardTargetChooser::clone() const{ - CardTargetChooser * a = NEW CardTargetChooser(*this); - return a; - } - -/** - Choose anything that has a given list of types -**/ -TypeTargetChooser::TypeTargetChooser(const char * _type, MTGCardInstance * card, int _maxtargets,bool other):TargetZoneChooser(card, _maxtargets,other){ - int id = Subtypes::subtypesList->find(_type); - nbtypes = 0; - addType(id); - int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; - init(default_zones,2); +int TargetChooser::targetsReadyCheck() +{ + if (cursor == 0) + { + return TARGET_NOK; + } + if (full()) + { + return TARGET_OK_FULL; + } + if (!ready()) + { + return TARGET_OK_NOT_READY; + } + return TARGET_OK; } -TypeTargetChooser::TypeTargetChooser(const char * _type, int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets,bool other):TargetZoneChooser(card, _maxtargets,other){ - int id = Subtypes::subtypesList->find(_type); - nbtypes = 0; - addType(id); - if (nbzones == 0){ - int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; - init(default_zones,2); - }else{ - init(_zones, nbzones); - } +int TargetChooser::targetListSet() +{ + int state = targetsReadyCheck(); + if (state == TARGET_OK_FULL || forceTargetListReady) + { + return 1; + } + return 0; } -void TypeTargetChooser::addType(const char * _type){ - int id = Subtypes::subtypesList->find(_type); - addType(id); -} - -void TypeTargetChooser::addType(int type){ - types[nbtypes] = type; - nbtypes++; -} - -bool TypeTargetChooser::canTarget(Targetable * target){ - if (!TargetZoneChooser::canTarget(target)) return false; - if (target->typeAsTarget() == TARGET_CARD){ - MTGCardInstance * card = (MTGCardInstance *) target; - for (int i= 0; i < nbtypes; i++){ - if (card->hasSubtype(types[i])) return true; - if (Subtypes::subtypesList->find(card->getLCName()) == types[i]) return true; +bool TargetChooser::validTargetsExist() +{ + for (int i = 0; i < 2; ++i) + { + Player *p = GameObserver::GetInstance()->players[i]; + if (canTarget(p)) return true; + MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library }; + for (int k = 0; k < 4; k++) + { + MTGGameZone * z = zones[k]; + if (targetsZone(z)) + { + for (int j = 0; j < z->nb_cards; j++) + { + if (canTarget(z->cards[j])) return true; + } + } + } } return false; - }else if (target->typeAsTarget() == TARGET_STACKACTION){ - Interruptible * action = (Interruptible *) target; - if (action->type == ACTION_SPELL && action->state==NOT_RESOLVED){ - Spell * spell = (Spell *) action; - MTGCardInstance * card = spell->source; - for (int i= 0; i < nbtypes; i++){ - if (card->hasSubtype(types[i])) return true; - if (Subtypes::subtypesList->find(card->name) == types[i]) return true; - } - return false; - } - } - return false; } - TypeTargetChooser * TypeTargetChooser::clone() const{ - TypeTargetChooser * a = NEW TypeTargetChooser(*this); - return a; - } - - /** - A Target Chooser associated to a Card Descriptor object, for fine tuning of targets description -**/ -DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ - int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; - init(default_zones,2); - cd = _cd; + a specific Card + **/ +CardTargetChooser::CardTargetChooser(MTGCardInstance * _card, MTGCardInstance * source, int * _zones, int _nbzones) : + TargetZoneChooser(_zones, _nbzones, source) +{ + validTarget = _card; } -DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ - if (nbzones == 0){ - int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; - init(default_zones,2); - }else{ - init(_zones, nbzones); - } - cd = _cd; -} - -bool DescriptorTargetChooser::canTarget(Targetable * target){ - if (!TargetZoneChooser::canTarget(target)) return false; - if (target->typeAsTarget() == TARGET_CARD){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if (cd->match(_target)) return true; - }else if (target->typeAsTarget() == TARGET_STACKACTION){ - Interruptible * action = (Interruptible *) target; - if (action->type == ACTION_SPELL && action->state==NOT_RESOLVED){ - Spell * spell = (Spell *) action; - MTGCardInstance * card = spell->source; - if (cd->match(card)) return true; - } - } - return false; -} - -DescriptorTargetChooser::~DescriptorTargetChooser(){ - SAFE_DELETE(cd); -} - - DescriptorTargetChooser * DescriptorTargetChooser ::clone() const{ - DescriptorTargetChooser * a = NEW DescriptorTargetChooser (*this); - a->cd = NEW CardDescriptor(*cd); - return a; - } - - -/** - Choose a creature -**/ - -CreatureTargetChooser::CreatureTargetChooser( MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ - int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; - init(default_zones,2); -} - -CreatureTargetChooser::CreatureTargetChooser(int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ - if (nbzones == 0){ - int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; - init(default_zones,2); - }else{ - init(_zones, nbzones); - } -} - - -bool CreatureTargetChooser::canTarget(Targetable * target){ - if (!TargetZoneChooser::canTarget(target)) return false; - if (target->typeAsTarget() == TARGET_CARD){ +bool CardTargetChooser::canTarget(Targetable * target) +{ + if (!target) return false; + if (target->typeAsTarget() != TARGET_CARD) return false; + if (!nbzones && !TargetChooser::canTarget(target)) return false; + if (nbzones && !TargetZoneChooser::canTarget(target)) return false; MTGCardInstance * card = (MTGCardInstance *) target; - return card->isCreature(); - } - return false; + while (card) + { + if (card == validTarget) return true; + card = card->previous; + } + return false; } - CreatureTargetChooser * CreatureTargetChooser::clone() const{ - CreatureTargetChooser * a = NEW CreatureTargetChooser(*this); +CardTargetChooser * CardTargetChooser::clone() const +{ + CardTargetChooser * a = NEW CardTargetChooser(*this); return a; - } +} +/** + Choose anything that has a given list of types + **/ +TypeTargetChooser::TypeTargetChooser(const char * _type, MTGCardInstance * card, int _maxtargets, bool other) : + TargetZoneChooser(card, _maxtargets, other) +{ + int id = Subtypes::subtypesList->find(_type); + nbtypes = 0; + addType(id); + int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; + init(default_zones, 2); +} + +TypeTargetChooser::TypeTargetChooser(const char * _type, int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, + bool other) : + TargetZoneChooser(card, _maxtargets, other) +{ + int id = Subtypes::subtypesList->find(_type); + nbtypes = 0; + addType(id); + if (nbzones == 0) + { + int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; + init(default_zones, 2); + } + else + { + init(_zones, nbzones); + } +} + +void TypeTargetChooser::addType(const char * _type) +{ + int id = Subtypes::subtypesList->find(_type); + addType(id); +} + +void TypeTargetChooser::addType(int type) +{ + types[nbtypes] = type; + nbtypes++; +} + +bool TypeTargetChooser::canTarget(Targetable * target) +{ + if (!TargetZoneChooser::canTarget(target)) return false; + if (target->typeAsTarget() == TARGET_CARD) + { + MTGCardInstance * card = (MTGCardInstance *) target; + for (int i = 0; i < nbtypes; i++) + { + if (card->hasSubtype(types[i])) return true; + if (Subtypes::subtypesList->find(card->getLCName()) == types[i]) return true; + } + return false; + } + else if (target->typeAsTarget() == TARGET_STACKACTION) + { + Interruptible * action = (Interruptible *) target; + if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) + { + Spell * spell = (Spell *) action; + MTGCardInstance * card = spell->source; + for (int i = 0; i < nbtypes; i++) + { + if (card->hasSubtype(types[i])) return true; + if (Subtypes::subtypesList->find(card->name) == types[i]) return true; + } + return false; + } + } + return false; +} + +TypeTargetChooser * TypeTargetChooser::clone() const +{ + TypeTargetChooser * a = NEW TypeTargetChooser(*this); + return a; +} + +/** + A Target Chooser associated to a Card Descriptor object, for fine tuning of targets description + **/ +DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, MTGCardInstance * card, int _maxtargets, bool other) : + TargetZoneChooser(card, _maxtargets, other) +{ + int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; + init(default_zones, 2); + cd = _cd; +} + +DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, int * _zones, int nbzones, MTGCardInstance * card, + int _maxtargets, bool other) : + TargetZoneChooser(card, _maxtargets, other) +{ + if (nbzones == 0) + { + int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; + init(default_zones, 2); + } + else + { + init(_zones, nbzones); + } + cd = _cd; +} + +bool DescriptorTargetChooser::canTarget(Targetable * target) +{ + if (!TargetZoneChooser::canTarget(target)) return false; + if (target->typeAsTarget() == TARGET_CARD) + { + MTGCardInstance * _target = (MTGCardInstance *) target; + if (cd->match(_target)) return true; + } + else if (target->typeAsTarget() == TARGET_STACKACTION) + { + Interruptible * action = (Interruptible *) target; + if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) + { + Spell * spell = (Spell *) action; + MTGCardInstance * card = spell->source; + if (cd->match(card)) return true; + } + } + return false; +} + +DescriptorTargetChooser::~DescriptorTargetChooser() +{ + SAFE_DELETE(cd); +} + +DescriptorTargetChooser * DescriptorTargetChooser::clone() const +{ + DescriptorTargetChooser * a = NEW DescriptorTargetChooser(*this); + a->cd = NEW CardDescriptor(*cd); + return a; +} + +/** + Choose a creature + **/ + +CreatureTargetChooser::CreatureTargetChooser(MTGCardInstance * card, int _maxtargets, bool other) : + TargetZoneChooser(card, _maxtargets, other) +{ + int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; + init(default_zones, 2); +} + +CreatureTargetChooser::CreatureTargetChooser(int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other) : + TargetZoneChooser(card, _maxtargets, other) +{ + if (nbzones == 0) + { + int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; + init(default_zones, 2); + } + else + { + init(_zones, nbzones); + } +} + +bool CreatureTargetChooser::canTarget(Targetable * target) +{ + if (!TargetZoneChooser::canTarget(target)) return false; + if (target->typeAsTarget() == TARGET_CARD) + { + MTGCardInstance * card = (MTGCardInstance *) target; + return card->isCreature(); + } + return false; +} + +CreatureTargetChooser * CreatureTargetChooser::clone() const +{ + CreatureTargetChooser * a = NEW CreatureTargetChooser(*this); + return a; +} /* TargetzoneChooser targets everything in a given zone */ -TargetZoneChooser::TargetZoneChooser(MTGCardInstance * card, int _maxtargets, bool other):TargetChooser(card,_maxtargets, other){ - init(NULL,0); +TargetZoneChooser::TargetZoneChooser(MTGCardInstance * card, int _maxtargets, bool other) : + TargetChooser(card, _maxtargets, other) +{ + init(NULL, 0); } -TargetZoneChooser::TargetZoneChooser(int * _zones, int _nbzones,MTGCardInstance * card, int _maxtargets, bool other):TargetChooser(card,_maxtargets, other){ - init(_zones, _nbzones); +TargetZoneChooser::TargetZoneChooser(int * _zones, int _nbzones, MTGCardInstance * card, int _maxtargets, bool other) : + TargetChooser(card, _maxtargets, other) +{ + init(_zones, _nbzones); } -int TargetZoneChooser::init(int * _zones, int _nbzones){ - for (int i = 0; i < _nbzones; i++){ - zones[i] = _zones[i]; - } - nbzones = _nbzones; - return nbzones; -} - -int TargetZoneChooser::setAllZones(){ - int zones[] = { - MTGGameZone::ALL_ZONES, - }; - - init(zones,1); - return 1; -} - - -bool TargetZoneChooser::canTarget(Targetable * target){ - if (!TargetChooser::canTarget(target)) return false; - if (target->typeAsTarget() == TARGET_CARD){ - MTGCardInstance * card = (MTGCardInstance *) target; - for (int i = 0; ihasCard(card)) return true; +int TargetZoneChooser::init(int * _zones, int _nbzones) +{ + for (int i = 0; i < _nbzones; i++) + { + zones[i] = _zones[i]; } - }else if (target->typeAsTarget() == TARGET_STACKACTION){ - DebugTrace("CHECKING INTERRUPTIBLE\n"); - Interruptible * action = (Interruptible *) target; - if (action->type == ACTION_SPELL && action->state==NOT_RESOLVED){ - Spell * spell = (Spell *) action; - MTGCardInstance * card = spell->source; - for (int i = 0; ihasCard(card)) return true; + nbzones = _nbzones; + return nbzones; +} + +int TargetZoneChooser::setAllZones() +{ + int zones[] = { MTGGameZone::ALL_ZONES, }; + + init(zones, 1); + return 1; +} + +bool TargetZoneChooser::canTarget(Targetable * target) +{ + if (!TargetChooser::canTarget(target)) return false; + if (target->typeAsTarget() == TARGET_CARD) + { + MTGCardInstance * card = (MTGCardInstance *) target; + for (int i = 0; i < nbzones; i++) + { + if (zones[i] == MTGGameZone::ALL_ZONES) return true; + if (MTGGameZone::intToZone(zones[i], source, card)->hasCard(card)) return true; + } } - } - return false; + else if (target->typeAsTarget() == TARGET_STACKACTION) + { + DebugTrace("CHECKING INTERRUPTIBLE\n"); + Interruptible * action = (Interruptible *) target; + if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) + { + Spell * spell = (Spell *) action; + MTGCardInstance * card = spell->source; + for (int i = 0; i < nbzones; i++) + if (MTGGameZone::intToZone(zones[i], source, card)->hasCard(card)) return true; + } + } + return false; } - -bool TargetZoneChooser::targetsZone(MTGGameZone * z){ - for (int i = 0; i < nbzones; i++) - if (MTGGameZone::intToZone(zones[i],source) == z) return true; - return false; +bool TargetZoneChooser::targetsZone(MTGGameZone * z) +{ + for (int i = 0; i < nbzones; i++) + if (MTGGameZone::intToZone(zones[i], source) == z) return true; + return false; } - TargetZoneChooser * TargetZoneChooser::clone() const{ - TargetZoneChooser * a = NEW TargetZoneChooser(*this); +TargetZoneChooser * TargetZoneChooser::clone() const +{ + TargetZoneChooser * a = NEW TargetZoneChooser(*this); return a; - } +} /* Player Target */ -PlayerTargetChooser::PlayerTargetChooser(MTGCardInstance * card, int _maxtargets, Player *p):TargetChooser(card, _maxtargets), p(p){ +PlayerTargetChooser::PlayerTargetChooser(MTGCardInstance * card, int _maxtargets, Player *p) : + TargetChooser(card, _maxtargets), p(p) +{ } -bool PlayerTargetChooser::canTarget(Targetable * target){ -if (source && targetter && (targetter->controller() != targetter->controller()->opponent()) && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::CONTROLLERSHROUD)) && targetter->controller() != target) return false; -if (source && targetter && (targetter->controller() == targetter->controller()) && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller()->opponent() == target) return false; -if (source && targetter && (targetter->controller() == targetter->controller()) && (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller()== target) return false; - return (target->typeAsTarget() == TARGET_PLAYER) && (!p || p == (Player*)target); +bool PlayerTargetChooser::canTarget(Targetable * target) +{ + if (source && targetter && (targetter->controller() != targetter->controller()->opponent()) + && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::CONTROLLERSHROUD)) + && targetter->controller() != target) return false; + if (source && targetter && (targetter->controller() == targetter->controller()) + && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) + && targetter->controller()->opponent() == target) return false; + if (source && targetter && (targetter->controller() == targetter->controller()) + && (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller() + == target) return false; + return (target->typeAsTarget() == TARGET_PLAYER) && (!p || p == (Player*) target); } - PlayerTargetChooser* PlayerTargetChooser::clone() const{ - PlayerTargetChooser * a = NEW PlayerTargetChooser(*this); +PlayerTargetChooser* PlayerTargetChooser::clone() const +{ + PlayerTargetChooser * a = NEW PlayerTargetChooser(*this); return a; - } - +} /*Damageable Target */ -bool DamageableTargetChooser::canTarget(Targetable * target){ -if (source && targetter && (targetter->controller() != targetter->controller()->opponent()) && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::CONTROLLERSHROUD)) && targetter->controller() != target) return false; -if (source && targetter && (targetter->controller() == targetter->controller()) && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller()->opponent() == target) return false; -if (source && targetter && (targetter->controller() == targetter->controller()) && (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller()== target) return false; - if (target->typeAsTarget() == TARGET_PLAYER){ - return true; - } - return CreatureTargetChooser::canTarget(target); +bool DamageableTargetChooser::canTarget(Targetable * target) +{ + if (source && targetter && (targetter->controller() != targetter->controller()->opponent()) + && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::CONTROLLERSHROUD)) + && targetter->controller() != target) return false; + if (source && targetter && (targetter->controller() == targetter->controller()) + && (targetter->controller()->opponent()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) + && targetter->controller()->opponent() == target) return false; + if (source && targetter && (targetter->controller() == targetter->controller()) + && (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller() + == target) return false; + if (target->typeAsTarget() == TARGET_PLAYER) + { + return true; + } + return CreatureTargetChooser::canTarget(target); } - DamageableTargetChooser* DamageableTargetChooser::clone() const{ - DamageableTargetChooser * a = NEW DamageableTargetChooser(*this); +DamageableTargetChooser* DamageableTargetChooser::clone() const +{ + DamageableTargetChooser * a = NEW DamageableTargetChooser(*this); return a; - } +} /*Spell */ - - -SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card,int _color, int _maxtargets, bool other ):TargetChooser(card, _maxtargets, other){ - color = _color; +SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) : + TargetChooser(card, _maxtargets, other) +{ + color = _color; } -bool SpellTargetChooser::canTarget(Targetable * target){ - MTGCardInstance * card = NULL; - if (target->typeAsTarget() == TARGET_STACKACTION){ - Interruptible * action = (Interruptible *) target; - if (action->type == ACTION_SPELL && action->state==NOT_RESOLVED){ - Spell * spell = (Spell *) action; - card = spell->source; - if (card && (color == -1 || card->hasColor(color))) return true; +bool SpellTargetChooser::canTarget(Targetable * target) +{ + MTGCardInstance * card = NULL; + if (target->typeAsTarget() == TARGET_STACKACTION) + { + Interruptible * action = (Interruptible *) target; + if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) + { + Spell * spell = (Spell *) action; + card = spell->source; + if (card && (color == -1 || card->hasColor(color))) return true; + } } - } - return false; + return false; } - SpellTargetChooser* SpellTargetChooser::clone() const{ - SpellTargetChooser * a = NEW SpellTargetChooser(*this); +SpellTargetChooser* SpellTargetChooser::clone() const +{ + SpellTargetChooser * a = NEW SpellTargetChooser(*this); return a; - } +} /*Spell or Permanent */ -SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card,int _color, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ - int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; - init(default_zones,2); - color = _color; +SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) : + TargetZoneChooser(card, _maxtargets, other) +{ + int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD }; + init(default_zones, 2); + color = _color; } -bool SpellOrPermanentTargetChooser::canTarget(Targetable * target){ - MTGCardInstance * card = NULL; - if (target->typeAsTarget() == TARGET_CARD){ - card = (MTGCardInstance *) target; - if (color == -1 || card->hasColor(color)) return TargetZoneChooser::canTarget(target); - }else if (target->typeAsTarget() == TARGET_STACKACTION){ - Interruptible * action = (Interruptible *) target; - if (action->type == ACTION_SPELL && action->state==NOT_RESOLVED){ - Spell * spell = (Spell *) action; - card = spell->source; - if (card && (color == -1 || card->hasColor(color))) return true; +bool SpellOrPermanentTargetChooser::canTarget(Targetable * target) +{ + MTGCardInstance * card = NULL; + if (target->typeAsTarget() == TARGET_CARD) + { + card = (MTGCardInstance *) target; + if (color == -1 || card->hasColor(color)) return TargetZoneChooser::canTarget(target); } - } - return false; + else if (target->typeAsTarget() == TARGET_STACKACTION) + { + Interruptible * action = (Interruptible *) target; + if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) + { + Spell * spell = (Spell *) action; + card = spell->source; + if (card && (color == -1 || card->hasColor(color))) return true; + } + } + return false; } - SpellOrPermanentTargetChooser* SpellOrPermanentTargetChooser::clone() const{ - SpellOrPermanentTargetChooser * a = NEW SpellOrPermanentTargetChooser(*this); +SpellOrPermanentTargetChooser* SpellOrPermanentTargetChooser::clone() const +{ + SpellOrPermanentTargetChooser * a = NEW SpellOrPermanentTargetChooser(*this); return a; - } +} /*Damage */ -DamageTargetChooser::DamageTargetChooser(MTGCardInstance * card,int _color, int _maxtargets, int _state):TargetChooser(card, _maxtargets){ - color = _color; - state = _state; +DamageTargetChooser::DamageTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, int _state) : + TargetChooser(card, _maxtargets) +{ + color = _color; + state = _state; } -bool DamageTargetChooser::canTarget(Targetable * target){ - MTGCardInstance * card = NULL; - if (target->typeAsTarget() == TARGET_STACKACTION){ - Interruptible * action = (Interruptible *) target; - if (action->type == ACTION_DAMAGE && (action->state == state || state == -1)){ - Damage * damage = (Damage *) action; - card = damage->source; - if (card && (color == -1 || card->hasColor(color))) return true; +bool DamageTargetChooser::canTarget(Targetable * target) +{ + MTGCardInstance * card = NULL; + if (target->typeAsTarget() == TARGET_STACKACTION) + { + Interruptible * action = (Interruptible *) target; + if (action->type == ACTION_DAMAGE && (action->state == state || state == -1)) + { + Damage * damage = (Damage *) action; + card = damage->source; + if (card && (color == -1 || card->hasColor(color))) return true; + } } - } - return false; + return false; } - DamageTargetChooser* DamageTargetChooser::clone() const{ - DamageTargetChooser * a = NEW DamageTargetChooser(*this); +DamageTargetChooser* DamageTargetChooser::clone() const +{ + DamageTargetChooser * a = NEW DamageTargetChooser(*this); return a; - } +} - TriggerTargetChooser::TriggerTargetChooser(int _triggerTarget){ - triggerTarget = _triggerTarget; - target = NULL; - } +TriggerTargetChooser::TriggerTargetChooser(int _triggerTarget) +{ + triggerTarget = _triggerTarget; + target = NULL; +} - bool TriggerTargetChooser::targetsZone(MTGGameZone * z){ - return true; - } +bool TriggerTargetChooser::targetsZone(MTGGameZone * z) +{ + return true; +} - bool TriggerTargetChooser::canTarget(Targetable * _target){ - if (_target == target) return true; - return false; - } +bool TriggerTargetChooser::canTarget(Targetable * _target) +{ + if (_target == target) return true; + return false; +} - TriggerTargetChooser * TriggerTargetChooser::clone() const{ - TriggerTargetChooser * a = NEW TriggerTargetChooser(*this); - return a; - } +TriggerTargetChooser * TriggerTargetChooser::clone() const +{ + TriggerTargetChooser * a = NEW TriggerTargetChooser(*this); + return a; +} diff --git a/projects/mtg/src/TargetsList.cpp b/projects/mtg/src/TargetsList.cpp index 63c87b1e6..b51abe531 100644 --- a/projects/mtg/src/TargetsList.cpp +++ b/projects/mtg/src/TargetsList.cpp @@ -6,125 +6,156 @@ #include "Damage.h" #include "ActionStack.h" -TargetsList::TargetsList(){ - cursor = 0; +TargetsList::TargetsList() +{ + cursor = 0; } -TargetsList::TargetsList(Targetable * _targets[], int nbtargets){ - for (int i = 0; i < nbtargets; i++){ - targets[i] = _targets[i]; - } - cursor = nbtargets; -} - -int TargetsList::addTarget(Targetable * target){ - if (!alreadyHasTarget(target)){ - targets[cursor] = target; - cursor++; - return 1; - } - return 0; - -} - - -int TargetsList::alreadyHasTarget(Targetable * target){ - for (int i=0; itypeAsTarget() == type)){ - return (targets[i]); +int TargetsList::addTarget(Targetable * target) +{ + if (!alreadyHasTarget(target)) + { + targets[cursor] = target; + cursor++; + return 1; } - if (targets[i] == previous) found = 1; - } - return NULL; + return 0; + } -MTGCardInstance * TargetsList::getNextCardTarget(MTGCardInstance * previous){ - return ((MTGCardInstance *)getNextTarget(previous, TARGET_CARD)); -} - - -Player * TargetsList::getNextPlayerTarget(Player * previous){ - return ((Player *)getNextTarget(previous, TARGET_PLAYER)); -} - - -Interruptible * TargetsList::getNextInterruptible(Interruptible * previous, int type){ - int found = 0; - if (!previous) found = 1; - for (int i = 0; i < cursor; i++){ - if (found && targets[i]->typeAsTarget() == TARGET_STACKACTION){ - Interruptible * action = (Interruptible *) targets[i]; - if (action->type==type){ - return action; - } +int TargetsList::alreadyHasTarget(Targetable * target) +{ + for (int i = 0; i < cursor; i++) + { + if (targets[i] == target) return 1; } - if (targets[i] == previous) found = 1; - } - return NULL; + return 0; } -Spell * TargetsList::getNextSpellTarget(Spell * previous){ - Spell * spell = (Spell *) getNextInterruptible(previous, ACTION_SPELL); - return spell; +int TargetsList::removeTarget(Targetable * target) +{ + for (int i = 0; i < cursor; i++) + { + if (targets[i] == target) + { + targets[i] = targets[cursor]; + targets[cursor] = NULL; + cursor--; + } + } + + return 0; +} + +int TargetsList::toggleTarget(Targetable * target) +{ + if (alreadyHasTarget(target)) + { + + return removeTarget(target); + } + else + { + + return addTarget(target); + } +} + +Targetable * TargetsList::getNextTarget(Targetable * previous, int type) +{ + int found = 0; + if (!previous) found = 1; + for (int i = 0; i < cursor; i++) + { + if (found && (type == -1 || targets[i]->typeAsTarget() == type)) + { + return (targets[i]); + } + if (targets[i] == previous) found = 1; + } + return NULL; +} + +MTGCardInstance * TargetsList::getNextCardTarget(MTGCardInstance * previous) +{ + return ((MTGCardInstance *) getNextTarget(previous, TARGET_CARD)); +} + +Player * TargetsList::getNextPlayerTarget(Player * previous) +{ + return ((Player *) getNextTarget(previous, TARGET_PLAYER)); +} + +Interruptible * TargetsList::getNextInterruptible(Interruptible * previous, int type) +{ + int found = 0; + if (!previous) found = 1; + for (int i = 0; i < cursor; i++) + { + if (found && targets[i]->typeAsTarget() == TARGET_STACKACTION) + { + Interruptible * action = (Interruptible *) targets[i]; + if (action->type == type) + { + return action; + } + } + if (targets[i] == previous) found = 1; + } + return NULL; +} + +Spell * TargetsList::getNextSpellTarget(Spell * previous) +{ + Spell * spell = (Spell *) getNextInterruptible(previous, ACTION_SPELL); + return spell; } //How about DAMAGESTacks ?? -Damage * TargetsList::getNextDamageTarget(Damage * previous){ - Damage * damage = (Damage * ) getNextInterruptible(previous, ACTION_DAMAGE); - return damage; +Damage * TargetsList::getNextDamageTarget(Damage * previous) +{ + Damage * damage = (Damage *) getNextInterruptible(previous, ACTION_DAMAGE); + return damage; } -Damageable * TargetsList::getNextDamageableTarget(Damageable * previous){ - int found = 0; - if (!previous) found = 1; - for (int i = 0; i < cursor; i++){ +Damageable * TargetsList::getNextDamageableTarget(Damageable * previous) +{ + int found = 0; + if (!previous) found = 1; + for (int i = 0; i < cursor; i++) + { - if (targets[i]->typeAsTarget() == TARGET_PLAYER){ - if (found){ - return ((Player *) targets[i]); - }else{ - if ((Player *)targets[i] == previous) found = 1; - } - }else if(targets[i]->typeAsTarget() == TARGET_CARD){ - if (found){ - return ((MTGCardInstance *) targets[i]); - }else{ - if ((MTGCardInstance *)targets[i] == previous) found = 1; - } + if (targets[i]->typeAsTarget() == TARGET_PLAYER) + { + if (found) + { + return ((Player *) targets[i]); + } + else + { + if ((Player *) targets[i] == previous) found = 1; + } + } + else if (targets[i]->typeAsTarget() == TARGET_CARD) + { + if (found) + { + return ((MTGCardInstance *) targets[i]); + } + else + { + if ((MTGCardInstance *) targets[i] == previous) found = 1; + } + } } - } - return NULL; + return NULL; } diff --git a/projects/mtg/src/Tasks.cpp b/projects/mtg/src/Tasks.cpp index 46ff4c66f..a6e5b7f68 100644 --- a/projects/mtg/src/Tasks.cpp +++ b/projects/mtg/src/Tasks.cpp @@ -15,513 +15,607 @@ vector Task::AIDeckNames; // TODO: Move to dedicated file //!! Copypaste from GameStateDeckViewer.cpp StringExplode. Move and #include here and there -void ExplodeStr(string str, string separator, vector* results){ +void ExplodeStr(string str, string separator, vector* results) +{ int found; results->clear(); found = str.find_first_of(separator); - while(found != (int)string::npos){ - if(found > 0){ - results->push_back(str.substr(0,found)); - } else { - results->push_back(" "); + while (found != (int) string::npos) + { + if (found > 0) + { + results->push_back(str.substr(0, found)); } - str = str.substr(found+1); + else + { + results->push_back(" "); + } + str = str.substr(found + 1); found = str.find_first_of(separator); } - if(str.length() > 0){ + if (str.length() > 0) + { results->push_back(str); } } -string ImplodeStr(string separator, vector strs){ - string result = ""; - for (vector::iterator it = strs.begin(); it!=strs.end(); it++){ - result += (it == strs.begin()?"":separator) + (*it); - } - return result; +string ImplodeStr(string separator, vector strs) +{ + string result = ""; + for (vector::iterator it = strs.begin(); it != strs.end(); it++) + { + result += (it == strs.begin() ? "" : separator) + (*it); + } + return result; } /*---------------- Task -----------------*/ -Task::Task(char _type) { - reward = 0; - expiresIn = 1; - accepted = FALSE; - if (_type == ' ') { - type = TASK_BASIC; - } else { - type = _type; - } +Task::Task(char _type) +{ + reward = 0; + expiresIn = 1; + accepted = FALSE; + if (_type == ' ') + { + type = TASK_BASIC; + } + else + { + type = _type; + } } -int Task::getReward() { - if (reward == 0) { - reward = computeReward(); - } +int Task::getReward() +{ + if (reward == 0) + { + reward = computeReward(); + } - return reward; + return reward; } -string Task::toString() { - storeCommonAttribs(); - storeCustomAttribs(); - return ImplodeStr(ITEM_SEPARATOR, persistentAttribs); +string Task::toString() +{ + storeCommonAttribs(); + storeCustomAttribs(); + return ImplodeStr(ITEM_SEPARATOR, persistentAttribs); } // Store basic attributes to vector, for saving -void Task::storeCommonAttribs() { - char buff[256]; +void Task::storeCommonAttribs() +{ + char buff[256]; - persistentAttribs.clear(); - persistentAttribs.push_back(string(1, type)); + persistentAttribs.clear(); + persistentAttribs.push_back(string(1, type)); - sprintf(buff, "%i", expiresIn); - persistentAttribs.push_back(string(buff)); + sprintf(buff, "%i", expiresIn); + persistentAttribs.push_back(string(buff)); - sprintf(buff, "%i", accepted?1:0); - persistentAttribs.push_back(string(buff)); + sprintf(buff, "%i", accepted ? 1 : 0); + persistentAttribs.push_back(string(buff)); - sprintf(buff, "%i", opponent); - persistentAttribs.push_back(string(buff)); + sprintf(buff, "%i", opponent); + persistentAttribs.push_back(string(buff)); - sprintf(buff, "%i", reward); - persistentAttribs.push_back(string(buff)); + sprintf(buff, "%i", reward); + persistentAttribs.push_back(string(buff)); - persistentAttribs.push_back(getDesc()); + persistentAttribs.push_back(getDesc()); - persistentAttribs.push_back(getOpponentName()); + persistentAttribs.push_back(getOpponentName()); } -int Task::restoreCommonAttribs() { - if (persistentAttribs.size() < COMMON_ATTRIBS_COUNT) { - #if defined (WIN32) || defined (LINUX) - DebugTrace("\nTasks.cpp::restoreCommonAttribs: Not enough attributes loaded\n"); - #endif - - return -1; - } - expiresIn = atoi(persistentAttribs[1].c_str()); - accepted = (persistentAttribs[2].compare("1") == 0); - opponent = atoi(persistentAttribs[3].c_str()); - reward = atoi(persistentAttribs[4].c_str()); - description = persistentAttribs[5]; - opponentName = persistentAttribs[6]; - return 1; +int Task::restoreCommonAttribs() +{ + if (persistentAttribs.size() < COMMON_ATTRIBS_COUNT) + { +#if defined (WIN32) || defined (LINUX) + DebugTrace("\nTasks.cpp::restoreCommonAttribs: Not enough attributes loaded\n"); +#endif + + return -1; + } + expiresIn = atoi(persistentAttribs[1].c_str()); + accepted = (persistentAttribs[2].compare("1") == 0); + opponent = atoi(persistentAttribs[3].c_str()); + reward = atoi(persistentAttribs[4].c_str()); + description = persistentAttribs[5]; + opponentName = persistentAttribs[6]; + return 1; } -void Task::storeCustomAttribs() { - // To be extended in child class +void Task::storeCustomAttribs() +{ + // To be extended in child class } -void Task::restoreCustomAttribs() { - // To be extended in child class +void Task::restoreCustomAttribs() +{ + // To be extended in child class } -string Task::getOpponentName() { - if (opponentName == "") { - opponentName = Task::getAIDeckName(opponent); - } - - return opponentName; +string Task::getOpponentName() +{ + if (opponentName == "") + { + opponentName = Task::getAIDeckName(opponent); + } + + return opponentName; } -string Task::getDesc() { - return (description == "") ? (description = createDesc()) : description; +string Task::getDesc() +{ + return (description == "") ? (description = createDesc()) : description; } -void Task::randomize() { - opponent = rand() % getAIDeckCount() + 1; - opponentName = ""; - setExpiration((rand()%3)+1); - reward = computeReward(); +void Task::randomize() +{ + opponent = rand() % getAIDeckCount() + 1; + opponentName = ""; + setExpiration((rand() % 3) + 1); + reward = computeReward(); } -bool Task::isExpired() { - return (expiresIn <= 0); +bool Task::isExpired() +{ + return (expiresIn <= 0); } -int Task::getExpiration() { - return expiresIn; +int Task::getExpiration() +{ + return expiresIn; } -void Task::setExpiration(int _expiresIn) { - expiresIn = _expiresIn; +void Task::setExpiration(int _expiresIn) +{ + expiresIn = _expiresIn; } -void Task::passOneDay() { - expiresIn--; - reward = (int) (getReward() * 0.9); // Todo: degradation and minreward constants - if (reward < 33) { - reward = 33; - } +void Task::passOneDay() +{ + expiresIn--; + reward = (int) (getReward() * 0.9); // Todo: degradation and minreward constants + if (reward < 33) + { + reward = 33; + } } - // AI deck buffering code -void Task::loadAIDeckNames() { - int found = 1; - int nbDecks = 0; - while (found){ - found = 0; - char buffer[512]; - sprintf(buffer, "%s/deck%i.txt",JGE_GET_RES("ai/baka").c_str(),nbDecks + 1); +void Task::loadAIDeckNames() +{ + int found = 1; + int nbDecks = 0; + while (found) + { + found = 0; + char buffer[512]; + sprintf(buffer, "%s/deck%i.txt", JGE_GET_RES("ai/baka").c_str(), nbDecks + 1); - if(fileExists(buffer)){ - found = 1; - nbDecks++; - // TODO: Creating MTGDeck only for getting decks name. Find an easier way. - MTGDeck * mtgd = NEW MTGDeck(buffer,NULL,1); - AIDeckNames.push_back(mtgd->meta_name); - delete mtgd; + if (fileExists(buffer)) + { + found = 1; + nbDecks++; + // TODO: Creating MTGDeck only for getting decks name. Find an easier way. + MTGDeck * mtgd = NEW MTGDeck(buffer, NULL, 1); + AIDeckNames.push_back(mtgd->meta_name); + delete mtgd; + } } - } } -int Task::getAIDeckCount() { - if (AIDeckNames.size() == 0) { - loadAIDeckNames(); - } - return AIDeckNames.size(); +int Task::getAIDeckCount() +{ + if (AIDeckNames.size() == 0) + { + loadAIDeckNames(); + } + return AIDeckNames.size(); } -string Task::getAIDeckName(int id) { - if (AIDeckNames.size() == 0) { - loadAIDeckNames(); - } - return ((unsigned int)id <= AIDeckNames.size()) ? AIDeckNames.at(id-1) : ""; +string Task::getAIDeckName(int id) +{ + if (AIDeckNames.size() == 0) + { + loadAIDeckNames(); + } + return ((unsigned int) id <= AIDeckNames.size()) ? AIDeckNames.at(id - 1) : ""; } // End of AI deck buffering code // Each child class has to be added to the switch in this function (clumsy..) -Task* Task::createFromStr(string params, bool rand) { - vector exploded; - Task *result; +Task* Task::createFromStr(string params, bool rand) +{ + vector exploded; + Task *result; - ExplodeStr(params, ITEM_SEPARATOR, &exploded); + ExplodeStr(params, ITEM_SEPARATOR, &exploded); - switch (exploded[0][0]) { + switch (exploded[0][0]) + { case TASK_WIN_AGAINST: - result = NEW TaskWinAgainst(); - break; + result = NEW TaskWinAgainst(); + break; case TASK_SLAUGHTER: - result = NEW TaskSlaughter(); - break; + result = NEW TaskSlaughter(); + break; case TASK_DELAY: - result = NEW TaskDelay(); - break; + result = NEW TaskDelay(); + break; case TASK_IMMORTAL: - result = NEW TaskImmortal(); - break; + result = NEW TaskImmortal(); + break; case TASK_MASSIVE_BURIAL: - result = NEW TaskMassiveBurial(); - break; + result = NEW TaskMassiveBurial(); + break; case TASK_WISDOM: - result = NEW TaskWisdom(); - break; + result = NEW TaskWisdom(); + break; case TASK_PACIFISM: - result = NEW TaskPacifism(); - break; + result = NEW TaskPacifism(); + break; default: - #if defined (WIN32) || defined (LINUX) +#if defined (WIN32) || defined (LINUX) DebugTrace("\nTasks.cpp::createFromStr: Undefined class type\n"); - #endif - result = NEW TaskWinAgainst(); - } - - if (!result) { - #if defined (WIN32) || defined (LINUX) - DebugTrace("\nTask::createFromStr: Failed to create task\n"); - #endif - return NULL; - } - - result->persistentAttribs = exploded; - - if (exploded.size() >= COMMON_ATTRIBS_COUNT) { - result->restoreCommonAttribs(); - if (exploded.size() > COMMON_ATTRIBS_COUNT) { - result->restoreCustomAttribs(); +#endif + result = NEW TaskWinAgainst(); } - } else if (rand) { - result->randomize(); - } - return result; + if (!result) + { +#if defined (WIN32) || defined (LINUX) + DebugTrace("\nTask::createFromStr: Failed to create task\n"); +#endif + return NULL; + } + + result->persistentAttribs = exploded; + + if (exploded.size() >= COMMON_ATTRIBS_COUNT) + { + result->restoreCommonAttribs(); + if (exploded.size() > COMMON_ATTRIBS_COUNT) + { + result->restoreCustomAttribs(); + } + } + else if (rand) + { + result->randomize(); + } + + return result; } /*---------------- TaskList -----------------*/ -TaskList::TaskList(string _fileName) { - fileName = _fileName; - if (fileName == "") { - fileName = options.profileFile(PLAYER_TASKS).c_str(); - } - load(fileName); - for(int i=0;i<9;i++) +TaskList::TaskList(string _fileName) +{ + fileName = _fileName; + if (fileName == "") + { + fileName = options.profileFile(PLAYER_TASKS).c_str(); + } + load(fileName); + for (int i = 0; i < 9; i++) mBg[i] = NULL; - mBgTex = NULL; //We only load the background if we use the task screen. + mBgTex = NULL; //We only load the background if we use the task screen. } -int TaskList::save(string _fileName) { - if (_fileName != "") { - fileName = _fileName; - } - if (fileName == "") { - #if defined (WIN32) || defined (LINUX) - DebugTrace("\nTaskList::save: No filename specified\n"); - #endif - return -1; - } +int TaskList::save(string _fileName) +{ + if (_fileName != "") + { + fileName = _fileName; + } + if (fileName == "") + { +#if defined (WIN32) || defined (LINUX) + DebugTrace("\nTaskList::save: No filename specified\n"); +#endif + return -1; + } - std::ofstream file(fileName.c_str()); - if (file){ - #if defined (WIN32) || defined (LINUX) + std::ofstream file(fileName.c_str()); + if (file) + { +#if defined (WIN32) || defined (LINUX) DebugTrace("\nsaving tasks\n"); - #endif - - file << "# Format: |||||[|Additional attributes]\n"; +#endif - for (vector::iterator it = tasks.begin(); it!=tasks.end(); it++){ - file << (*it)->toString() << "\n"; + file << "# Format: |||||[|Additional attributes]\n"; + + for (vector::iterator it = tasks.begin(); it != tasks.end(); it++) + { + file << (*it)->toString() << "\n"; + } + file.close(); } - file.close(); - } - return 1; + return 1; } -int TaskList::load(string _fileName) { - Task *task; - if (_fileName != "") { - fileName = _fileName; - } - if (fileName == "") { - #if defined (WIN32) || defined (LINUX) - DebugTrace("\nTaskList::load: No filename specified\n"); - #endif - return -1; - } - - std::ifstream file(fileName.c_str()); - std::string s; - - if (file) { - while(std::getline(file,s)) { - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - if (s[0] == '#') { - continue; - } - - task = Task::createFromStr(s); - if (task) { - this->addTask(task); - } else { - #if defined (WIN32) || defined (LINUX) - DebugTrace("\nTaskList::load: error creating task\n"); - #endif - } +int TaskList::load(string _fileName) +{ + Task *task; + if (_fileName != "") + { + fileName = _fileName; } - file.close(); - } else { - #if defined (WIN32) || defined (LINUX) - DebugTrace("\nTaskList::load: Failed to open file\n"); - #endif - return -1; - } - - return 1; -} - -void TaskList::addTask(Task *task) { - tasks.push_back(task); -} - -void TaskList::addTask(string params, bool rand) { - addTask(Task::createFromStr(params, rand)); -} - -void TaskList::removeTask(Task *task) { - vector::iterator it; - - it = find(tasks.begin(), tasks.end(), task); - - if (it != tasks.end()) { - SAFE_DELETE(*it); - tasks.erase(it); - } else { - // TODO: task not found handling. - } -} -void TaskList::Start(){ - vPos = -SCREEN_HEIGHT; //Offscreen - mElapsed = 0; - mState = TASKS_IN; - if(!mBgTex){ - mBgTex = resources.RetrieveTexture("taskboard.png", RETRIEVE_LOCK); - float unitH = static_cast(mBgTex->mHeight / 4); - float unitW = static_cast(mBgTex->mWidth / 4); - if(unitH == 0 || unitW == 0) return; - - for(int i=0;i<9;i++) - SAFE_DELETE(mBg[i]); - if(mBgTex){ - mBg[0] = NEW JQuad(mBgTex, 0, 0, unitW, unitH); - mBg[1] = NEW JQuad(mBgTex, unitW, 0, unitW*2, unitH); - mBg[2] = NEW JQuad(mBgTex, unitW*3, 0, unitW, unitH); - mBg[3] = NEW JQuad(mBgTex, 0, unitH, unitW, unitH*2); - mBg[4] = NEW JQuad(mBgTex, unitW, unitH, unitW*2, unitH*2); - mBg[5] = NEW JQuad(mBgTex, unitW*3, unitH, unitW, unitH*2); - mBg[6] = NEW JQuad(mBgTex, 0, unitH*3, unitW, unitH); - mBg[7] = NEW JQuad(mBgTex, unitW, unitH*3, unitW*2, unitH); - mBg[8] = NEW JQuad(mBgTex, unitW*3, unitH*3, unitW, unitH); + if (fileName == "") + { +#if defined (WIN32) || defined (LINUX) + DebugTrace("\nTaskList::load: No filename specified\n"); +#endif + return -1; } - - sH = 64 / unitH; - sW = 64 / unitW; - } -} -void TaskList::End(){ - mState = TASKS_OUT; - mElapsed = 0; -} -void TaskList::passOneDay() { - // TODO: "You have failed the task" message to the user when accepted task expires - for (vector::iterator it = tasks.begin(); it!=tasks.end(); ){ - (*it)->passOneDay(); - if ((*it)->isExpired()) { - SAFE_DELETE(*it); - it = tasks.erase(it); - } else { - it++; + + std::ifstream file(fileName.c_str()); + std::string s; + + if (file) + { + while (std::getline(file, s)) + { + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + if (s[0] == '#') + { + continue; + } + + task = Task::createFromStr(s); + if (task) + { + this->addTask(task); + } + else + { +#if defined (WIN32) || defined (LINUX) + DebugTrace("\nTaskList::load: error creating task\n"); +#endif + } + } + file.close(); } - } -} - -void TaskList::getDoneTasks(Player * _p1, Player * _p2, GameApp * _app, vector* result) { - result->clear(); - // TODO: Return only accepted tasks - for (vector::iterator it = tasks.begin(); it!=tasks.end(); it++) { - if ((*it)->isDone(_p1, _p2, _app)) { - result->push_back(*it); + else + { +#if defined (WIN32) || defined (LINUX) + DebugTrace("\nTaskList::load: Failed to open file\n"); +#endif + return -1; } - } + + return 1; } -int TaskList::getTaskCount() { - return tasks.size(); +void TaskList::addTask(Task *task) +{ + tasks.push_back(task); } -void TaskList::Update(float dt) { - mElapsed += dt; - - if(mState == TASKS_IN && vPos < 0){ - vPos = -SCREEN_HEIGHT+(SCREEN_HEIGHT*mElapsed/0.75f); //Todo: more physical drop-in. - if(vPos >= 0){ - vPos = 0; - mState = TaskList::TASKS_ACTIVE; + +void TaskList::addTask(string params, bool rand) +{ + addTask(Task::createFromStr(params, rand)); +} + +void TaskList::removeTask(Task *task) +{ + vector::iterator it; + + it = find(tasks.begin(), tasks.end(), task); + + if (it != tasks.end()) + { + SAFE_DELETE(*it); + tasks.erase(it); + } + else + { + // TODO: task not found handling. } - }else if(mState == TASKS_OUT && vPos > -SCREEN_HEIGHT){ - vPos = -(SCREEN_HEIGHT*mElapsed/0.75f); - if(vPos <= -SCREEN_HEIGHT) - mState = TASKS_INACTIVE; - } -} -void TaskList::Render() { - JRenderer * r = JRenderer::GetInstance(); - //Setup fonts. - WFont * f = resources.GetWFont(Fonts::MAIN_FONT); - WFont * f2 = resources.GetWFont(Fonts::MAGIC_FONT); - WFont * f3 = resources.GetWFont(Fonts::MENU_FONT); //OPTION_FONT - f2->SetColor(ARGB(255, 205, 237, 240)); - f3->SetColor(ARGB(255, 219, 206, 151)); - - //Render background board - if(mBgTex){ - r->FillRect(0,vPos,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(128,0,0,0)); - r->RenderQuad(mBg[0],0,vPos,0,sW,sH); //TL - r->RenderQuad(mBg[2],SCREEN_WIDTH-64,vPos,0,sW,sH); //TR - r->RenderQuad(mBg[6],0,vPos+SCREEN_HEIGHT-64,0,sW,sH); //BL - r->RenderQuad(mBg[8],SCREEN_WIDTH-64,vPos+SCREEN_HEIGHT-64,0,sW,sH); //BR - - //Stretch the sides - float stretchV = (144.0f/128.0f)*sH; - float stretchH = (176.0f/128.0f)*sW; - r->RenderQuad(mBg[3],0,vPos+64,0,sW,stretchV); //L - r->RenderQuad(mBg[5],SCREEN_WIDTH-64,vPos+64,0,sW,stretchV); //R - r->RenderQuad(mBg[1],64,vPos,0,stretchH,sH); //T1 - r->RenderQuad(mBg[1],240,vPos,0,stretchH,sH); //T1 - r->RenderQuad(mBg[7],64,vPos+208,0,stretchH,sH); //B1 - r->RenderQuad(mBg[7],240,vPos+208,0,stretchH,sH); //B1 - r->RenderQuad(mBg[4],64,vPos+64,0,stretchH,stretchV); //Center1 - r->RenderQuad(mBg[4],240,vPos+64,0,stretchH,stretchV); //Center2 - - f2->SetColor(ARGB(255, 55, 46, 34)); - f=f2; - }else{ - r->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(128,0,0,0)); - r->FillRect(10,10+vPos,SCREEN_WIDTH-10,SCREEN_HEIGHT-10,ARGB(128,0,0,0)); - } - - - - float posX = 40, posY = vPos+20; - char buffer[300]; - string title = _("Task Board"); - - f3->DrawString(title.c_str(), static_cast((SCREEN_WIDTH-20)/2 - title.length()*4), posY); - posY += 30; - - if (0 == tasks.size()) { - f->DrawString(_("There are no tasks that need to be done. Come again tomorrow.").c_str(), posX, posY); - posY += 20; - return; - } - - for (vector::iterator it = tasks.begin(); it!=tasks.end(); it++) { - sprintf(buffer, "%s", (*it)->getShortDesc().c_str()); - f2->DrawString(buffer, posX, posY); - if(mBgTex){ - f->SetScale(.8f); - } - sprintf(buffer, _("Days left: %i").c_str(), (*it)->getExpiration()); - f->DrawString(buffer, SCREEN_WIDTH - 190, posY); - sprintf(buffer, _("Reward: %i").c_str(), (*it)->getReward()); - f->DrawString(buffer, SCREEN_WIDTH - 100, posY); - posY += 15; - - sprintf(buffer, "%s", (*it)->getDesc().c_str()); - f->DrawString(buffer, posX+10, posY); - posY += 15; - if(mBgTex){ - f->SetScale(1); - } - //r->DrawLine((SCREEN_WIDTH)/2 - 200, posY, (SCREEN_WIDTH)/2 + 200, posY, ARGB(128, 255, 255, 255)); - } - f->SetScale(1); } -void TaskList::addRandomTask(int diff) { - // TODO: Weighted random (rarity of tasks) - // - based on counts of finished tasks? - // Winning a task several times may slightly lessen the probability of it being generated - string s (TASKS_ALL); - char taskType[2]; - sprintf(taskType, "%c", s[rand()%s.length()]); - addTask(string(taskType), TRUE); +void TaskList::Start() +{ + vPos = -SCREEN_HEIGHT; //Offscreen + mElapsed = 0; + mState = TASKS_IN; + if (!mBgTex) + { + mBgTex = resources.RetrieveTexture("taskboard.png", RETRIEVE_LOCK); + float unitH = static_cast (mBgTex->mHeight / 4); + float unitW = static_cast (mBgTex->mWidth / 4); + if (unitH == 0 || unitW == 0) return; + + for (int i = 0; i < 9; i++) + SAFE_DELETE(mBg[i]); + if (mBgTex) + { + mBg[0] = NEW JQuad(mBgTex, 0, 0, unitW, unitH); + mBg[1] = NEW JQuad(mBgTex, unitW, 0, unitW * 2, unitH); + mBg[2] = NEW JQuad(mBgTex, unitW * 3, 0, unitW, unitH); + mBg[3] = NEW JQuad(mBgTex, 0, unitH, unitW, unitH * 2); + mBg[4] = NEW JQuad(mBgTex, unitW, unitH, unitW * 2, unitH * 2); + mBg[5] = NEW JQuad(mBgTex, unitW * 3, unitH, unitW, unitH * 2); + mBg[6] = NEW JQuad(mBgTex, 0, unitH * 3, unitW, unitH); + mBg[7] = NEW JQuad(mBgTex, unitW, unitH * 3, unitW * 2, unitH); + mBg[8] = NEW JQuad(mBgTex, unitW * 3, unitH * 3, unitW, unitH); + } + + sH = 64 / unitH; + sW = 64 / unitW; + } +} +void TaskList::End() +{ + mState = TASKS_OUT; + mElapsed = 0; } +void TaskList::passOneDay() +{ + // TODO: "You have failed the task" message to the user when accepted task expires + for (vector::iterator it = tasks.begin(); it != tasks.end();) + { + (*it)->passOneDay(); + if ((*it)->isExpired()) + { + SAFE_DELETE(*it); + it = tasks.erase(it); + } + else + { + it++; + } + } +} -TaskList::~TaskList() { +void TaskList::getDoneTasks(Player * _p1, Player * _p2, GameApp * _app, vector* result) +{ + result->clear(); + // TODO: Return only accepted tasks + for (vector::iterator it = tasks.begin(); it != tasks.end(); it++) + { + if ((*it)->isDone(_p1, _p2, _app)) + { + result->push_back(*it); + } + } +} - for (unsigned int i=0; i= 0) + { + vPos = 0; + mState = TaskList::TASKS_ACTIVE; + } + } + else if (mState == TASKS_OUT && vPos > -SCREEN_HEIGHT) + { + vPos = -(SCREEN_HEIGHT * mElapsed / 0.75f); + if (vPos <= -SCREEN_HEIGHT) mState = TASKS_INACTIVE; + } +} + +void TaskList::Render() +{ + JRenderer * r = JRenderer::GetInstance(); + //Setup fonts. + WFont * f = resources.GetWFont(Fonts::MAIN_FONT); + WFont * f2 = resources.GetWFont(Fonts::MAGIC_FONT); + WFont * f3 = resources.GetWFont(Fonts::MENU_FONT); //OPTION_FONT + f2->SetColor(ARGB(255, 205, 237, 240)); + f3->SetColor(ARGB(255, 219, 206, 151)); + + //Render background board + if (mBgTex) + { + r->FillRect(0, vPos, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(128,0,0,0)); + r->RenderQuad(mBg[0], 0, vPos, 0, sW, sH); //TL + r->RenderQuad(mBg[2], SCREEN_WIDTH - 64, vPos, 0, sW, sH); //TR + r->RenderQuad(mBg[6], 0, vPos + SCREEN_HEIGHT - 64, 0, sW, sH); //BL + r->RenderQuad(mBg[8], SCREEN_WIDTH - 64, vPos + SCREEN_HEIGHT - 64, 0, sW, sH); //BR + + //Stretch the sides + float stretchV = (144.0f / 128.0f) * sH; + float stretchH = (176.0f / 128.0f) * sW; + r->RenderQuad(mBg[3], 0, vPos + 64, 0, sW, stretchV); //L + r->RenderQuad(mBg[5], SCREEN_WIDTH - 64, vPos + 64, 0, sW, stretchV); //R + r->RenderQuad(mBg[1], 64, vPos, 0, stretchH, sH); //T1 + r->RenderQuad(mBg[1], 240, vPos, 0, stretchH, sH); //T1 + r->RenderQuad(mBg[7], 64, vPos + 208, 0, stretchH, sH); //B1 + r->RenderQuad(mBg[7], 240, vPos + 208, 0, stretchH, sH); //B1 + r->RenderQuad(mBg[4], 64, vPos + 64, 0, stretchH, stretchV); //Center1 + r->RenderQuad(mBg[4], 240, vPos + 64, 0, stretchH, stretchV); //Center2 + + f2->SetColor(ARGB(255, 55, 46, 34)); + f = f2; + } + else + { + r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(128,0,0,0)); + r->FillRect(10, 10 + vPos, SCREEN_WIDTH - 10, SCREEN_HEIGHT - 10, ARGB(128,0,0,0)); + } + + float posX = 40, posY = vPos + 20; + char buffer[300]; + string title = _("Task Board"); + + f3->DrawString(title.c_str(), static_cast ((SCREEN_WIDTH - 20) / 2 - title.length() * 4), posY); + posY += 30; + + if (0 == tasks.size()) + { + f->DrawString(_("There are no tasks that need to be done. Come again tomorrow.").c_str(), posX, posY); + posY += 20; + return; + } + + for (vector::iterator it = tasks.begin(); it != tasks.end(); it++) + { + sprintf(buffer, "%s", (*it)->getShortDesc().c_str()); + f2->DrawString(buffer, posX, posY); + if (mBgTex) + { + f->SetScale(.8f); + } + sprintf(buffer, _("Days left: %i").c_str(), (*it)->getExpiration()); + f->DrawString(buffer, SCREEN_WIDTH - 190, posY); + sprintf(buffer, _("Reward: %i").c_str(), (*it)->getReward()); + f->DrawString(buffer, SCREEN_WIDTH - 100, posY); + posY += 15; + + sprintf(buffer, "%s", (*it)->getDesc().c_str()); + f->DrawString(buffer, posX + 10, posY); + posY += 15; + if (mBgTex) + { + f->SetScale(1); + } + //r->DrawLine((SCREEN_WIDTH)/2 - 200, posY, (SCREEN_WIDTH)/2 + 200, posY, ARGB(128, 255, 255, 255)); + } + f->SetScale(1); +} + +void TaskList::addRandomTask(int diff) +{ + // TODO: Weighted random (rarity of tasks) + // - based on counts of finished tasks? + // Winning a task several times may slightly lessen the probability of it being generated + string s(TASKS_ALL); + char taskType[2]; + sprintf(taskType, "%c", s[rand() % s.length()]); + addTask(string(taskType), TRUE); +} + +TaskList::~TaskList() +{ + + for (unsigned int i = 0; i < tasks.size(); i++) + { + SAFE_DELETE(tasks[i]); + } + if (mBgTex) resources.Release(mBgTex); + for (int i = 0; i < 9; i++) + SAFE_DELETE(mBg[i]); } /*----------------------------------------*/ @@ -530,525 +624,608 @@ TaskList::~TaskList() { /*----------- TaskWinAgainst -------------*/ -TaskWinAgainst::TaskWinAgainst(int _opponent) : Task(TASK_WIN_AGAINST) { - opponent = _opponent; +TaskWinAgainst::TaskWinAgainst(int _opponent) : + Task(TASK_WIN_AGAINST) +{ + opponent = _opponent; } -int TaskWinAgainst::computeReward() { - return 75 + rand() % 75; +int TaskWinAgainst::computeReward() +{ + return 75 + rand() % 75; } -string TaskWinAgainst::createDesc() { - char buffer[4096]; - switch (rand()%2) { +string TaskWinAgainst::createDesc() +{ + char buffer[4096]; + switch (rand() % 2) + { case 0: - sprintf(buffer, _("You have to defeat %s before it causes too much harm.").c_str(), getOpponentName().c_str()); - break; + sprintf(buffer, _("You have to defeat %s before it causes too much harm.").c_str(), getOpponentName().c_str()); + break; case 1: - sprintf(buffer, _("Please defeat %s as soon as possible.").c_str(), getOpponentName().c_str()); - break; - } - return buffer; + sprintf(buffer, _("Please defeat %s as soon as possible.").c_str(), getOpponentName().c_str()); + break; + } + return buffer; } -string TaskWinAgainst::getShortDesc() { - char buffer[4096]; - string result; - - sprintf(buffer, _("Defeat %s").c_str(), getOpponentName().c_str()); - result = buffer; - - return result; +string TaskWinAgainst::getShortDesc() +{ + char buffer[4096]; + string result; + + sprintf(buffer, _("Defeat %s").c_str(), getOpponentName().c_str()); + result = buffer; + + return result; } -bool TaskWinAgainst::isDone(Player * _p1, Player * _p2, GameApp * _app) { - GameObserver * g = GameObserver::GetInstance(); - AIPlayerBaka * baka = (AIPlayerBaka*)_p2; - return ( - (baka) - && (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins - && (baka->deckId == opponent) - ); +bool TaskWinAgainst::isDone(Player * _p1, Player * _p2, GameApp * _app) +{ + GameObserver * g = GameObserver::GetInstance(); + AIPlayerBaka * baka = (AIPlayerBaka*) _p2; + return ((baka) && (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins + && (baka->deckId == opponent)); } /*----------- TaskSlaughter -------------*/ -TaskSlaughter::TaskSlaughter(int _opponent, int _targetLife) : TaskWinAgainst(_opponent) { - type = TASK_SLAUGHTER; - targetLife = _targetLife; +TaskSlaughter::TaskSlaughter(int _opponent, int _targetLife) : + TaskWinAgainst(_opponent) +{ + type = TASK_SLAUGHTER; + targetLife = _targetLife; } -int TaskSlaughter::computeReward() { - return 2*TaskWinAgainst::computeReward() - 9*targetLife*(targetLife<-50 ? 2 : 1); +int TaskSlaughter::computeReward() +{ + return 2 * TaskWinAgainst::computeReward() - 9 * targetLife * (targetLife < -50 ? 2 : 1); } -void TaskSlaughter::randomize() { - targetLife = -15 - rand()%10; - if (!(rand()%7)) { - targetLife *= 5; - } - Task::randomize(); +void TaskSlaughter::randomize() +{ + targetLife = -15 - rand() % 10; + if (!(rand() % 7)) + { + targetLife *= 5; + } + Task::randomize(); } -string TaskSlaughter::createDesc() { - char buffer[4096]; - switch (rand()%2) { +string TaskSlaughter::createDesc() +{ + char buffer[4096]; + switch (rand() % 2) + { case 0: - sprintf(buffer, _("Defeat %s in a way it won't forget. Bring it to %i life.").c_str(), getOpponentName().c_str(), targetLife); - break; + sprintf(buffer, _("Defeat %s in a way it won't forget. Bring it to %i life.").c_str(), getOpponentName().c_str(), + targetLife); + break; case 1: - sprintf(buffer, _("Slaughter %s! Beat it to %i life or less.").c_str(), getOpponentName().c_str(), targetLife); - break; - } - return buffer; + sprintf(buffer, _("Slaughter %s! Beat it to %i life or less.").c_str(), getOpponentName().c_str(), targetLife); + break; + } + return buffer; } -string TaskSlaughter::getShortDesc(){ - char buffer[4096]; - sprintf(buffer, _("Slaughter %s (%i life)").c_str(), getOpponentName().c_str(), targetLife); - return buffer; +string TaskSlaughter::getShortDesc() +{ + char buffer[4096]; + sprintf(buffer, _("Slaughter %s (%i life)").c_str(), getOpponentName().c_str(), targetLife); + return buffer; } -bool TaskSlaughter::isDone(Player * _p1, Player * _p2, GameApp * _app) { - return TaskWinAgainst::isDone(_p1, _p2, _app) - && (_p2->life <= targetLife); +bool TaskSlaughter::isDone(Player * _p1, Player * _p2, GameApp * _app) +{ + return TaskWinAgainst::isDone(_p1, _p2, _app) && (_p2->life <= targetLife); } -void TaskSlaughter::storeCustomAttribs() { - char buff[256]; - - sprintf(buff, "%i", targetLife); - persistentAttribs.push_back(buff); +void TaskSlaughter::storeCustomAttribs() +{ + char buff[256]; + + sprintf(buff, "%i", targetLife); + persistentAttribs.push_back(buff); } -void TaskSlaughter::restoreCustomAttribs() { - targetLife = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); +void TaskSlaughter::restoreCustomAttribs() +{ + targetLife = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); } /*----------- TaskDelay -------------*/ // Now serves as both 'Delay' and 'Fast defeat' task. -TaskDelay::TaskDelay(int _opponent, int _turn) : TaskWinAgainst(_opponent) { - type = TASK_DELAY; - turn = _turn; - afterTurn = TRUE; +TaskDelay::TaskDelay(int _opponent, int _turn) : + TaskWinAgainst(_opponent) +{ + type = TASK_DELAY; + turn = _turn; + afterTurn = TRUE; } -int TaskDelay::computeReward() { - return TaskWinAgainst::computeReward() + (afterTurn ? turn*33 : (17-turn)*(17-turn)*17); +int TaskDelay::computeReward() +{ + return TaskWinAgainst::computeReward() + (afterTurn ? turn * 33 : (17 - turn) * (17 - turn) * 17); } -void TaskDelay::randomize() { - afterTurn = rand()%2 == 1; - turn = afterTurn ? rand()%15 + 20 : 15 - rand()%9; - Task::randomize(); +void TaskDelay::randomize() +{ + afterTurn = rand() % 2 == 1; + turn = afterTurn ? rand() % 15 + 20 : 15 - rand() % 9; + Task::randomize(); } -string TaskDelay::createDesc() { - char buffer[4096]; - if (afterTurn) { - switch (rand()%2) { - case 0: - sprintf(buffer, _("Defeat %s after keeping it occupied for %i turns.").c_str(), getOpponentName().c_str(), turn); - break; - case 1: - sprintf(buffer, _("Defeat %s, but play with it for %i turns first.").c_str(), getOpponentName().c_str(), turn); - break; +string TaskDelay::createDesc() +{ + char buffer[4096]; + if (afterTurn) + { + switch (rand() % 2) + { + case 0: + sprintf(buffer, _("Defeat %s after keeping it occupied for %i turns.").c_str(), getOpponentName().c_str(), turn); + break; + case 1: + sprintf(buffer, _("Defeat %s, but play with it for %i turns first.").c_str(), getOpponentName().c_str(), turn); + break; + } } - } else { - switch (rand()%2) { - case 0: - sprintf(buffer, _("Defeat %s and make sure it doesn't take more than %i turns.").c_str(), getOpponentName().c_str(), turn); - break; - case 1: - sprintf(buffer, _("Defeat %s, in a duel no longer than %i turns.").c_str(), getOpponentName().c_str(), turn); - break; + else + { + switch (rand() % 2) + { + case 0: + sprintf(buffer, _("Defeat %s and make sure it doesn't take more than %i turns.").c_str(), getOpponentName().c_str(), + turn); + break; + case 1: + sprintf(buffer, _("Defeat %s, in a duel no longer than %i turns.").c_str(), getOpponentName().c_str(), turn); + break; + } } - } - return buffer; + return buffer; } -string TaskDelay::getShortDesc(){ - char buffer[4096]; - if (afterTurn) { - sprintf(buffer, _("Delay %s for %i turns").c_str(), getOpponentName().c_str(), turn); - } else { - sprintf(buffer, _("Defeat %s before turn %i").c_str(), getOpponentName().c_str(), turn + 1); - } - return buffer; +string TaskDelay::getShortDesc() +{ + char buffer[4096]; + if (afterTurn) + { + sprintf(buffer, _("Delay %s for %i turns").c_str(), getOpponentName().c_str(), turn); + } + else + { + sprintf(buffer, _("Defeat %s before turn %i").c_str(), getOpponentName().c_str(), turn + 1); + } + return buffer; } -bool TaskDelay::isDone(Player * _p1, Player * _p2, GameApp * _app) { - GameObserver * g = GameObserver::GetInstance(); - return TaskWinAgainst::isDone(_p1, _p2, _app) - && (afterTurn ? (g->turn >= turn) : (g->turn <= turn)); +bool TaskDelay::isDone(Player * _p1, Player * _p2, GameApp * _app) +{ + GameObserver * g = GameObserver::GetInstance(); + return TaskWinAgainst::isDone(_p1, _p2, _app) && (afterTurn ? (g->turn >= turn) : (g->turn <= turn)); } -void TaskDelay::storeCustomAttribs() { - char buff[256]; - - sprintf(buff, "%i", turn); - persistentAttribs.push_back(buff); - sprintf(buff, "%i", afterTurn); - persistentAttribs.push_back(buff); +void TaskDelay::storeCustomAttribs() +{ + char buff[256]; + + sprintf(buff, "%i", turn); + persistentAttribs.push_back(buff); + sprintf(buff, "%i", afterTurn); + persistentAttribs.push_back(buff); } -void TaskDelay::restoreCustomAttribs() { - turn = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); - if (persistentAttribs.size() > COMMON_ATTRIBS_COUNT + 1) { - afterTurn = static_cast(atoi(persistentAttribs[COMMON_ATTRIBS_COUNT+1].c_str())); - } +void TaskDelay::restoreCustomAttribs() +{ + turn = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); + if (persistentAttribs.size() > COMMON_ATTRIBS_COUNT + 1) + { + afterTurn = static_cast (atoi(persistentAttribs[COMMON_ATTRIBS_COUNT + 1].c_str())); + } } /* ------------ TaskImmortal ------------ */ -TaskImmortal::TaskImmortal(int _targetLife) : Task(TASK_IMMORTAL) { - targetLife = _targetLife; - level = (targetLife < 100) ? 0 : ((targetLife < 1000) ? 1 : 2); +TaskImmortal::TaskImmortal(int _targetLife) : + Task(TASK_IMMORTAL) +{ + targetLife = _targetLife; + level = (targetLife < 100) ? 0 : ((targetLife < 1000) ? 1 : 2); } -int TaskImmortal::computeReward() { - return targetLife*2 + 150 + rand()%50; +int TaskImmortal::computeReward() +{ + return targetLife * 2 + 150 + rand() % 50; } -string TaskImmortal::createDesc() { - char buffer[4096]; - - sprintf(buffer, _("Defeat any opponent, having at least %i life in the end.").c_str(), targetLife); +string TaskImmortal::createDesc() +{ + char buffer[4096]; - return buffer; + sprintf(buffer, _("Defeat any opponent, having at least %i life in the end.").c_str(), targetLife); + + return buffer; } -string TaskImmortal::getShortDesc(){ - char buffer[4096]; - - switch (level) { +string TaskImmortal::getShortDesc() +{ + char buffer[4096]; + + switch (level) + { case 0: - sprintf(buffer, _("Win flawlessly (%i life)").c_str(), targetLife); - break; + sprintf(buffer, _("Win flawlessly (%i life)").c_str(), targetLife); + break; case 1: - sprintf(buffer, _("Reach Invulnerability (%i life)").c_str(), targetLife); - break; + sprintf(buffer, _("Reach Invulnerability (%i life)").c_str(), targetLife); + break; case 2: - sprintf(buffer, _("Reach Immortality! (%i life)").c_str(), targetLife); - break; - } + sprintf(buffer, _("Reach Immortality! (%i life)").c_str(), targetLife); + break; + } - return buffer; + return buffer; } -bool TaskImmortal::isDone(Player * _p1, Player * _p2, GameApp * _app) { - GameObserver * g = GameObserver::GetInstance(); - return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins - && (_p1->life >= targetLife); +bool TaskImmortal::isDone(Player * _p1, Player * _p2, GameApp * _app) +{ + GameObserver * g = GameObserver::GetInstance(); + return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins + && (_p1->life >= targetLife); } -void TaskImmortal::storeCustomAttribs() { - char buff[256]; - - sprintf(buff, "%i", targetLife); - persistentAttribs.push_back(buff); - - sprintf(buff, "%i", level); - persistentAttribs.push_back(buff); +void TaskImmortal::storeCustomAttribs() +{ + char buff[256]; + + sprintf(buff, "%i", targetLife); + persistentAttribs.push_back(buff); + + sprintf(buff, "%i", level); + persistentAttribs.push_back(buff); } -void TaskImmortal::restoreCustomAttribs() { - targetLife = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); - level = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT+1].c_str()); +void TaskImmortal::restoreCustomAttribs() +{ + targetLife = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); + level = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT + 1].c_str()); } -void TaskImmortal::randomize() { - level = rand() % 3; - switch (level) { +void TaskImmortal::randomize() +{ + level = rand() % 3; + switch (level) + { case 0: - targetLife = 20 + rand()%10; - break; + targetLife = 20 + rand() % 10; + break; case 1: - targetLife = 100 + 5*(rand()%5); - break; + targetLife = 100 + 5 * (rand() % 5); + break; case 2: - targetLife = 1000 + 50*(rand()%10); - break; - } - Task::randomize(); + targetLife = 1000 + 50 * (rand() % 10); + break; + } + Task::randomize(); } /* ------------ TaskMassiveBurial ------------ */ -TaskMassiveBurial::TaskMassiveBurial(int _color, int _bodyCount) : Task(TASK_MASSIVE_BURIAL) { - color = _color; - bodyCount = _bodyCount; - if ( (0 == color) || (0 == bodyCount) ) { - randomize(); - } -} - -int TaskMassiveBurial::computeReward() { - return rand()%150 + bodyCount * ((Constants::MTG_COLOR_LAND == color) ? 70 : 50); -} - -string TaskMassiveBurial::createDesc() { - char buffer[4096]; - - sprintf(buffer, _("Bury %i %s cards to your opponent's graveyard and defeat him.").c_str(), bodyCount, Constants::MTGColorStrings[color]); - - return buffer; -} - -string TaskMassiveBurial::getShortDesc(){ - char buffer[4096]; - switch (color) { - case Constants::MTG_COLOR_GREEN: - sprintf(buffer, _("Tame the nature (%i)").c_str(), bodyCount); - break; - case Constants::MTG_COLOR_BLUE: - sprintf(buffer, _("Evaporation (%i)").c_str(), bodyCount); - break; - case Constants::MTG_COLOR_RED: - sprintf(buffer, _("Bring the order (%i)").c_str(), bodyCount); - break; - case Constants::MTG_COLOR_BLACK: - sprintf(buffer, _("Exorcism (%i)").c_str(), bodyCount); - break; - case Constants::MTG_COLOR_WHITE: - sprintf(buffer, _("Dusk (%i)").c_str(), bodyCount); - break; - case Constants::MTG_COLOR_LAND: - sprintf(buffer, _("Selective disaster (%i)").c_str(), bodyCount); - break; - } - return buffer; -} - -bool TaskMassiveBurial::isDone(Player * _p1, Player * _p2, GameApp * _app) { - int countColor = 0; - vector cards = _p2->game->graveyard->cards; - - for (vector::iterator it = cards.begin(); it!=cards.end(); it++){ - if ((*it)->hasColor(color)) { - countColor++; +TaskMassiveBurial::TaskMassiveBurial(int _color, int _bodyCount) : + Task(TASK_MASSIVE_BURIAL) +{ + color = _color; + bodyCount = _bodyCount; + if ((0 == color) || (0 == bodyCount)) + { + randomize(); } - } - - return (countColor >= bodyCount); } -void TaskMassiveBurial::storeCustomAttribs() { - char buff[256]; - sprintf(buff, "%i", color); - persistentAttribs.push_back(buff); - - sprintf(buff, "%i", bodyCount); - persistentAttribs.push_back(buff); +int TaskMassiveBurial::computeReward() +{ + return rand() % 150 + bodyCount * ((Constants::MTG_COLOR_LAND == color) ? 70 : 50); } -void TaskMassiveBurial::restoreCustomAttribs() { - color = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); - bodyCount = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT+1].c_str()); +string TaskMassiveBurial::createDesc() +{ + char buffer[4096]; + + sprintf(buffer, _("Bury %i %s cards to your opponent's graveyard and defeat him.").c_str(), bodyCount, + Constants::MTGColorStrings[color]); + + return buffer; } -void TaskMassiveBurial::randomize() { - color = rand()%(Constants::MTG_NB_COLORS - 1) + 1; - bodyCount = 5 + ((Constants::MTG_COLOR_LAND == color) ? rand()%10 : rand()%20); - Task::randomize(); +string TaskMassiveBurial::getShortDesc() +{ + char buffer[4096]; + switch (color) + { + case Constants::MTG_COLOR_GREEN: + sprintf(buffer, _("Tame the nature (%i)").c_str(), bodyCount); + break; + case Constants::MTG_COLOR_BLUE: + sprintf(buffer, _("Evaporation (%i)").c_str(), bodyCount); + break; + case Constants::MTG_COLOR_RED: + sprintf(buffer, _("Bring the order (%i)").c_str(), bodyCount); + break; + case Constants::MTG_COLOR_BLACK: + sprintf(buffer, _("Exorcism (%i)").c_str(), bodyCount); + break; + case Constants::MTG_COLOR_WHITE: + sprintf(buffer, _("Dusk (%i)").c_str(), bodyCount); + break; + case Constants::MTG_COLOR_LAND: + sprintf(buffer, _("Selective disaster (%i)").c_str(), bodyCount); + break; + } + return buffer; +} + +bool TaskMassiveBurial::isDone(Player * _p1, Player * _p2, GameApp * _app) +{ + int countColor = 0; + vector cards = _p2->game->graveyard->cards; + + for (vector::iterator it = cards.begin(); it != cards.end(); it++) + { + if ((*it)->hasColor(color)) + { + countColor++; + } + } + + return (countColor >= bodyCount); +} + +void TaskMassiveBurial::storeCustomAttribs() +{ + char buff[256]; + sprintf(buff, "%i", color); + persistentAttribs.push_back(buff); + + sprintf(buff, "%i", bodyCount); + persistentAttribs.push_back(buff); +} + +void TaskMassiveBurial::restoreCustomAttribs() +{ + color = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); + bodyCount = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT + 1].c_str()); +} + +void TaskMassiveBurial::randomize() +{ + color = rand() % (Constants::MTG_NB_COLORS - 1) + 1; + bodyCount = 5 + ((Constants::MTG_COLOR_LAND == color) ? rand() % 10 : rand() % 20); + Task::randomize(); } /* ------------ TaskWisdom ------------ */ -TaskWisdom::TaskWisdom(int _color, int _cardCount) : Task(TASK_WISDOM) { - color = _color; - cardCount = _cardCount; - if ( (0 == color) || (0 == cardCount) ) { - randomize(); - } -} - -int TaskWisdom::computeReward() { - return (rand()%150) + (cardCount * 50) + (cardCount>7 ? 200 : 0); -} - -string TaskWisdom::createDesc() { - char buffer[4096]; - - sprintf(buffer, _("Win a game with at least %i %s cards in your hand.").c_str(), cardCount, Constants::MTGColorStrings[color]); - - return buffer; -} - -string TaskWisdom::getShortDesc(){ - char buffer[4096]; - switch (color) { - case Constants::MTG_COLOR_GREEN: - sprintf(buffer, _("Animal herder (%i)").c_str(), cardCount); - break; - case Constants::MTG_COLOR_BLUE: - sprintf(buffer, _("Accumulated knowledge (%i)").c_str(), cardCount); - break; - case Constants::MTG_COLOR_RED: - sprintf(buffer, _("Retained anger (%i)").c_str(), cardCount); - break; - case Constants::MTG_COLOR_BLACK: - sprintf(buffer, _("Necropotence (%i)").c_str(), cardCount); - break; - case Constants::MTG_COLOR_WHITE: - sprintf(buffer, _("Dawn of crusade (%i)").c_str(), cardCount); - break; - case Constants::MTG_COLOR_LAND: - sprintf(buffer, _("Mana reserves (%i)").c_str(), cardCount); - break; - } - return buffer; -} - -bool TaskWisdom::isDone(Player * _p1, Player * _p2, GameApp * _app) { - GameObserver * g = GameObserver::GetInstance(); - int countColor = 0; - vector cards = _p1->game->hand->cards; - - for (vector::iterator it = cards.begin(); it!=cards.end(); it++){ - if ((*it)->hasColor(color)) { - countColor++; +TaskWisdom::TaskWisdom(int _color, int _cardCount) : + Task(TASK_WISDOM) +{ + color = _color; + cardCount = _cardCount; + if ((0 == color) || (0 == cardCount)) + { + randomize(); } - } - - return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins - && (countColor >= cardCount); } -void TaskWisdom::storeCustomAttribs() { - char buff[256]; - sprintf(buff, "%i", color); - persistentAttribs.push_back(buff); - - sprintf(buff, "%i", cardCount); - persistentAttribs.push_back(buff); +int TaskWisdom::computeReward() +{ + return (rand() % 150) + (cardCount * 50) + (cardCount > 7 ? 200 : 0); } -void TaskWisdom::restoreCustomAttribs() { - color = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); - cardCount = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT+1].c_str()); +string TaskWisdom::createDesc() +{ + char buffer[4096]; + + sprintf(buffer, _("Win a game with at least %i %s cards in your hand.").c_str(), cardCount, Constants::MTGColorStrings[color]); + + return buffer; } -void TaskWisdom::randomize() { - color = rand()%(Constants::MTG_NB_COLORS - 1) + 1; - cardCount = 2 + ((Constants::MTG_COLOR_LAND == color) ? rand()%5 : rand()%7); - Task::randomize(); +string TaskWisdom::getShortDesc() +{ + char buffer[4096]; + switch (color) + { + case Constants::MTG_COLOR_GREEN: + sprintf(buffer, _("Animal herder (%i)").c_str(), cardCount); + break; + case Constants::MTG_COLOR_BLUE: + sprintf(buffer, _("Accumulated knowledge (%i)").c_str(), cardCount); + break; + case Constants::MTG_COLOR_RED: + sprintf(buffer, _("Retained anger (%i)").c_str(), cardCount); + break; + case Constants::MTG_COLOR_BLACK: + sprintf(buffer, _("Necropotence (%i)").c_str(), cardCount); + break; + case Constants::MTG_COLOR_WHITE: + sprintf(buffer, _("Dawn of crusade (%i)").c_str(), cardCount); + break; + case Constants::MTG_COLOR_LAND: + sprintf(buffer, _("Mana reserves (%i)").c_str(), cardCount); + break; + } + return buffer; +} + +bool TaskWisdom::isDone(Player * _p1, Player * _p2, GameApp * _app) +{ + GameObserver * g = GameObserver::GetInstance(); + int countColor = 0; + vector cards = _p1->game->hand->cards; + + for (vector::iterator it = cards.begin(); it != cards.end(); it++) + { + if ((*it)->hasColor(color)) + { + countColor++; + } + } + + return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins + && (countColor >= cardCount); +} + +void TaskWisdom::storeCustomAttribs() +{ + char buff[256]; + sprintf(buff, "%i", color); + persistentAttribs.push_back(buff); + + sprintf(buff, "%i", cardCount); + persistentAttribs.push_back(buff); +} + +void TaskWisdom::restoreCustomAttribs() +{ + color = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); + cardCount = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT + 1].c_str()); +} + +void TaskWisdom::randomize() +{ + color = rand() % (Constants::MTG_NB_COLORS - 1) + 1; + cardCount = 2 + ((Constants::MTG_COLOR_LAND == color) ? rand() % 5 : rand() % 7); + Task::randomize(); } /* ------------ TaskPacifism ------------ */ -TaskPacifism::TaskPacifism(int _lifeSlashCardMin) : Task(TASK_PACIFISM) { - lifeSlashCardMin = _lifeSlashCardMin; - if (lifeSlashCardMin == 0) { - randomize(); - } +TaskPacifism::TaskPacifism(int _lifeSlashCardMin) : + Task(TASK_PACIFISM) +{ + lifeSlashCardMin = _lifeSlashCardMin; + if (lifeSlashCardMin == 0) + { + randomize(); + } } -int TaskPacifism::computeReward() { - return 200 + (rand()%50) + (lifeSlashCardMin * 5) + (lifeSlashCardMin>20 ? 200 : 0); +int TaskPacifism::computeReward() +{ + return 200 + (rand() % 50) + (lifeSlashCardMin * 5) + (lifeSlashCardMin > 20 ? 200 : 0); } -string TaskPacifism::createDesc() { - char buffer[4096]; - - switch (rand()%2) { +string TaskPacifism::createDesc() +{ + char buffer[4096]; + + switch (rand() % 2) + { case 0: - sprintf(buffer, _("Let your opponent live with at least %i life and cards in library, but defeat him.").c_str(), lifeSlashCardMin); - break; + sprintf(buffer, _("Let your opponent live with at least %i life and cards in library, but defeat him.").c_str(), + lifeSlashCardMin); + break; case 1: - sprintf(buffer, _("Win a game with your opponent having at least %i life and cards in library.").c_str(), lifeSlashCardMin); - break; - } - return buffer; + sprintf(buffer, _("Win a game with your opponent having at least %i life and cards in library.").c_str(), lifeSlashCardMin); + break; + } + return buffer; } -string TaskPacifism::getShortDesc(){ - char buffer[4096]; - sprintf(buffer, _("Pacifism (%i)").c_str(), lifeSlashCardMin); - return buffer; +string TaskPacifism::getShortDesc() +{ + char buffer[4096]; + sprintf(buffer, _("Pacifism (%i)").c_str(), lifeSlashCardMin); + return buffer; } -bool TaskPacifism::isDone(Player * _p1, Player * _p2, GameApp * _app) { - GameObserver * g = GameObserver::GetInstance(); - return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins - && (_p2->life >= lifeSlashCardMin) && ((int)_p2->game->library->cards.size() >= lifeSlashCardMin); +bool TaskPacifism::isDone(Player * _p1, Player * _p2, GameApp * _app) +{ + GameObserver * g = GameObserver::GetInstance(); + return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins + && (_p2->life >= lifeSlashCardMin) && ((int) _p2->game->library->cards.size() >= lifeSlashCardMin); } -void TaskPacifism::storeCustomAttribs() { - char buff[256]; +void TaskPacifism::storeCustomAttribs() +{ + char buff[256]; - sprintf(buff, "%i", lifeSlashCardMin); - persistentAttribs.push_back(buff); + sprintf(buff, "%i", lifeSlashCardMin); + persistentAttribs.push_back(buff); } -void TaskPacifism::restoreCustomAttribs() { - lifeSlashCardMin = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); +void TaskPacifism::restoreCustomAttribs() +{ + lifeSlashCardMin = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT].c_str()); } -void TaskPacifism::randomize() { - lifeSlashCardMin = rand()%25 + 1; - Task::randomize(); +void TaskPacifism::randomize() +{ + lifeSlashCardMin = rand() % 25 + 1; + Task::randomize(); } /* ------------ Task template ------------ -TaskXX::TaskXX() : Task(TASK_XX) { - // TODO: Implement -} + TaskXX::TaskXX() : Task(TASK_XX) { + // TODO: Implement + } -int TaskXX::computeReward() { - // TODO: Implement - return 100; -} + int TaskXX::computeReward() { + // TODO: Implement + return 100; + } -string TaskXX::createDesc() { - // TODO: Implement - char buffer[4096]; - - switch (rand()%2) { - case 0: - sprintf(buffer, _("%s").c_str(), getOpponentName().c_str()); - break; - case 1: - sprintf(buffer, _("%s").c_str(), getOpponentName().c_str()); - break; - } - return buffer; -} + string TaskXX::createDesc() { + // TODO: Implement + char buffer[4096]; -string TaskXX::getShortDesc(){ - // TODO: Implement - char buffer[4096]; - sprintf(buffer, _("%s").c_str(), getOpponentName().c_str()); - return buffer; -} + switch (rand()%2) { + case 0: + sprintf(buffer, _("%s").c_str(), getOpponentName().c_str()); + break; + case 1: + sprintf(buffer, _("%s").c_str(), getOpponentName().c_str()); + break; + } + return buffer; + } -bool TaskXX::isDone(Player * _p1, Player * _p2, GameApp * _app) { - GameObserver * g = GameObserver::GetInstance(); - // TODO: Implement - return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins - && ; -} + string TaskXX::getShortDesc(){ + // TODO: Implement + char buffer[4096]; + sprintf(buffer, _("%s").c_str(), getOpponentName().c_str()); + return buffer; + } -void TaskXX::storeCustomAttribs() { - // TODO: Implement - char buff[256]; - persistentAttribs.push_back(VarXX); - - sprintf(buff, "%i", VarXY); - persistentAttribs.push_back(buff); -} + bool TaskXX::isDone(Player * _p1, Player * _p2, GameApp * _app) { + GameObserver * g = GameObserver::GetInstance(); + // TODO: Implement + return (!_p1->isAI()) && (_p2->isAI()) && (g->gameOver != _p1) // Human player wins + && ; + } -void TaskXX::restoreCustomAttribs() { - // TODO: Implement - VarXX = persistentAttribs[COMMON_ATTRIBS_COUNT]; - VarXY = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT+1].c_str()); -} + void TaskXX::storeCustomAttribs() { + // TODO: Implement + char buff[256]; + persistentAttribs.push_back(VarXX); -void TaskXX::randomize() { - // TODO: Implement - VarXX = rand()%10 + 1; - Task::randomize(); -} + sprintf(buff, "%i", VarXY); + persistentAttribs.push_back(buff); + } -*/ + void TaskXX::restoreCustomAttribs() { + // TODO: Implement + VarXX = persistentAttribs[COMMON_ATTRIBS_COUNT]; + VarXY = atoi(persistentAttribs[COMMON_ATTRIBS_COUNT+1].c_str()); + } + + void TaskXX::randomize() { + // TODO: Implement + VarXX = rand()%10 + 1; + Task::randomize(); + } + + */ diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index 6124507ca..70ab7b003 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -13,602 +13,750 @@ using std::string; // NULL is sent in place of a MTGDeck since there is no way to create a MTGDeck without a proper deck file. // TestSuiteAI will be responsible for managing its own deck state. -TestSuiteAI::TestSuiteAI(TestSuite * _suite, int playerId):AIPlayerBaka(NULL, "testsuite", "testsuite", "baka.jpg") { - this->game = _suite->buildDeck(playerId); - game->setOwner( this ); - suite = _suite; - timer = 0; - playMode = MODE_TEST_SUITE; - this->deckName = "Test Suite AI"; +TestSuiteAI::TestSuiteAI(TestSuite * _suite, int playerId) : + AIPlayerBaka(NULL, "testsuite", "testsuite", "baka.jpg") +{ + this->game = _suite->buildDeck(playerId); + game->setOwner(this); + suite = _suite; + timer = 0; + playMode = MODE_TEST_SUITE; + this->deckName = "Test Suite AI"; } - -MTGCardInstance * TestSuiteAI::getCard(string action){ - int mtgid = Rules::getMTGId(action); - if (mtgid) return Rules::getCardByMTGId(mtgid); - - //This mostly handles tokens - GameObserver * g = GameObserver::GetInstance(); - std::transform(action.begin(), action.end(), action.begin(),::tolower ); - for (int i = 0; i < 2; i++){ - Player * p = g->players[i]; - MTGGameZone * zones[] = {p->game->library,p->game->hand, p->game->inPlay, p->game->graveyard}; - for (int j = 0; j < 4; j++){ - MTGGameZone * zone = zones[j]; - for (int k = 0; k < zone->nb_cards; k++){ - MTGCardInstance * card = zone->cards[k]; - if (!card) return NULL; - string name = card->getLCName(); - if (name.compare(action) == 0) return card; - } - } - } - DebugTrace("TESTUISTEAI: Can't find card:" << action.c_str()); - return NULL; -} - - -Interruptible * TestSuite::getActionByMTGId(int mtgid){ - ActionStack * as= GameObserver::GetInstance()->mLayers->stackLayer(); - Interruptible * action = NULL; - while ((action = as->getNext(action,0,0,1))){ - if (action->source && action->source->getMTGId() == mtgid){ - return action; - } - } - return NULL; -} - -int TestSuiteAI::displayStack(){ - if (playMode == MODE_AI) return 0; - return 1; -} - -int TestSuiteAI::Act(float dt){ - GameObserver * g = GameObserver::GetInstance(); - g->gameOver = NULL; // Prevent draw rule from losing the game - if (playMode == MODE_AI && suite->aiMaxCalls) { - suite->aiMaxCalls--; - suite->timerLimit = 40; //TODO Remove this limitation when AI is not using a stupid timer anymore... - AIPlayerBaka::Act(dt); - } - if (playMode == MODE_HUMAN){ - g->mLayers->CheckUserInput(0); - return 1; - } - - - timer+= 1; - if (timer < suite->timerLimit) return 1; - timer = 0; - - string action = suite->getNextAction(); - g->mLayers->stackLayer()->Dump(); - // DamageResolverLayer * drl = g->mLayers->combatLayer(); - DebugTrace("TESTSUITE command: " << action); - - if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){ - if(action.compare("no") != 0 && action.compare("yes") != 0){ - g->mLayers->stackLayer()->cancelInterruptOffer(); - suite->currentAction--; - return 1; - } - } - - if (action == ""){ - //end of game - suite->assertGame(); - g->gameOver = g->players[0]; - DebugTrace("================================ END OF TEST =======================\n"); - return 1; - } - - if (action.compare("eot")== 0){ - if (g->getCurrentGamePhase() != Constants::MTG_PHASE_CLEANUP) suite->currentAction--; - g->userRequestNextGamePhase(); - } - else if (action.compare("human")==0){ - DebugTrace("TESTSUITE You have control"); - playMode = MODE_HUMAN; - return 1; - } - else if (action.compare("ai")==0){ - DebugTrace("TESTSUITE Switching to AI"); - playMode = MODE_AI; - return 1; - } - else if (action.compare("next")==0){ - GuiCombat * gc = g->mLayers->combatLayer(); - if (ORDER == g->combatStep || DAMAGE == g->combatStep) - gc->clickOK(); - else g->userRequestNextGamePhase(); - } - else if (action.compare("yes")==0) - g->mLayers->stackLayer()->setIsInterrupting(this); - else if (action.compare("endinterruption")==0) - g->mLayers->stackLayer()->endOfInterruption(); - else if(action.compare("no")==0){ - if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this) - g->mLayers->stackLayer()->cancelInterruptOffer(); - }else if(action.find("choice ")!=string::npos){ - DebugTrace("TESTSUITE choice !!!"); - int choice = atoi(action.substr(action.find("choice ") + 7).c_str()); - g->mLayers->actionLayer()->doReactTo(choice); - }else if(action.find(" -momir- ")!=string::npos){ - int start = action.find(" -momir- "); - int cardId = Rules::getMTGId(action.substr(start + 9).c_str()); - int cardIdHand = Rules::getMTGId(action.substr(0,start).c_str()); - MTGMomirRule * a = ((MTGMomirRule *)g->mLayers->actionLayer()->getAbility(MTGAbility::MOMIR)); - a->reactToClick(Rules::getCardByMTGId(cardIdHand), cardId); - g->mLayers->actionLayer()->stuffHappened = 1; - }else if(action.find("p1")!=string::npos || action.find("p2")!=string::npos){ - Player * p = g->players[1]; - size_t start = action.find("p1"); - if (start != string::npos) p = g->players[0]; - g->cardClick(NULL, p); - }else{ +MTGCardInstance * TestSuiteAI::getCard(string action) +{ int mtgid = Rules::getMTGId(action); - Interruptible * toInterrupt = NULL; - if (mtgid){ - DebugTrace("TESTSUITE CARD ID:" << mtgid); - toInterrupt = suite->getActionByMTGId(mtgid); - } + if (mtgid) return Rules::getCardByMTGId(mtgid); - if (toInterrupt) { - g->stackObjectClicked(toInterrupt); - return 1; - } - - MTGCardInstance * card = getCard(action); - if (card) { - DebugTrace("TESTSUITE Clicking ON: " << card->name); - card->currentZone->needShuffle = true; //mimic library shuffle - g->cardClick(card,card); - g->forceShuffleLibraries(); //mimic library shuffle - return 1; - } - } - return 0; -} - - -TestSuiteActions::TestSuiteActions(){ - nbitems = 0; -} - -void TestSuiteActions::add(string s){ - actions[nbitems] = s; - nbitems++; -} - -TestSuitePlayerData::TestSuitePlayerData(){ - life = 20; - manapool = NEW ManaCost(); -} - -TestSuitePlayerData::~TestSuitePlayerData(){ - SAFE_DELETE(manapool); -} - -TestSuitePlayerZone::TestSuitePlayerZone(){ - nbitems = 0; -} - -void TestSuitePlayerZone::add(int cardId){ - cards[nbitems] = cardId; - nbitems++; -} - -TestSuiteState::TestSuiteState(){ - -} - -void TestSuiteState::parsePlayerState(int playerId, string s){ - size_t limiter = s.find(":"); - string areaS; - int area; - if (limiter != string::npos){ - areaS = s.substr(0,limiter); - if (areaS.compare("graveyard") == 0){ - area = 0; - }else if(areaS.compare("library") == 0){ - area = 1; - }else if(areaS.compare("hand") == 0){ - area = 2; - }else if(areaS.compare("inplay") == 0 || areaS.compare("battlefield") == 0 ){ - area = 3; - }else if(areaS.compare("life") == 0){ - playerData[playerId].life = atoi((s.substr(limiter+1)).c_str()); - return; - }else if(areaS.compare("manapool") == 0){ - SAFE_DELETE(playerData[playerId].manapool); - playerData[playerId].manapool = ManaCost::parseManaCost(s.substr(limiter+1)); - return; - }else{ - return; // ERROR - } - s = s.substr(limiter+1); - while (s.size()){ - unsigned int value; - limiter = s.find(","); - if (limiter != string::npos){ - string ss = s.substr(0,limiter); // ss is needed because trim requires a non-const reference, - value = Rules::getMTGId(trim(ss)); // while in g++ functions cannot take non-const references from temporary values - s = s.substr(limiter+1); - }else{ - value = Rules::getMTGId(trim(s)); - s = ""; - } - if (value) playerData[playerId].zones[area].add(value); - } - }else{ - //ERROR - } -} - - -string TestSuite::getNextAction(){ - currentAction++; - if (actions.nbitems && currentAction <= actions.nbitems){ - return actions.actions[currentAction-1]; - } - return ""; -} - - -MTGPlayerCards * TestSuite::buildDeck( int playerId){ - int list[100]; - int nbcards = 0; - for (int j = 0; j < 4; j++){ - for (int k = 0; k < initState.playerData[playerId].zones[j].nbitems; k++){ - int cardid = initState.playerData[playerId].zones[j].cards[k]; - list[nbcards] = cardid; - nbcards++; - } - } - MTGPlayerCards * deck = NEW MTGPlayerCards(list, nbcards); - return deck; -} - -void TestSuite::initGame(){ - //The first test runs slowly, the other ones run faster. - //This way a human can see what happens when testing a specific file, - // or go faster when it comes to the whole test suite. - //Warning, putting this value too low (< 3) will give unexpected results - if (!timerLimit){ - timerLimit = 40; - }else{ - timerLimit = 3; - } - //Put the GameObserver in the initial state - GameObserver * g = GameObserver::GetInstance(); - DebugTrace("TESTSUITE Init Game"); - g->phaseRing->goToPhase(initState.phase, g->players[0]); - g->currentGamePhase = initState.phase; - for (int i = 0; i < 2; i++){ - AIPlayer * p = (AIPlayer *) (g->players[i]); - p->forceBestAbilityUse = forceAbility; - p->life = initState.playerData[i].life; - p->getManaPool()->copy(initState.playerData[i].manapool); - MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay}; - for (int j = 0; j < 4; j++){ - MTGGameZone * zone = playerZones[j]; - for (int k = 0; k < initState.playerData[i].zones[j].nbitems; k++){ - MTGCardInstance * card = Rules::getCardByMTGId(initState.playerData[i].zones[j].cards[k]); - if (card && zone != p->game->library){ - if (zone == p->game->inPlay){ - MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); - Spell * spell = NEW Spell(copy); - spell->resolve(); - if (!summoningSickness && p->game->inPlay->nb_cards>k) p->game->inPlay->cards[k]->summoningSickness = 0; - delete spell; - }else{ - if (!p->game->library->hasCard(card)){ - LOG ("TESTUITE ERROR, CARD NOT FOUND IN LIBRARY\n"); - } - p->game->putInZone(card,p->game->library,zone); - } - }else{ - if (!card) { LOG ("TESTUITE ERROR, card is NULL\n"); } + //This mostly handles tokens + GameObserver * g = GameObserver::GetInstance(); + std::transform(action.begin(), action.end(), action.begin(), ::tolower); + for (int i = 0; i < 2; i++) + { + Player * p = g->players[i]; + MTGGameZone * zones[] = { p->game->library, p->game->hand, p->game->inPlay, p->game->graveyard }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = zones[j]; + for (int k = 0; k < zone->nb_cards; k++) + { + MTGCardInstance * card = zone->cards[k]; + if (!card) return NULL; + string name = card->getLCName(); + if (name.compare(action) == 0) return card; + } } - } } - } - DebugTrace("TESTUITE Init Game Done !"); + DebugTrace("TESTUISTEAI: Can't find card:" << action.c_str()); + return NULL; } -int TestSuite::Log(const char * text){ - ofstream file (JGE_GET_RES("test/results.html").c_str(),ios_base::app); - if (file){ - file << text; - file << "\n"; - file.close(); - } - DebugTrace(text); - return 1; - -} -int TestSuite::assertGame(){ - //compare the game state with the results - char result[4096]; - sprintf(result,"

%s

",files[currentfile-1].c_str()); - Log(result); - - int error = 0; - bool wasAI = false; - - GameObserver * g = GameObserver::GetInstance(); - if (g->currentGamePhase != endState.phase){ - sprintf(result, "==phase problem. Expected %i, got %i==
",endState.phase, g->currentGamePhase); - Log(result); - error++; - } - for (int i = 0; i < 2; i++){ - TestSuiteAI * p = (TestSuiteAI *)(g->players[i]); - if (p->playMode == Player::MODE_AI) wasAI = true; - - if (p->life != endState.playerData[i].life){ - sprintf(result, "==life problem for player %i. Expected %i, got %i==
",i,endState.playerData[i].life, p->life); - Log(result); - error++; - } - if (! p->getManaPool()->canAfford(endState.playerData[i].manapool)){ - sprintf(result, "==Mana problem. Was expecting %i but got %i for player %i==
",endState.playerData[i].manapool->getConvertedCost(),p->getManaPool()->getConvertedCost(),i); - Log(result); - error++; - } - if(! endState.playerData[i].manapool->canAfford(p->getManaPool())){ - sprintf(result, "==Mana problem. Was expecting %i but got %i for player %i==
",endState.playerData[i].manapool->getConvertedCost(),p->getManaPool()->getConvertedCost(),i); - Log(result); - error++; - - } - MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay}; - for (int j = 0; j < 4; j++){ - MTGGameZone * zone = playerZones[j]; - if (zone->nb_cards != endState.playerData[i].zones[j].nbitems){ - sprintf(result, "==Card number not the same in player %i's %s==, expected %i, got %i
",i, zone->getName(), endState.playerData[i].zones[j].nbitems, zone->nb_cards); - Log(result); - error++; - } - for (int k = 0; k < endState.playerData[i].zones[j].nbitems; k++){ - int cardid = endState.playerData[i].zones[j].cards[k]; - if (cardid != -1){ - MTGCardInstance * card = Rules::getCardByMTGId(cardid); - if (!card || !zone->hasCard(card)){ - sprintf(result, "==Card ID not the same. Didn't find %i
", cardid); - Log(result); - error++; - } +Interruptible * TestSuite::getActionByMTGId(int mtgid) +{ + ActionStack * as = GameObserver::GetInstance()->mLayers->stackLayer(); + Interruptible * action = NULL; + while ((action = as->getNext(action, 0, 0, 1))) + { + if (action->source && action->source->getMTGId() == mtgid) + { + return action; } - } } - } - if (wasAI) { - nbAITests++; - if (error) { - nbAIFailed++; - return 0; + return NULL; +} + +int TestSuiteAI::displayStack() +{ + if (playMode == MODE_AI) return 0; + return 1; +} + +int TestSuiteAI::Act(float dt) +{ + GameObserver * g = GameObserver::GetInstance(); + g->gameOver = NULL; // Prevent draw rule from losing the game + if (playMode == MODE_AI && suite->aiMaxCalls) + { + suite->aiMaxCalls--; + suite->timerLimit = 40; //TODO Remove this limitation when AI is not using a stupid timer anymore... + AIPlayerBaka::Act(dt); } - } else { - nbTests++; - if (error) { - nbFailed++; - return 0; + if (playMode == MODE_HUMAN) + { + g->mLayers->CheckUserInput(0); + return 1; } - } - Log("==Test Succesful !=="); - return 1; -} -TestSuite::TestSuite(const char * filename,MTGAllCards* _collection){ - collection=_collection; - timerLimit = 0; - std::ifstream file(filename); - std::string s; - nbfiles = 0; - currentfile = 0; - nbFailed = 0; - nbTests = 0; - nbAIFailed = 0; - nbAITests = 0; - int comment = 0; - seed = 0; - forceAbility = false; - aiMaxCalls = -1; - if(file){ - while(std::getline(file,s)){ - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - if (s[0] == '/' && s[1] == '*') comment = 1; - if (s[0] && s[0] != '#' && !comment){ - files[nbfiles] = s; - nbfiles++; - } - if (s[0] == '*' && s[1] == '/') comment = 0; + timer += 1; + if (timer < suite->timerLimit) return 1; + timer = 0; + + string action = suite->getNextAction(); + g->mLayers->stackLayer()->Dump(); + // DamageResolverLayer * drl = g->mLayers->combatLayer(); + DebugTrace("TESTSUITE command: " << action); + + if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this) + { + if (action.compare("no") != 0 && action.compare("yes") != 0) + { + g->mLayers->stackLayer()->cancelInterruptOffer(); + suite->currentAction--; + return 1; + } } - file.close(); - } - ofstream file2 (JGE_GET_RES("/test/results.html").c_str()); - if (file2){ - file2 << ""; -#ifdef WIN32 - file2 << ""; -#endif - file2 << "\n"; - file2.close(); - } - -} - -int TestSuite::loadNext(){ - summoningSickness = 0; - seed = 0; - aiMaxCalls = -1; - if (!nbfiles) return 0; - if (currentfile >= nbfiles) return 0; - currentfile++; - if (!load(files[currentfile-1].c_str())) return loadNext(); - else cout << "Starting test : " << files[currentfile-1] << endl; - //load(files[currentfile].c_str()); - //currentfile++; - return currentfile; -} - - -void TestSuiteActions::cleanup(){ - nbitems = 0; -} - -void TestSuitePlayerZone::cleanup(){ - nbitems = 0; -} - -void TestSuitePlayerData::cleanup(){ - if (manapool) delete manapool; - manapool = NULL; - manapool = NEW ManaCost(); - for (int i = 0; i < 5; i++){ - zones[i].cleanup(); - } - life=20; -} - -void TestSuiteState::cleanup(){ - for (int i = 0; i < 2; i++){ - playerData[i].cleanup(); - } -} - -void TestSuite::cleanup(){ - currentAction = 0; - initState.cleanup(); - endState.cleanup(); - actions.cleanup(); - loadRandValues(""); -} - -int TestSuite::load(const char * _filename){ - summoningSickness = 0; - forceAbility = false; - gameType = GAME_TYPE_CLASSIC; - char filename[4096]; - sprintf(filename, JGE_GET_RES("/test/%s").c_str(), _filename); - std::ifstream file(filename); - std::string s; - loadRandValues(""); - - int state = -1; - - // std::cout << std::endl << std::endl << "!!!" << file << std::endl << std::endl; - if(file){ - cleanup(); - while(std::getline(file,s)){ - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - if (s[0] == '#') continue; - std::transform( s.begin(), s.end(), s.begin(),::tolower ); - if (s.compare("summoningsickness") == 0) { - summoningSickness = 1; - continue; - } - if (s.compare("forceability") == 0) { - forceAbility = true; - continue; - } - if (s.find("seed ") == 0) { - seed = atoi(s.substr(5).c_str()); - continue; - } - if (s.find("rvalues:") == 0) { - loadRandValues(s.substr(8).c_str()); - continue; - } - if (s.find("aicalls ") == 0) { - aiMaxCalls = atoi(s.substr(8).c_str()); - continue; - } - if (s.compare("momir") == 0) { - gameType = GAME_TYPE_MOMIR; - continue; - } - switch(state){ - case -1: - if (s.compare("[init]") == 0) state++; - break; - case 0: - if (s.compare("[player1]") == 0){ - state++; - }else{ - initState.phase = PhaseRing::phaseStrToInt(s); - } - break; - case 1: - if (s.compare("[player2]") == 0){ - state++; - }else{ - initState.parsePlayerState(0, s); - } - break; - case 2: - if (s.compare("[do]") == 0){ - state++; - }else{ - initState.parsePlayerState(1, s); - } - break; - case 3: - if (s.compare("[assert]") == 0){ - state++; - }else{ - actions.add(s); - } - break; - case 4: - if (s.compare("[player1]") == 0){ - state++; - }else{ - endState.phase = PhaseRing::phaseStrToInt(s); - } - break; - case 5: - if (s.compare("[player2]") == 0){ - state++; - }else{ - endState.parsePlayerState(0, s); - } - break; - case 6: - if (s.compare("[end]") == 0){ - state++; - }else{ - endState.parsePlayerState(1, s); - } - break; - } + if (action == "") + { + //end of game + suite->assertGame(); + g->gameOver = g->players[0]; + DebugTrace("================================ END OF TEST =======================\n"); + return 1; + } + + if (action.compare("eot") == 0) + { + if (g->getCurrentGamePhase() != Constants::MTG_PHASE_CLEANUP) suite->currentAction--; + g->userRequestNextGamePhase(); + } + else if (action.compare("human") == 0) + { + DebugTrace("TESTSUITE You have control"); + playMode = MODE_HUMAN; + return 1; + } + else if (action.compare("ai") == 0) + { + DebugTrace("TESTSUITE Switching to AI"); + playMode = MODE_AI; + return 1; + } + else if (action.compare("next") == 0) + { + GuiCombat * gc = g->mLayers->combatLayer(); + if (ORDER == g->combatStep || DAMAGE == g->combatStep) + gc->clickOK(); + else + g->userRequestNextGamePhase(); + } + else if (action.compare("yes") == 0) + g->mLayers->stackLayer()->setIsInterrupting(this); + else if (action.compare("endinterruption") == 0) + g->mLayers->stackLayer()->endOfInterruption(); + else if (action.compare("no") == 0) + { + if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this) g->mLayers->stackLayer()->cancelInterruptOffer(); + } + else if (action.find("choice ") != string::npos) + { + DebugTrace("TESTSUITE choice !!!"); + int choice = atoi(action.substr(action.find("choice ") + 7).c_str()); + g->mLayers->actionLayer()->doReactTo(choice); + } + else if (action.find(" -momir- ") != string::npos) + { + int start = action.find(" -momir- "); + int cardId = Rules::getMTGId(action.substr(start + 9).c_str()); + int cardIdHand = Rules::getMTGId(action.substr(0, start).c_str()); + MTGMomirRule * a = ((MTGMomirRule *) g->mLayers->actionLayer()->getAbility(MTGAbility::MOMIR)); + a->reactToClick(Rules::getCardByMTGId(cardIdHand), cardId); + g->mLayers->actionLayer()->stuffHappened = 1; + } + else if (action.find("p1") != string::npos || action.find("p2") != string::npos) + { + Player * p = g->players[1]; + size_t start = action.find("p1"); + if (start != string::npos) p = g->players[0]; + g->cardClick(NULL, p); + } + else + { + int mtgid = Rules::getMTGId(action); + Interruptible * toInterrupt = NULL; + if (mtgid) + { + DebugTrace("TESTSUITE CARD ID:" << mtgid); + toInterrupt = suite->getActionByMTGId(mtgid); + } + + if (toInterrupt) + { + g->stackObjectClicked(toInterrupt); + return 1; + } + + MTGCardInstance * card = getCard(action); + if (card) + { + DebugTrace("TESTSUITE Clicking ON: " << card->name); + card->currentZone->needShuffle = true; //mimic library shuffle + g->cardClick(card, card); + g->forceShuffleLibraries(); //mimic library shuffle + return 1; + } } - file.close(); - }else{ return 0; - } - return 1; } +TestSuiteActions::TestSuiteActions() +{ + nbitems = 0; +} -void TestSuite::pregameTests(){ +void TestSuiteActions::add(string s) +{ + actions[nbitems] = s; + nbitems++; +} + +TestSuitePlayerData::TestSuitePlayerData() +{ + life = 20; + manapool = NEW ManaCost(); +} + +TestSuitePlayerData::~TestSuitePlayerData() +{ + SAFE_DELETE(manapool); +} + +TestSuitePlayerZone::TestSuitePlayerZone() +{ + nbitems = 0; +} + +void TestSuitePlayerZone::add(int cardId) +{ + cards[nbitems] = cardId; + nbitems++; +} + +TestSuiteState::TestSuiteState() +{ + +} + +void TestSuiteState::parsePlayerState(int playerId, string s) +{ + size_t limiter = s.find(":"); + string areaS; + int area; + if (limiter != string::npos) + { + areaS = s.substr(0, limiter); + if (areaS.compare("graveyard") == 0) + { + area = 0; + } + else if (areaS.compare("library") == 0) + { + area = 1; + } + else if (areaS.compare("hand") == 0) + { + area = 2; + } + else if (areaS.compare("inplay") == 0 || areaS.compare("battlefield") == 0) + { + area = 3; + } + else if (areaS.compare("life") == 0) + { + playerData[playerId].life = atoi((s.substr(limiter + 1)).c_str()); + return; + } + else if (areaS.compare("manapool") == 0) + { + SAFE_DELETE(playerData[playerId].manapool); + playerData[playerId].manapool = ManaCost::parseManaCost(s.substr(limiter + 1)); + return; + } + else + { + return; // ERROR + } + s = s.substr(limiter + 1); + while (s.size()) + { + unsigned int value; + limiter = s.find(","); + if (limiter != string::npos) + { + string ss = s.substr(0, limiter); // ss is needed because trim requires a non-const reference, + value = Rules::getMTGId(trim(ss)); // while in g++ functions cannot take non-const references from temporary values + s = s.substr(limiter + 1); + } + else + { + value = Rules::getMTGId(trim(s)); + s = ""; + } + if (value) playerData[playerId].zones[area].add(value); + } + } + else + { + //ERROR + } +} + +string TestSuite::getNextAction() +{ + currentAction++; + if (actions.nbitems && currentAction <= actions.nbitems) + { + return actions.actions[currentAction - 1]; + } + return ""; +} + +MTGPlayerCards * TestSuite::buildDeck(int playerId) +{ + int list[100]; + int nbcards = 0; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < initState.playerData[playerId].zones[j].nbitems; k++) + { + int cardid = initState.playerData[playerId].zones[j].cards[k]; + list[nbcards] = cardid; + nbcards++; + } + } + MTGPlayerCards * deck = NEW MTGPlayerCards(list, nbcards); + return deck; +} + +void TestSuite::initGame() +{ + //The first test runs slowly, the other ones run faster. + //This way a human can see what happens when testing a specific file, + // or go faster when it comes to the whole test suite. + //Warning, putting this value too low (< 3) will give unexpected results + if (!timerLimit) + { + timerLimit = 40; + } + else + { + timerLimit = 3; + } + //Put the GameObserver in the initial state + GameObserver * g = GameObserver::GetInstance(); + DebugTrace("TESTSUITE Init Game"); + g->phaseRing->goToPhase(initState.phase, g->players[0]); + g->currentGamePhase = initState.phase; + for (int i = 0; i < 2; i++) + { + AIPlayer * p = (AIPlayer *) (g->players[i]); + p->forceBestAbilityUse = forceAbility; + p->life = initState.playerData[i].life; + p->getManaPool()->copy(initState.playerData[i].manapool); + MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = playerZones[j]; + for (int k = 0; k < initState.playerData[i].zones[j].nbitems; k++) + { + MTGCardInstance * card = Rules::getCardByMTGId(initState.playerData[i].zones[j].cards[k]); + if (card && zone != p->game->library) + { + if (zone == p->game->inPlay) + { + MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); + Spell * spell = NEW Spell(copy); + spell->resolve(); + if (!summoningSickness && p->game->inPlay->nb_cards > k) p->game->inPlay->cards[k]->summoningSickness = 0; + delete spell; + } + else + { + if (!p->game->library->hasCard(card)) + { + LOG ("TESTUITE ERROR, CARD NOT FOUND IN LIBRARY\n"); + } + p->game->putInZone(card, p->game->library, zone); + } + } + else + { + if (!card) + { + LOG ("TESTUITE ERROR, card is NULL\n"); + } + } + } + } + } +DebugTrace("TESTUITE Init Game Done !"); +} +int TestSuite::Log(const char * text) +{ + ofstream file(JGE_GET_RES("test/results.html").c_str(), ios_base::app); + if (file) + { + file << text; + file << "\n"; + file.close(); + } + + DebugTrace(text); + return 1; + +} +int TestSuite::assertGame() +{ + //compare the game state with the results + char result[4096]; + sprintf(result, "

%s

", files[currentfile - 1].c_str()); + Log(result); + + int error = 0; + bool wasAI = false; + + GameObserver * g = GameObserver::GetInstance(); + if (g->currentGamePhase != endState.phase) + { + sprintf(result, "==phase problem. Expected %i, got %i==
", endState.phase, + g->currentGamePhase); + Log(result); + error++; + } + for (int i = 0; i < 2; i++) + { + TestSuiteAI * p = (TestSuiteAI *) (g->players[i]); + if (p->playMode == Player::MODE_AI) wasAI = true; + + if (p->life != endState.playerData[i].life) + { + sprintf(result, "==life problem for player %i. Expected %i, got %i==
", i, + endState.playerData[i].life, p->life); + Log(result); + error++; + } + if (!p->getManaPool()->canAfford(endState.playerData[i].manapool)) + { + sprintf(result, "==Mana problem. Was expecting %i but got %i for player %i==
", + endState.playerData[i].manapool->getConvertedCost(), p->getManaPool()->getConvertedCost(), i); + Log(result); + error++; + } + if (!endState.playerData[i].manapool->canAfford(p->getManaPool())) + { + sprintf(result, "==Mana problem. Was expecting %i but got %i for player %i==
", + endState.playerData[i].manapool->getConvertedCost(), p->getManaPool()->getConvertedCost(), i); + Log(result); + error++; + + } + MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = playerZones[j]; + if (zone->nb_cards != endState.playerData[i].zones[j].nbitems) + { + sprintf( + result, + "==Card number not the same in player %i's %s==, expected %i, got %i
", + i, zone->getName(), endState.playerData[i].zones[j].nbitems, zone->nb_cards); + Log(result); + error++; + } + for (int k = 0; k < endState.playerData[i].zones[j].nbitems; k++) + { + int cardid = endState.playerData[i].zones[j].cards[k]; + if (cardid != -1) + { + MTGCardInstance * card = Rules::getCardByMTGId(cardid); + if (!card || !zone->hasCard(card)) + { + sprintf(result, "==Card ID not the same. Didn't find %i
", cardid); + Log(result); + error++; + } + } + } + } + } + if (wasAI) + { + nbAITests++; + if (error) + { + nbAIFailed++; + return 0; + } + } + else + { + nbTests++; + if (error) + { + nbFailed++; + return 0; + } + } + Log("==Test Succesful !=="); + return 1; +} + +TestSuite::TestSuite(const char * filename, MTGAllCards* _collection) +{ + collection = _collection; + timerLimit = 0; + std::ifstream file(filename); + std::string s; + nbfiles = 0; + currentfile = 0; + nbFailed = 0; + nbTests = 0; + nbAIFailed = 0; + nbAITests = 0; + int comment = 0; + seed = 0; + forceAbility = false; + aiMaxCalls = -1; + if (file) + { + while (std::getline(file, s)) + { + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + if (s[0] == '/' && s[1] == '*') comment = 1; + if (s[0] && s[0] != '#' && !comment) + { + files[nbfiles] = s; + nbfiles++; + } + if (s[0] == '*' && s[1] == '/') comment = 0; + } + file.close(); + } + + ofstream file2(JGE_GET_RES("/test/results.html").c_str()); + if (file2) + { + file2 << ""; +#ifdef WIN32 + file2 << ""; +#endif + file2 << "\n"; + file2.close(); + } + +} + +int TestSuite::loadNext() +{ + summoningSickness = 0; + seed = 0; + aiMaxCalls = -1; + if (!nbfiles) return 0; + if (currentfile >= nbfiles) return 0; + currentfile++; + if (!load(files[currentfile - 1].c_str())) + return loadNext(); + else + cout << "Starting test : " << files[currentfile - 1] << endl; + //load(files[currentfile].c_str()); + //currentfile++; + return currentfile; +} + +void TestSuiteActions::cleanup() +{ + nbitems = 0; +} + +void TestSuitePlayerZone::cleanup() +{ + nbitems = 0; +} + +void TestSuitePlayerData::cleanup() +{ + if (manapool) delete manapool; + manapool = NULL; + manapool = NEW ManaCost(); + for (int i = 0; i < 5; i++) + { + zones[i].cleanup(); + } + life = 20; +} + +void TestSuiteState::cleanup() +{ + for (int i = 0; i < 2; i++) + { + playerData[i].cleanup(); + } +} + +void TestSuite::cleanup() +{ + currentAction = 0; + initState.cleanup(); + endState.cleanup(); + actions.cleanup(); + loadRandValues(""); +} + +int TestSuite::load(const char * _filename) +{ + summoningSickness = 0; + forceAbility = false; + gameType = GAME_TYPE_CLASSIC; + char filename[4096]; + sprintf(filename, JGE_GET_RES("/test/%s").c_str(), _filename); + std::ifstream file(filename); + std::string s; + loadRandValues(""); + + int state = -1; + + // std::cout << std::endl << std::endl << "!!!" << file << std::endl << std::endl; + if (file) + { + cleanup(); + while (std::getline(file, s)) + { + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + if (s[0] == '#') continue; + std::transform(s.begin(), s.end(), s.begin(), ::tolower); + if (s.compare("summoningsickness") == 0) + { + summoningSickness = 1; + continue; + } + if (s.compare("forceability") == 0) + { + forceAbility = true; + continue; + } + if (s.find("seed ") == 0) + { + seed = atoi(s.substr(5).c_str()); + continue; + } + if (s.find("rvalues:") == 0) + { + loadRandValues(s.substr(8).c_str()); + continue; + } + if (s.find("aicalls ") == 0) + { + aiMaxCalls = atoi(s.substr(8).c_str()); + continue; + } + if (s.compare("momir") == 0) + { + gameType = GAME_TYPE_MOMIR; + continue; + } + switch (state) + { + case -1: + if (s.compare("[init]") == 0) state++; + break; + case 0: + if (s.compare("[player1]") == 0) + { + state++; + } + else + { + initState.phase = PhaseRing::phaseStrToInt(s); + } + break; + case 1: + if (s.compare("[player2]") == 0) + { + state++; + } + else + { + initState.parsePlayerState(0, s); + } + break; + case 2: + if (s.compare("[do]") == 0) + { + state++; + } + else + { + initState.parsePlayerState(1, s); + } + break; + case 3: + if (s.compare("[assert]") == 0) + { + state++; + } + else + { + actions.add(s); + } + break; + case 4: + if (s.compare("[player1]") == 0) + { + state++; + } + else + { + endState.phase = PhaseRing::phaseStrToInt(s); + } + break; + case 5: + if (s.compare("[player2]") == 0) + { + state++; + } + else + { + endState.parsePlayerState(0, s); + } + break; + case 6: + if (s.compare("[end]") == 0) + { + state++; + } + else + { + endState.parsePlayerState(1, s); + } + break; + } + } + file.close(); + } + else + { + return 0; + } + return 1; +} + +void TestSuite::pregameTests() +{ //Test Booster Generation srand(1024); char result[1024]; ShopBooster sb; - for(int i=0;i<5;i++){ + for (int i = 0; i < 5; i++) + { nbTests++; sprintf(result, "

pregame/BoosterTest#%i

", i); Log(result); - if(!sb.unitTest()) - nbFailed++; + if (!sb.unitTest()) nbFailed++; } } diff --git a/projects/mtg/src/TextScroller.cpp b/projects/mtg/src/TextScroller.cpp index 42d6708fe..bc5b90b1f 100644 --- a/projects/mtg/src/TextScroller.cpp +++ b/projects/mtg/src/TextScroller.cpp @@ -5,100 +5,103 @@ #include "utils.h" #include "WFont.h" -enum { - HORIZONTAL_SCROLLER = 0, - VERTICAL_SCROLLER = 1 +enum +{ + HORIZONTAL_SCROLLER = 0, VERTICAL_SCROLLER = 1 }; - -TextScroller::TextScroller(int fontId, float x, float y, float width, float speed, int scrollerType, size_t numItems ): JGuiObject(0), fontId(fontId){ - mWidth = width; - mSpeed = speed; - minimumItems = numItems; - mX = x; - mY = y; - start = -width; - timer = 0; - currentId = 0; - mRandom = 0; - scrollDirection = scrollerType; +TextScroller::TextScroller(int fontId, float x, float y, float width, float speed, int scrollerType, size_t numItems) : + JGuiObject(0), fontId(fontId) +{ + mWidth = width; + mSpeed = speed; + minimumItems = numItems; + mX = x; + mY = y; + start = -width; + timer = 0; + currentId = 0; + mRandom = 0; + scrollDirection = scrollerType; } -void TextScroller::setRandom(int mode){ - mRandom = mode; - if (mRandom && strings.size()){ - currentId = (rand() % strings.size()); - mText = strings[currentId]; - } -} - -void TextScroller::Add(string text){ - if (!strings.size()) mText = text; - strings.push_back(text); -} - -void TextScroller::Reset(){ - strings.clear(); - currentId = 0; -} - -void TextScroller::Update(float dt){ - if(!strings.size()) - return; - if ( scrollDirection == HORIZONTAL_SCROLLER ) - { - start+=mSpeed*dt; - WFont * mFont = resources.GetWFont(fontId); - if (start > mFont->GetStringWidth(mText.c_str())){ - start = -mWidth; - if (mRandom){ - currentId = (rand() % strings.size()); - }else{ - currentId++; - if (currentId >= strings.size())currentId = 0; - } - mText = strings[currentId]; - } - } - else - { - // we want to display 2 at a time - ostringstream scrollerText; - if ( timer == 0 ) +void TextScroller::setRandom(int mode) +{ + mRandom = mode; + if (mRandom && strings.size()) { - size_t nbItemsToDisplay = ( minimumItems < strings.size() ? minimumItems : strings.size()); - for ( size_t idx = 0; idx < nbItemsToDisplay; ++idx) - { - size_t index = (currentId + idx) % strings.size(); - scrollerText << strings[index]; - } - currentId++; - if ( currentId >= strings.size()) - currentId = 0; - mText = wordWrap( scrollerText.str(), (int) mWidth ); + currentId = (rand() % strings.size()); + mText = strings[currentId]; } - timer = ++timer % ((int) mSpeed); - } } -void TextScroller::Render(){ - WFont * mFont = resources.GetWFont(fontId); - if ( scrollDirection == HORIZONTAL_SCROLLER ) - mFont->DrawString(mText.c_str(),mX,mY,JGETEXT_LEFT,start,mWidth); - else - mFont->DrawString(mText.c_str(), mX, mY ); +void TextScroller::Add(string text) +{ + if (!strings.size()) mText = text; + strings.push_back(text); +} + +void TextScroller::Reset() +{ + strings.clear(); + currentId = 0; +} + +void TextScroller::Update(float dt) +{ + if (!strings.size()) return; + if (scrollDirection == HORIZONTAL_SCROLLER) + { + start += mSpeed * dt; + WFont * mFont = resources.GetWFont(fontId); + if (start > mFont->GetStringWidth(mText.c_str())) + { + start = -mWidth; + if (mRandom) + { + currentId = (rand() % strings.size()); + } + else + { + currentId++; + if (currentId >= strings.size()) currentId = 0; + } + mText = strings[currentId]; + } + } + else + { + // we want to display 2 at a time + ostringstream scrollerText; + if (timer == 0) + { + size_t nbItemsToDisplay = (minimumItems < strings.size() ? minimumItems : strings.size()); + for (size_t idx = 0; idx < nbItemsToDisplay; ++idx) + { + size_t index = (currentId + idx) % strings.size(); + scrollerText << strings[index]; + } + currentId++; + if (currentId >= strings.size()) currentId = 0; + mText = wordWrap(scrollerText.str(), (int) mWidth); + } + timer = ++timer % ((int) mSpeed); + } +} + +void TextScroller::Render() +{ + WFont * mFont = resources.GetWFont(fontId); + if (scrollDirection == HORIZONTAL_SCROLLER) + mFont->DrawString(mText.c_str(), mX, mY, JGETEXT_LEFT, start, mWidth); + else + mFont->DrawString(mText.c_str(), mX, mY); } ostream& TextScroller::toString(ostream& out) const { - return out << "TextScroller ::: mText : " << mText - << " ; tempText : " << tempText - << " ; mWidth : " << mWidth - << " ; mSpeed : " << mSpeed - << " ; mX,mY : " << mX << "," << mY - << " ; start : " << start - << " ; timer : " << timer - << " ; strings : ?" // << strings - << " ; currentId : " << currentId - << " ; mRandom : " << mRandom; + return out << "TextScroller ::: mText : " << mText << " ; tempText : " << tempText << " ; mWidth : " << mWidth + << " ; mSpeed : " << mSpeed << " ; mX,mY : " << mX << "," << mY << " ; start : " << start << " ; timer : " + << timer << " ; strings : ?" // << strings + << " ; currentId : " << currentId << " ; mRandom : " << mRandom; } diff --git a/projects/mtg/src/ThisDescriptor.cpp b/projects/mtg/src/ThisDescriptor.cpp index fefceaa11..e0baf48c9 100644 --- a/projects/mtg/src/ThisDescriptor.cpp +++ b/projects/mtg/src/ThisDescriptor.cpp @@ -5,330 +5,394 @@ #include "MTGCardInstance.h" #include "CardDescriptor.h" - -ThisDescriptor::~ThisDescriptor(){ - //nothing to do for now +ThisDescriptor::~ThisDescriptor() +{ + //nothing to do for now } //Returns the amount by which a value passes the comparison. -int ThisDescriptor::matchValue(int value){ - switch (comparisonMode){ +int ThisDescriptor::matchValue(int value) +{ + switch (comparisonMode) + { case COMPARISON_AT_MOST: - return (comparisonCriterion - value + 1); + return (comparisonCriterion - value + 1); case COMPARISON_AT_LEAST: - return (value - comparisonCriterion + 1); + return (value - comparisonCriterion + 1); case COMPARISON_EQUAL: - return (comparisonCriterion == value); + return (comparisonCriterion == value); case COMPARISON_GREATER: - return (value - comparisonCriterion); + return (value - comparisonCriterion); case COMPARISON_LESS: - return (comparisonCriterion - value); + return (comparisonCriterion - value); case COMPARISON_UNEQUAL: - return (comparisonCriterion != value); - } - return 0; + return (comparisonCriterion != value); + } + return 0; } -ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s){ - size_t found; - - string whitespaces (" \t\f\v\n\r"); +ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s) +{ + size_t found; - found=s.find_last_not_of(whitespaces); - if (found!=string::npos) - s.erase(found+1); - else return NULL; + string whitespaces(" \t\f\v\n\r"); - found=s.find_first_not_of(whitespaces); - if (found!=string::npos) - s.erase(0,found); - else return NULL; + found = s.find_last_not_of(whitespaces); + if (found != string::npos) + s.erase(found + 1); + else + return NULL; - //set comparison mode - //equal, greater, and less must remain above the others, otherwise the others may never be used. - int mode = 0; - size_t found2 = string::npos; - int opLength = 0; + found = s.find_first_not_of(whitespaces); + if (found != string::npos) + s.erase(0, found); + else + return NULL; - found = s.find("="); - if (found != string::npos){ - mode = COMPARISON_EQUAL; - found2 = found + 1; - opLength = 1; - } - found = s.find(">"); - if (found != string::npos){ - mode = COMPARISON_GREATER; - found2 = found + 1; - opLength = 1; - } - found = s.find("<"); - if (found != string::npos){ - mode = COMPARISON_LESS; - found2 = found + 1; - opLength = 1; - } - found = s.find("<="); - if (found != string::npos){ - mode = COMPARISON_AT_MOST; - found2 = found + 2; - opLength = 2; - } - found = s.find(">="); - if (found != string::npos){ - mode = COMPARISON_AT_LEAST; - found2 = found + 2; - opLength = 2; - } - found = s.find("!="); - if (found != string::npos){ - mode = COMPARISON_UNEQUAL; - found2 = found + 2; - opLength = 2; - } - if (!mode) mode = COMPARISON_AT_LEAST; + //set comparison mode + //equal, greater, and less must remain above the others, otherwise the others may never be used. + int mode = 0; + size_t found2 = string::npos; + int opLength = 0; - //get comparison criterion - int criterionFound = 0; - int criterion = 1; - if ((found2 != string::npos) && (found2 < s.length())){ - criterion = atoi(s.substr(found2).c_str()); - criterionFound = 1; - } - if (found2 != string::npos) s.erase(found2 - opLength); - - //counters - found = s.find("counter{"); - if (found != string::npos) { - size_t start = s.find("{"); - size_t end = s.find("}"); - string counterString = s.substr(start+1,end-start-1); - AbilityFactory abf; - Counter * counter = abf.parseCounter(counterString,NULL); - if (counter) { - if (criterionFound) counter->nb = criterion; - ThisCounter * td = NEW ThisCounter(counter); - if (td) { - td->comparisonMode = mode; - return td; - } + found = s.find("="); + if (found != string::npos) + { + mode = COMPARISON_EQUAL; + found2 = found + 1; + opLength = 1; } - return NULL; - } - - //any counter - found = s.find("counters"); - if (found != string::npos) { - ThisCounterAny * td = NEW ThisCounterAny(criterion); - if (td) { - td->comparisonMode = mode; - return td; + found = s.find(">"); + if (found != string::npos) + { + mode = COMPARISON_GREATER; + found2 = found + 1; + opLength = 1; } - return NULL; - } - - //equips - found = s.find("gear");//still same meaning, better wording to word conflict with MTGAbility equip. - if (found != string::npos) { - ThisEquip * td = NEW ThisEquip(criterion); - if (td) { - td->comparisonMode = mode; - return td; + found = s.find("<"); + if (found != string::npos) + { + mode = COMPARISON_LESS; + found2 = found + 1; + opLength = 1; } - return NULL; - } - - //whenever this creature attacks do effect - found = s.find("attacking"); - if (found != string::npos) { - ThisAttacked * td = NEW ThisAttacked(criterion); - if (td) { - td->comparisonMode = mode; - return td; + found = s.find("<="); + if (found != string::npos) + { + mode = COMPARISON_AT_MOST; + found2 = found + 2; + opLength = 2; } - return NULL; - } - - //whenever this creature attacks do effect - found = s.find("notblocked"); - if (found != string::npos) { - ThisNotBlocked * td = NEW ThisNotBlocked(criterion); - if (td) { - td->comparisonMode = mode; - return td; + found = s.find(">="); + if (found != string::npos) + { + mode = COMPARISON_AT_LEAST; + found2 = found + 2; + opLength = 2; } - return NULL; - } - - //controller life - found = s.find("opponentlife"); - if (found != string::npos) { - ThisOpponentlife * td = NEW ThisOpponentlife(criterion); - if (td) { - td->comparisonMode = mode; - return td; + found = s.find("!="); + if (found != string::npos) + { + mode = COMPARISON_UNEQUAL; + found2 = found + 2; + opLength = 2; } - return NULL; - } + if (!mode) mode = COMPARISON_AT_LEAST; - //controller life - found = s.find("controllerlife"); - if (found != string::npos) { - ThisControllerlife * td = NEW ThisControllerlife(criterion); - if (td) { - td->comparisonMode = mode; - return td; + //get comparison criterion + int criterionFound = 0; + int criterion = 1; + if ((found2 != string::npos) && (found2 < s.length())) + { + criterion = atoi(s.substr(found2).c_str()); + criterionFound = 1; } - return NULL; - } + if (found2 != string::npos) s.erase(found2 - opLength); - //power - found = s.find("power"); - if (found != string::npos) { - ThisPower * td = NEW ThisPower(criterion); - if (td) { - td->comparisonMode = mode; - return td; + //counters + found = s.find("counter{"); + if (found != string::npos) + { + size_t start = s.find("{"); + size_t end = s.find("}"); + string counterString = s.substr(start + 1, end - start - 1); + AbilityFactory abf; + Counter * counter = abf.parseCounter(counterString, NULL); + if (counter) + { + if (criterionFound) counter->nb = criterion; + ThisCounter * td = NEW ThisCounter(counter); + if (td) + { + td->comparisonMode = mode; + return td; + } + } + return NULL; } - return NULL; - } - //toughness - found = s.find("toughness"); - if (found != string::npos) { - ThisToughness * td = NEW ThisToughness(criterion); - if (td) { - td->comparisonMode = mode; - return td; + //any counter + found = s.find("counters"); + if (found != string::npos) + { + ThisCounterAny * td = NEW ThisCounterAny(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; } - return NULL; - } - // X - found = s.find("x"); - if (found != string::npos) { - ThisX * td = NEW ThisX(criterion); - if (td){ - td->comparisonMode = mode; - return td; + //equips + found = s.find("gear");//still same meaning, better wording to word conflict with MTGAbility equip. + if (found != string::npos) + { + ThisEquip * td = NEW ThisEquip(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; } - return NULL; - } - return NULL; + //whenever this creature attacks do effect + found = s.find("attacking"); + if (found != string::npos) + { + ThisAttacked * td = NEW ThisAttacked(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; + } + + //whenever this creature attacks do effect + found = s.find("notblocked"); + if (found != string::npos) + { + ThisNotBlocked * td = NEW ThisNotBlocked(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; + } + + //controller life + found = s.find("opponentlife"); + if (found != string::npos) + { + ThisOpponentlife * td = NEW ThisOpponentlife(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; + } + + //controller life + found = s.find("controllerlife"); + if (found != string::npos) + { + ThisControllerlife * td = NEW ThisControllerlife(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; + } + + //power + found = s.find("power"); + if (found != string::npos) + { + ThisPower * td = NEW ThisPower(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; + } + + //toughness + found = s.find("toughness"); + if (found != string::npos) + { + ThisToughness * td = NEW ThisToughness(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; + } + + // X + found = s.find("x"); + if (found != string::npos) + { + ThisX * td = NEW ThisX(criterion); + if (td) + { + td->comparisonMode = mode; + return td; + } + return NULL; + } + + return NULL; } -ThisCounter::ThisCounter(Counter * _counter){ - counter = _counter; - comparisonCriterion = counter->nb; +ThisCounter::ThisCounter(Counter * _counter) +{ + counter = _counter; + comparisonCriterion = counter->nb; } -ThisCounter::ThisCounter(int power, int toughness, int nb, const char * name){ - counter = NEW Counter(NULL,name,power,toughness); - comparisonCriterion = nb; +ThisCounter::ThisCounter(int power, int toughness, int nb, const char * name) +{ + counter = NEW Counter(NULL, name, power, toughness); + comparisonCriterion = nb; } -int ThisCounter::match(MTGCardInstance * card){ - Counter * targetCounter = card->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness); - if (targetCounter){ - return matchValue(targetCounter->nb); - }else{ - switch (comparisonMode) { +int ThisCounter::match(MTGCardInstance * card) +{ + Counter * targetCounter = card->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness); + if (targetCounter) + { + return matchValue(targetCounter->nb); + } + else + { + switch (comparisonMode) + { case COMPARISON_LESS: - return comparisonCriterion; + return comparisonCriterion; case COMPARISON_AT_MOST: - return comparisonCriterion + 1; + return comparisonCriterion + 1; case COMPARISON_UNEQUAL: - if (comparisonCriterion) return 1; - else return 0; + if (comparisonCriterion) + return 1; + else + return 0; case COMPARISON_EQUAL: - if (comparisonCriterion) return 0; - else return 1; - default : - return 0; - } + if (comparisonCriterion) + return 0; + else + return 1; + default: + return 0; + } } } -ThisCounter::~ThisCounter() { - SAFE_DELETE(counter); +ThisCounter::~ThisCounter() +{ + SAFE_DELETE(counter); } -ThisOpponentlife::ThisOpponentlife(int olife){ - comparisonCriterion = olife; +ThisOpponentlife::ThisOpponentlife(int olife) +{ + comparisonCriterion = olife; } -int ThisOpponentlife::match(MTGCardInstance * card){ - return matchValue(card->controller()->opponent()->life); +int ThisOpponentlife::match(MTGCardInstance * card) +{ + return matchValue(card->controller()->opponent()->life); } -ThisControllerlife::ThisControllerlife(int life){ - comparisonCriterion = life; +ThisControllerlife::ThisControllerlife(int life) +{ + comparisonCriterion = life; } -int ThisControllerlife::match(MTGCardInstance * card){ - return matchValue(card->controller()->life); +int ThisControllerlife::match(MTGCardInstance * card) +{ + return matchValue(card->controller()->life); } -ThisPower::ThisPower(int power){ - comparisonCriterion = power; +ThisPower::ThisPower(int power) +{ + comparisonCriterion = power; } -int ThisPower::match(MTGCardInstance * card){ - return matchValue(card->power); +int ThisPower::match(MTGCardInstance * card) +{ + return matchValue(card->power); } -ThisEquip::ThisEquip(int equipment){ - comparisonCriterion = equipment; +ThisEquip::ThisEquip(int equipment) +{ + comparisonCriterion = equipment; } -int ThisEquip::match(MTGCardInstance * card){ - return matchValue(card->equipment); +int ThisEquip::match(MTGCardInstance * card) +{ + return matchValue(card->equipment); } -ThisAttacked::ThisAttacked(int attack){ +ThisAttacked::ThisAttacked(int attack) +{ - comparisonCriterion = attack; + comparisonCriterion = attack; } -int ThisAttacked::match(MTGCardInstance * card){ +int ThisAttacked::match(MTGCardInstance * card) +{ - return matchValue(card->didattacked); + return matchValue(card->didattacked); } -ThisNotBlocked::ThisNotBlocked(int unblocked){ +ThisNotBlocked::ThisNotBlocked(int unblocked) +{ - comparisonCriterion = unblocked; + comparisonCriterion = unblocked; } -int ThisNotBlocked::match(MTGCardInstance * card){ +int ThisNotBlocked::match(MTGCardInstance * card) +{ - return matchValue(card->notblocked); + return matchValue(card->notblocked); } -ThisToughness::ThisToughness(int toughness){ - comparisonCriterion = toughness; +ThisToughness::ThisToughness(int toughness) +{ + comparisonCriterion = toughness; } -int ThisToughness::match(MTGCardInstance * card){ - return matchValue(card->toughness); +int ThisToughness::match(MTGCardInstance * card) +{ + return matchValue(card->toughness); } -ThisCounterAny::ThisCounterAny(int nb){ - comparisonCriterion = nb; +ThisCounterAny::ThisCounterAny(int nb) +{ + comparisonCriterion = nb; } -int ThisCounterAny::match(MTGCardInstance * card){ - int result = 0; - for (int i = 0; i < card->counters->mCount; i++) { - result += card->counters->counters[i]->nb; - } - return matchValue(result); +int ThisCounterAny::match(MTGCardInstance * card) +{ + int result = 0; + for (int i = 0; i < card->counters->mCount; i++) + { + result += card->counters->counters[i]->nb; + } + return matchValue(result); } -ThisX::ThisX(int x){ - comparisonCriterion = x; +ThisX::ThisX(int x) +{ + comparisonCriterion = x; } -int ThisX::match(MTGCardInstance * card){ - return matchValue(card->X); -} \ No newline at end of file +int ThisX::match(MTGCardInstance * card) +{ + return matchValue(card->X); +} diff --git a/projects/mtg/src/Token.cpp b/projects/mtg/src/Token.cpp index adaf15900..1535c21ce 100644 --- a/projects/mtg/src/Token.cpp +++ b/projects/mtg/src/Token.cpp @@ -2,23 +2,25 @@ #include "Token.h" -Token::Token(string _name, MTGCardInstance * source, int _power, int _toughness):MTGCardInstance(){ - isToken = true; - tokenSource = source; - power = _power; - toughness = _toughness; - life=toughness; - lifeOrig = life; - rarity = Constants::RARITY_T; - name = _name; - if (name.size() && name[0]>=97 && name[0]<=122) name[0]-=32; //Poor man's camelcase. We assume strings we get are either Camelcased or lowercase - setMTGId(- source->getMTGId()); - setId = source->setId; - model = this; - data=this; - owner = source->owner; - belongs_to=source->controller()->game; - attacker = 0; - defenser = NULL; - banding = NULL; +Token::Token(string _name, MTGCardInstance * source, int _power, int _toughness) : + MTGCardInstance() +{ + isToken = true; + tokenSource = source; + power = _power; + toughness = _toughness; + life = toughness; + lifeOrig = life; + rarity = Constants::RARITY_T; + name = _name; + if (name.size() && name[0] >= 97 && name[0] <= 122) name[0] -= 32; //Poor man's camelcase. We assume strings we get are either Camelcased or lowercase + setMTGId(-source->getMTGId()); + setId = source->setId; + model = this; + data = this; + owner = source->owner; + belongs_to = source->controller()->game; + attacker = 0; + defenser = NULL; + banding = NULL; } diff --git a/projects/mtg/src/Translate.cpp b/projects/mtg/src/Translate.cpp index b94cdea06..3503a9707 100644 --- a/projects/mtg/src/Translate.cpp +++ b/projects/mtg/src/Translate.cpp @@ -3,159 +3,179 @@ #include "Translate.h" #include "GameOptions.h" -Translator * Translator::mInstance = NULL; +Translator * Translator::mInstance = NULL; -Translator * Translator::GetInstance(){ - if (!mInstance) mInstance = NEW Translator(); - return mInstance; +Translator * Translator::GetInstance() +{ + if (!mInstance) mInstance = NEW Translator(); + return mInstance; } -void Translator::EndInstance(){ - SAFE_DELETE(mInstance); +void Translator::EndInstance() +{ + SAFE_DELETE(mInstance); } -int Translator::Add(string from, string to){ - values[from] = to; - return 1; +int Translator::Add(string from, string to) +{ + values[from] = to; + return 1; } -string Translator::translate(string value){ - //if (!initDone) init(); - map::iterator it = values.find(value); - if (it != values.end()) return it->second; +string Translator::translate(string value) +{ + //if (!initDone) init(); + map::iterator it = values.find(value); + if (it != values.end()) return it->second; #if defined DEBUG_TRANSLATE - if (checkMisses){ - map::iterator it2 = dontCareValues.find(value); - if (it2 == dontCareValues.end()) - missingValues[value] = 1; - } -#endif - return value; -} - - -Translator::~Translator(){ -#if defined DEBUG_TRANSLATE - if (!checkMisses) return; - std::ofstream file(JGE_GET_RES("lang/missing.txt").c_str()); - char writer[4096]; - if (file){ - map::iterator it; - for (it = missingValues.begin(); it!=missingValues.end(); it++){ - sprintf(writer,"%s=\n", it->first.c_str()); - file<::iterator it2 = dontCareValues.find(value); + if (it2 == dontCareValues.end()) + missingValues[value] = 1; } - file.close(); - } #endif -} -Translator::Translator(){ - initDone = false; - neofont = false; - //init(); + return value; } -void Translator::load(string filename, map * dictionary) { - std::ifstream file(filename.c_str()); - - if(file){ - string s; - initDone = true; +Translator::~Translator() +{ #if defined DEBUG_TRANSLATE - checkMisses = 1; -#endif - while(std::getline(file,s)){ - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - size_t found = s.find('='); - if (found == string::npos) continue; - string s1 = s.substr(0,found); - string s2 = s.substr(found+1); - (*dictionary)[s1] = s2; + if (!checkMisses) return; + std::ofstream file(JGE_GET_RES("lang/missing.txt").c_str()); + char writer[4096]; + if (file) + { + map::iterator it; + for (it = missingValues.begin(); it!=missingValues.end(); it++) + { + sprintf(writer,"%s=\n", it->first.c_str()); + file< * dictionary) +{ + std::ifstream file(filename.c_str()); + + if (file) + { + string s; + initDone = true; +#if defined DEBUG_TRANSLATE + checkMisses = 1; +#endif + while (std::getline(file, s)) + { + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + size_t found = s.find('='); + if (found == string::npos) continue; + string s1 = s.substr(0, found); + string s2 = s.substr(found + 1); + (*dictionary)[s1] = s2; + } + file.close(); } - file.close(); - } #if defined DEBUG_TRANSLATE - if (!checkMisses) return; - std::ifstream file2(JGE_GET_RES("lang/dontcare.txt").c_str()); + if (!checkMisses) return; + std::ifstream file2(JGE_GET_RES("lang/dontcare.txt").c_str()); - if(file2){ - string s; - while(std::getline(file2,s)){ - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - size_t found = s.find('='); - if (found != string::npos) - s = s.substr(0,found); - dontCareValues[s] = 1; + if(file2) + { + string s; + while(std::getline(file2,s)) + { + if (!s.size()) continue; + if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files + size_t found = s.find('='); + if (found != string::npos) + s = s.substr(0,found); + dontCareValues[s] = 1; + } + file2.close(); } - file2.close(); - } #endif } -void Translator::initCards(){ - string lang = options[Options::LANG].str; - if (!lang.size()) return; - string cards_dict = JGE_GET_RES("lang/") + lang + "_cards.txt"; - load(cards_dict,&tempValues); +void Translator::initCards() +{ + string lang = options[Options::LANG].str; + if (!lang.size()) return; + string cards_dict = JGE_GET_RES("lang/") + lang + "_cards.txt"; + load(cards_dict, &tempValues); } -void Translator::initDecks(){ - string lang = options[Options::LANG].str; - if (!lang.size()) return; - string decks_dict = JGE_GET_RES("lang/") + lang + "_decks.txt"; +void Translator::initDecks() +{ + string lang = options[Options::LANG].str; + if (!lang.size()) return; + string decks_dict = JGE_GET_RES("lang/") + lang + "_decks.txt"; - // Load file - std::ifstream file(decks_dict.c_str()); - if(file){ - string s; - initDone = true; - while(std::getline(file,s)){ - if (!s.size()) continue; - if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files - // Translate '@' to '\n' - // Note: general language files don't include any line-break infomation - char * sp = (char *)s.c_str(); - for (int i = 0; sp[i]; i++) - if (sp[i] == '@') sp[i] = '\n'; - size_t found = s.find('='); - if (found == string::npos) continue; - string s1 = s.substr(0,found); - string s2 = s.substr(found+1); - deckValues[s1] = s2; + // Load file + std::ifstream file(decks_dict.c_str()); + if (file) + { + string s; + initDone = true; + while (std::getline(file, s)) + { + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + // Translate '@' to '\n' + // Note: general language files don't include any line-break infomation + char * sp = (char *) s.c_str(); + for (int i = 0; sp[i]; i++) + if (sp[i] == '@') sp[i] = '\n'; + size_t found = s.find('='); + if (found == string::npos) continue; + string s1 = s.substr(0, found); + string s2 = s.substr(found + 1); + deckValues[s1] = s2; + } + file.close(); } - file.close(); - } } -void Translator::init() { +void Translator::init() +{ #if defined DEBUG_TRANSLATE - checkMisses = 0; + checkMisses = 0; #endif - string lang = options[Options::LANG].str; - if (!lang.size()) return; - string name = JGE_GET_RES("lang/") + lang + ".txt"; + string lang = options[Options::LANG].str; + if (!lang.size()) return; + string name = JGE_GET_RES("lang/") + lang + ".txt"; - if (fileExists(name.c_str())){ - // fixup for multibyte support. - std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower); - if (lang.compare("cn") == 0 || lang.compare("jp") == 0) - neofont = true; - else - neofont = false; - initDone = true; - load(name,&values); - } + if (fileExists(name.c_str())) + { + // fixup for multibyte support. + std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower); + if (lang.compare("cn") == 0 || lang.compare("jp") == 0) + neofont = true; + else + neofont = false; + initDone = true; + load(name, &values); + } - initCards(); - initDecks(); + initCards(); + initDecks(); } -string _(string toTranslate){ - Translator * t = Translator::GetInstance(); - return t->translate(toTranslate); +string _(string toTranslate) +{ + Translator * t = Translator::GetInstance(); + return t->translate(toTranslate); } bool neofont; diff --git a/projects/mtg/src/TranslateKeys.cpp b/projects/mtg/src/TranslateKeys.cpp index e3779840f..2fc414804 100644 --- a/projects/mtg/src/TranslateKeys.cpp +++ b/projects/mtg/src/TranslateKeys.cpp @@ -11,122 +11,123 @@ static map fattable; static map slimtable; #ifdef LINUX -const KeyRep& translateKey(LocalKeySym key) { - { - map::iterator res; - if ((res = fattable.find(key)) != fattable.end()) - return res->second; - } - - char* str = NULL; -#ifndef QT_CONFIG - str = XKeysymToString(key); -#endif // QT_CONFIG - if (!str) +const KeyRep& translateKey(LocalKeySym key) +{ { - str = NEW char[11]; - sprintf(str, "%lu", key); + map::iterator res; + if ((res = fattable.find(key)) != fattable.end()) + return res->second; } - const KeyRep k = make_pair(str, static_cast(NULL)); - fattable[key] = k; - return fattable[key]; + + char* str = NULL; +#ifndef QT_CONFIG + str = XKeysymToString(key); +#endif // QT_CONFIG + if (!str) + { + str = NEW char[11]; + sprintf(str, "%lu", key); + } + const KeyRep k = make_pair(str, static_cast(NULL)); + fattable[key] = k; + return fattable[key]; } #else #ifdef WIN32 +const KeyRep& translateKey(LocalKeySym key) +{ + { + map::iterator res; + if ((res = fattable.find(key)) != fattable.end()) + return (res->second); + } + unsigned int sc = MapVirtualKey(key, 0); -const KeyRep& translateKey(LocalKeySym key) { - { - map::iterator res; - if ((res = fattable.find(key)) != fattable.end()) - return (res->second); - } - unsigned int sc = MapVirtualKey(key, 0); + switch (key) + { + case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: // arrow keys + case VK_PRIOR: case VK_NEXT: // page up and page down + case VK_END: case VK_HOME: + case VK_INSERT: case VK_DELETE: + case VK_DIVIDE: // numpad slash + case VK_NUMLOCK: + { + sc |= 0x100; // set extended bit + break; + } + } - switch (key) - { - case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: // arrow keys - case VK_PRIOR: case VK_NEXT: // page up and page down - case VK_END: case VK_HOME: - case VK_INSERT: case VK_DELETE: - case VK_DIVIDE: // numpad slash - case VK_NUMLOCK: - { - sc |= 0x100; // set extended bit - break; - } - } + char buf[256]; + memset(buf, 0, 256); - - char buf[256]; - memset(buf, 0, 256); - - string s; - // Convert to ANSI string - if (GetKeyNameTextA(sc << 16, buf, 256) > 0) + string s; + // Convert to ANSI string + if (GetKeyNameTextA(sc << 16, buf, 256) > 0) s = buf; - KeyRep k; - if (0 == s.length()) { - char*str = NEW char[11]; - sprintf(str, "%d", key); - k = make_pair(str, static_cast(NULL)); - } - else k = make_pair(s, static_cast(NULL)); - fattable[key] = k; - return fattable[key]; + KeyRep k; + if (0 == s.length()) + { + char*str = NEW char[11]; + sprintf(str, "%d", key); + k = make_pair(str, static_cast(NULL)); + } + else k = make_pair(s, static_cast(NULL)); + fattable[key] = k; + return fattable[key]; } #else // PSP - -const KeyRep& translateKey(LocalKeySym key) { - map::iterator res; - if ((res = fattable.find(key)) == fattable.end()) +const KeyRep& translateKey(LocalKeySym key) +{ + map::iterator res; + if ((res = fattable.find(key)) == fattable.end()) { - if (fattable.end() == fattable.find(PSP_CTRL_SELECT)) + if (fattable.end() == fattable.find(PSP_CTRL_SELECT)) { - fattable[PSP_CTRL_SELECT] = make_pair(_("Select"), static_cast(NULL)); - fattable[PSP_CTRL_START] = make_pair(_("Start"), static_cast(NULL)); - fattable[PSP_CTRL_UP] = make_pair(_("Up"), static_cast(NULL)); - fattable[PSP_CTRL_RIGHT] = make_pair(_("Right"), static_cast(NULL)); - fattable[PSP_CTRL_DOWN] = make_pair(_("Down"), static_cast(NULL)); - fattable[PSP_CTRL_LEFT] = make_pair(_("Left"), static_cast(NULL)); - fattable[PSP_CTRL_LTRIGGER] = make_pair(_("Left trigger"), static_cast(NULL)); - fattable[PSP_CTRL_RTRIGGER] = make_pair(_("Right trigger"), static_cast(NULL)); - fattable[PSP_CTRL_TRIANGLE] = make_pair(_("Triangle"), static_cast(NULL)); - fattable[PSP_CTRL_CIRCLE] = make_pair(_("Circle"), static_cast(NULL)); - fattable[PSP_CTRL_CROSS] = make_pair(_("Cross"), static_cast(NULL)); - fattable[PSP_CTRL_SQUARE] = make_pair(_("Square"), static_cast(NULL)); - fattable[PSP_CTRL_HOLD] = make_pair(_("Hold"), static_cast(NULL)); + fattable[PSP_CTRL_SELECT] = make_pair(_("Select"), static_cast(NULL)); + fattable[PSP_CTRL_START] = make_pair(_("Start"), static_cast(NULL)); + fattable[PSP_CTRL_UP] = make_pair(_("Up"), static_cast(NULL)); + fattable[PSP_CTRL_RIGHT] = make_pair(_("Right"), static_cast(NULL)); + fattable[PSP_CTRL_DOWN] = make_pair(_("Down"), static_cast(NULL)); + fattable[PSP_CTRL_LEFT] = make_pair(_("Left"), static_cast(NULL)); + fattable[PSP_CTRL_LTRIGGER] = make_pair(_("Left trigger"), static_cast(NULL)); + fattable[PSP_CTRL_RTRIGGER] = make_pair(_("Right trigger"), static_cast(NULL)); + fattable[PSP_CTRL_TRIANGLE] = make_pair(_("Triangle"), static_cast(NULL)); + fattable[PSP_CTRL_CIRCLE] = make_pair(_("Circle"), static_cast(NULL)); + fattable[PSP_CTRL_CROSS] = make_pair(_("Cross"), static_cast(NULL)); + fattable[PSP_CTRL_SQUARE] = make_pair(_("Square"), static_cast(NULL)); + fattable[PSP_CTRL_HOLD] = make_pair(_("Hold"), static_cast(NULL)); } - else + else { - char* str = NEW char[11]; - sprintf(str, "%d", (int) key); - fattable[key] = make_pair(str, static_cast(static_cast(NULL))); + char* str = NEW char[11]; + sprintf(str, "%d", (int) key); + fattable[key] = make_pair(str, static_cast (static_cast (NULL))); } - res = fattable.find(key); + res = fattable.find(key); } - KeyRep& k = res->second; - switch(key) + KeyRep& k = res->second; + switch (key) { - case PSP_CTRL_SELECT : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 32, 64, 32, "PSP_CTRL_SELECT", RETRIEVE_NORMAL); break; - case PSP_CTRL_START : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 32, 64, 32, "PSP_CTRL_START", RETRIEVE_NORMAL); break; - case PSP_CTRL_UP : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 0, 32, 32, "PSP_CTRL_UP", RETRIEVE_NORMAL); break; - case PSP_CTRL_RIGHT : k.second = resources.RetrieveQuad("iconspsp.png", (float)3*32, 0, 32, 32, "PSP_CTRL_RIGHT", RETRIEVE_NORMAL); break; - case PSP_CTRL_DOWN : k.second = resources.RetrieveQuad("iconspsp.png", (float)1*32, 0, 32, 32, "PSP_CTRL_DOWN", RETRIEVE_NORMAL); break; - case PSP_CTRL_LEFT : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 0, 32, 32, "PSP_CTRL_LEFT", RETRIEVE_NORMAL); break; - case PSP_CTRL_LTRIGGER : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 32, 64, 32, "PSP_CTRL_LTRIGGER", RETRIEVE_NORMAL); break; - case PSP_CTRL_RTRIGGER : k.second = resources.RetrieveQuad("iconspsp.png", (float)8*32, 32, 64, 32, "PSP_CTRL_RTRIGGER", RETRIEVE_NORMAL); break; - case PSP_CTRL_TRIANGLE : k.second = resources.RetrieveQuad("iconspsp.png", (float)5*32, 0, 32, 32, "PSP_CTRL_TRIANGLE", RETRIEVE_NORMAL); break; - case PSP_CTRL_CIRCLE : k.second = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32, "PSP_CTRL_CIRCLE", RETRIEVE_NORMAL); break; - case PSP_CTRL_CROSS : k.second = resources.RetrieveQuad("iconspsp.png", (float)7*32, 0, 32, 32, "PSP_CTRL_CROSS", RETRIEVE_NORMAL); break; - case PSP_CTRL_SQUARE : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 0, 32, 32, "PSP_CTRL_SQUARE", RETRIEVE_NORMAL); break; - case PSP_CTRL_HOLD : k.second = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32, "PSP_CTRL_HOLD", RETRIEVE_NORMAL); break; - default: /* Unknown key : no icon */ ; + case PSP_CTRL_SELECT : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 32, 64, 32, "PSP_CTRL_SELECT", RETRIEVE_NORMAL); break; + case PSP_CTRL_START : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 32, 64, 32, "PSP_CTRL_START", RETRIEVE_NORMAL); break; + case PSP_CTRL_UP : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 0, 32, 32, "PSP_CTRL_UP", RETRIEVE_NORMAL); break; + case PSP_CTRL_RIGHT : k.second = resources.RetrieveQuad("iconspsp.png", (float)3*32, 0, 32, 32, "PSP_CTRL_RIGHT", RETRIEVE_NORMAL); break; + case PSP_CTRL_DOWN : k.second = resources.RetrieveQuad("iconspsp.png", (float)1*32, 0, 32, 32, "PSP_CTRL_DOWN", RETRIEVE_NORMAL); break; + case PSP_CTRL_LEFT : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 0, 32, 32, "PSP_CTRL_LEFT", RETRIEVE_NORMAL); break; + case PSP_CTRL_LTRIGGER : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 32, 64, 32, "PSP_CTRL_LTRIGGER", RETRIEVE_NORMAL); break; + case PSP_CTRL_RTRIGGER : k.second = resources.RetrieveQuad("iconspsp.png", (float)8*32, 32, 64, 32, "PSP_CTRL_RTRIGGER", RETRIEVE_NORMAL); break; + case PSP_CTRL_TRIANGLE : k.second = resources.RetrieveQuad("iconspsp.png", (float)5*32, 0, 32, 32, "PSP_CTRL_TRIANGLE", RETRIEVE_NORMAL); break; + case PSP_CTRL_CIRCLE : k.second = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32, "PSP_CTRL_CIRCLE", RETRIEVE_NORMAL); break; + case PSP_CTRL_CROSS : k.second = resources.RetrieveQuad("iconspsp.png", (float)7*32, 0, 32, 32, "PSP_CTRL_CROSS", RETRIEVE_NORMAL); break; + case PSP_CTRL_SQUARE : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 0, 32, 32, "PSP_CTRL_SQUARE", RETRIEVE_NORMAL); break; + case PSP_CTRL_HOLD : k.second = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32, "PSP_CTRL_HOLD", RETRIEVE_NORMAL); break; + default: /* Unknown key : no icon */ ; } - return k; + return k; } #endif #endif @@ -160,49 +161,49 @@ const KeyRep& translateKey(JButton key) { */ map::iterator res; - if ((res = slimtable.find(key)) == slimtable.end()) + if ((res = slimtable.find(key)) == slimtable.end()) { - if (slimtable.end() == slimtable.find(JGE_BTN_CTRL)) + if (slimtable.end() == slimtable.find(JGE_BTN_CTRL)) { - slimtable[JGE_BTN_NONE] = make_pair(_("Delete this binding"), static_cast(NULL)); - slimtable[JGE_BTN_CTRL] = make_pair(_("Select"), static_cast(NULL)); - slimtable[JGE_BTN_MENU] = make_pair(_("Start"), static_cast(NULL)); - slimtable[JGE_BTN_UP] = make_pair(_("Up"), static_cast(NULL)); - slimtable[JGE_BTN_RIGHT] = make_pair(_("Right"), static_cast(NULL)); - slimtable[JGE_BTN_DOWN] = make_pair(_("Down"), static_cast(NULL)); - slimtable[JGE_BTN_LEFT] = make_pair(_("Left"), static_cast(NULL)); - slimtable[JGE_BTN_PREV] = make_pair(_("Left trigger"), static_cast(NULL)); - slimtable[JGE_BTN_NEXT] = make_pair(_("Right trigger"), static_cast(NULL)); - slimtable[JGE_BTN_CANCEL] = make_pair(_("Triangle"), static_cast(NULL)); - slimtable[JGE_BTN_OK] = make_pair(_("Circle"), static_cast(NULL)); - slimtable[JGE_BTN_SEC] = make_pair(_("Cross"), static_cast(NULL)); - slimtable[JGE_BTN_PRI] = make_pair(_("Square"), static_cast(NULL)); - slimtable[JGE_BTN_FULLSCREEN] = make_pair(_("Fullscreen"), static_cast(NULL)); + slimtable[JGE_BTN_NONE] = make_pair(_("Delete this binding"), static_cast(NULL)); + slimtable[JGE_BTN_CTRL] = make_pair(_("Select"), static_cast(NULL)); + slimtable[JGE_BTN_MENU] = make_pair(_("Start"), static_cast(NULL)); + slimtable[JGE_BTN_UP] = make_pair(_("Up"), static_cast(NULL)); + slimtable[JGE_BTN_RIGHT] = make_pair(_("Right"), static_cast(NULL)); + slimtable[JGE_BTN_DOWN] = make_pair(_("Down"), static_cast(NULL)); + slimtable[JGE_BTN_LEFT] = make_pair(_("Left"), static_cast(NULL)); + slimtable[JGE_BTN_PREV] = make_pair(_("Left trigger"), static_cast(NULL)); + slimtable[JGE_BTN_NEXT] = make_pair(_("Right trigger"), static_cast(NULL)); + slimtable[JGE_BTN_CANCEL] = make_pair(_("Triangle"), static_cast(NULL)); + slimtable[JGE_BTN_OK] = make_pair(_("Circle"), static_cast(NULL)); + slimtable[JGE_BTN_SEC] = make_pair(_("Cross"), static_cast(NULL)); + slimtable[JGE_BTN_PRI] = make_pair(_("Square"), static_cast(NULL)); + slimtable[JGE_BTN_FULLSCREEN] = make_pair(_("Fullscreen"), static_cast(NULL)); } - else + else { char* str = NEW char[11]; - sprintf(str, "%d", key); - slimtable[key] = make_pair(str, static_cast(static_cast(NULL))); + sprintf(str, "%d", key); + slimtable[key] = make_pair(str, static_cast (static_cast (NULL))); } - res = slimtable.find(key); + res = slimtable.find(key); } - KeyRep& k = res->second; - switch(key) + KeyRep& k = res->second; + switch (key) { - case JGE_BTN_CTRL : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 32, 64, 32, "PSP_CTRL_SELECT", RETRIEVE_NORMAL); break; - case JGE_BTN_MENU : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 32, 64, 32, "PSP_CTRL_START", RETRIEVE_NORMAL); break; - case JGE_BTN_UP : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 0, 32, 32, "PSP_CTRL_UP", RETRIEVE_NORMAL); break; - case JGE_BTN_RIGHT : k.second = resources.RetrieveQuad("iconspsp.png", (float)3*32, 0, 32, 32, "PSP_CTRL_RIGHT", RETRIEVE_NORMAL); break; - case JGE_BTN_DOWN : k.second = resources.RetrieveQuad("iconspsp.png", (float)1*32, 0, 32, 32, "PSP_CTRL_DOWN", RETRIEVE_NORMAL); break; - case JGE_BTN_LEFT : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 0, 32, 32, "PSP_CTRL_LEFT", RETRIEVE_NORMAL); break; - case JGE_BTN_PREV : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 32, 64, 32, "PSP_CTRL_LTRIGGER", RETRIEVE_NORMAL); break; - case JGE_BTN_NEXT : k.second = resources.RetrieveQuad("iconspsp.png", (float)8*32, 32, 64, 32, "PSP_CTRL_RTRIGGER", RETRIEVE_NORMAL); break; - case JGE_BTN_CANCEL : k.second = resources.RetrieveQuad("iconspsp.png", (float)5*32, 0, 32, 32, "PSP_CTRL_TRIANGLE", RETRIEVE_NORMAL); break; - case JGE_BTN_OK : k.second = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32, "PSP_CTRL_CIRCLE", RETRIEVE_NORMAL); break; - case JGE_BTN_SEC : k.second = resources.RetrieveQuad("iconspsp.png", (float)7*32, 0, 32, 32, "PSP_CTRL_CROSS", RETRIEVE_NORMAL); break; - case JGE_BTN_PRI : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 0, 32, 32, "PSP_CTRL_SQUARE", RETRIEVE_NORMAL); break; - default: /* Unknown key : no icon */ ; + case JGE_BTN_CTRL : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 32, 64, 32, "PSP_CTRL_SELECT", RETRIEVE_NORMAL); break; + case JGE_BTN_MENU : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 32, 64, 32, "PSP_CTRL_START", RETRIEVE_NORMAL); break; + case JGE_BTN_UP : k.second = resources.RetrieveQuad("iconspsp.png", (float)0*32, 0, 32, 32, "PSP_CTRL_UP", RETRIEVE_NORMAL); break; + case JGE_BTN_RIGHT : k.second = resources.RetrieveQuad("iconspsp.png", (float)3*32, 0, 32, 32, "PSP_CTRL_RIGHT", RETRIEVE_NORMAL); break; + case JGE_BTN_DOWN : k.second = resources.RetrieveQuad("iconspsp.png", (float)1*32, 0, 32, 32, "PSP_CTRL_DOWN", RETRIEVE_NORMAL); break; + case JGE_BTN_LEFT : k.second = resources.RetrieveQuad("iconspsp.png", (float)2*32, 0, 32, 32, "PSP_CTRL_LEFT", RETRIEVE_NORMAL); break; + case JGE_BTN_PREV : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 32, 64, 32, "PSP_CTRL_LTRIGGER", RETRIEVE_NORMAL); break; + case JGE_BTN_NEXT : k.second = resources.RetrieveQuad("iconspsp.png", (float)8*32, 32, 64, 32, "PSP_CTRL_RTRIGGER", RETRIEVE_NORMAL); break; + case JGE_BTN_CANCEL : k.second = resources.RetrieveQuad("iconspsp.png", (float)5*32, 0, 32, 32, "PSP_CTRL_TRIANGLE", RETRIEVE_NORMAL); break; + case JGE_BTN_OK : k.second = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32, "PSP_CTRL_CIRCLE", RETRIEVE_NORMAL); break; + case JGE_BTN_SEC : k.second = resources.RetrieveQuad("iconspsp.png", (float)7*32, 0, 32, 32, "PSP_CTRL_CROSS", RETRIEVE_NORMAL); break; + case JGE_BTN_PRI : k.second = resources.RetrieveQuad("iconspsp.png", (float)6*32, 0, 32, 32, "PSP_CTRL_SQUARE", RETRIEVE_NORMAL); break; + default: /* Unknown key : no icon */ ; } - return k; + return k; } diff --git a/projects/mtg/src/Trash.cpp b/projects/mtg/src/Trash.cpp index 869f4e649..515c2e3b2 100644 --- a/projects/mtg/src/Trash.cpp +++ b/projects/mtg/src/Trash.cpp @@ -6,12 +6,12 @@ #include "DamagerDamaged.h" #include "Trash.h" -template +template void TrashBin::put_out() { - for (typename std::vector::iterator it = bin.begin(); it != bin.end(); ++it) - SAFE_DELETE(*it); - bin.clear(); + for (typename std::vector::iterator it = bin.begin(); it != bin.end(); ++it) + SAFE_DELETE(*it); + bin.clear(); } static TrashBin CardViewTrash; @@ -20,20 +20,20 @@ static TrashBin AttackerDamagedTrash; void Trash::cleanup() { - CardViewTrash.put_out(); - DefenserDamagedTrash.put_out(); - AttackerDamagedTrash.put_out(); + CardViewTrash.put_out(); + DefenserDamagedTrash.put_out(); + AttackerDamagedTrash.put_out(); } template<> void trash(CardView* garbage) { - CardViewTrash.bin.push_back(garbage); + CardViewTrash.bin.push_back(garbage); } template<> void trash(DefenserDamaged* garbage) { - DefenserDamagedTrash.bin.push_back(garbage); + DefenserDamagedTrash.bin.push_back(garbage); } template<> void trash(AttackerDamaged* garbage) { - AttackerDamagedTrash.bin.push_back(garbage); + AttackerDamagedTrash.bin.push_back(garbage); } diff --git a/projects/mtg/src/WCachedResource.cpp b/projects/mtg/src/WCachedResource.cpp index cfc301e71..87f59e324 100644 --- a/projects/mtg/src/WCachedResource.cpp +++ b/projects/mtg/src/WCachedResource.cpp @@ -10,425 +10,477 @@ #endif //WResource -WResource::~WResource(){ -} -WResource::WResource(){ - locks = WRES_UNLOCKED; - lastTime = resources.nowTime(); - loadedMode = 0; +WResource::~WResource() +{ } -bool WResource::isLocked(){ - return (locks != WRES_UNLOCKED); +WResource::WResource() +{ + locks = WRES_UNLOCKED; + lastTime = resources.nowTime(); + loadedMode = 0; } -bool WResource::isPermanent(){ - return (locks == WRES_PERMANENT); +bool WResource::isLocked() +{ + return (locks != WRES_UNLOCKED); } -void WResource::deadbolt(){ - if(locks <= WRES_MAX_LOCK) - locks = WRES_PERMANENT; +bool WResource::isPermanent() +{ + return (locks == WRES_PERMANENT); } -void WResource::lock(){ - if(locks < WRES_MAX_LOCK) - locks++; +void WResource::deadbolt() +{ + if (locks <= WRES_MAX_LOCK) locks = WRES_PERMANENT; } -void WResource::unlock(bool force){ - if(force) - locks = 0; - else if(locks > WRES_UNLOCKED){ - if(locks <= WRES_MAX_LOCK) - locks--; - } - else +void WResource::lock() +{ + if (locks < WRES_MAX_LOCK) locks++; +} + +void WResource::unlock(bool force) +{ + if (force) + locks = 0; + else if (locks > WRES_UNLOCKED) + { + if (locks <= WRES_MAX_LOCK) locks--; + } + else #ifdef DEBUG_CACHE - locks = WRES_UNDERLOCKED; + locks = WRES_UNDERLOCKED; #else - locks = 0; + locks = 0; #endif } -void WResource::hit(){ - lastTime = resources.nowTime(); +void WResource::hit() +{ + lastTime = resources.nowTime(); } WCachedResource::~WCachedResource() { - DebugTrace("Destroying WCachedResource: " << mFilename); + DebugTrace("Destroying WCachedResource: " << mFilename); } //WCachedTexture -WCachedTexture::WCachedTexture(){ - texture = NULL; +WCachedTexture::WCachedTexture() +{ + texture = NULL; } -WCachedTexture::~WCachedTexture(){ - if(texture) +WCachedTexture::~WCachedTexture() +{ + if (texture) SAFE_DELETE(texture); - if(!trackedQuads.size()) - return; + if (!trackedQuads.size()) return; - vector::iterator it; - WTrackedQuad * tq = NULL; + vector::iterator it; + WTrackedQuad * tq = NULL; - for(it=trackedQuads.begin();it!=trackedQuads.end();it++){ - tq = (*it); - SAFE_DELETE(tq); - } - trackedQuads.clear(); -} - -JTexture * WCachedTexture::Actual(){ - return texture; -} -bool WCachedTexture::isLocked(){ - if(locks != WRES_UNLOCKED) - return true; - - for(vector::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){ - if((*it)->isLocked()) - return true; - } - - return false; -} - -bool WCachedTexture::ReleaseQuad(JQuad* quad){ - if(quad == NULL) - return false; - - WTrackedQuad * tq = NULL; - vector::iterator nit; - for(vector::iterator it = trackedQuads.begin();it!=trackedQuads.end();it=nit){ - nit = it; - nit++; - if((*it) && (*it)->quad == quad ){ - tq = (*it); - tq->unlock(); - - if(!tq->isLocked()){ - SAFE_DELETE(tq); - trackedQuads.erase(it); - } - - return true; //Returns true when found. - } - } - return false; -} - -WTrackedQuad * WCachedTexture::GetTrackedQuad(float offX, float offY, float width, float height,string resname){ - if(!texture) return NULL; - - bool allocated = false; - WTrackedQuad * tq = NULL; - JQuad * quad = NULL; - - vector::iterator it; - - if(width == 0.0f || width > static_cast(texture->mWidth)) - width = static_cast(texture->mWidth); - if(height == 0.0f || height > static_cast(texture->mHeight)) - height = static_cast(texture->mHeight); - - for(it = trackedQuads.begin();it!=trackedQuads.end();it++){ - if((*it) && (*it)->resname == resname){ - tq = (*it); - break; - } - } - - if(!tq){ - allocated = true; - tq = NEW WTrackedQuad(resname); - if(!tq) return NULL; - } - - quad = tq->quad; - - if(!quad){ - quad = NEW JQuad(texture,offX,offY,width,height); -/* -There's a risk this erases the texture calling the quad creation.... Erwan 2010/03/13 - if(!quad) { - //Probably out of memory. Try again. - resources.Cleanup(); - quad = NEW JQuad(texture,offX,offY,width,height); - } -*/ - if(!quad){ - if(allocated && tq) + for (it = trackedQuads.begin(); it != trackedQuads.end(); it++) + { + tq = (*it); SAFE_DELETE(tq); - fprintf(stderr, "WCACHEDRESOURCE:GetTrackedQuad - Quad is null\n"); - return NULL; //Probably a crash. + } + trackedQuads.clear(); +} + +JTexture * WCachedTexture::Actual() +{ + return texture; +} + +bool WCachedTexture::isLocked() +{ + if (locks != WRES_UNLOCKED) return true; + + for (vector::iterator it = trackedQuads.begin(); it != trackedQuads.end(); it++) + { + if ((*it)->isLocked()) return true; } - tq->quad = quad; - if (allocated) trackedQuads.push_back(tq); + return false; +} + +bool WCachedTexture::ReleaseQuad(JQuad* quad) +{ + if (quad == NULL) return false; + + WTrackedQuad * tq = NULL; + vector::iterator nit; + for (vector::iterator it = trackedQuads.begin(); it != trackedQuads.end(); it = nit) + { + nit = it; + nit++; + if ((*it) && (*it)->quad == quad) + { + tq = (*it); + tq->unlock(); + + if (!tq->isLocked()) + { + SAFE_DELETE(tq); + trackedQuads.erase(it); + } + + return true; //Returns true when found. + } + } + return false; +} + +WTrackedQuad * WCachedTexture::GetTrackedQuad(float offX, float offY, float width, float height, string resname) +{ + if (!texture) return NULL; + + bool allocated = false; + WTrackedQuad * tq = NULL; + JQuad * quad = NULL; + + vector::iterator it; + + if (width == 0.0f || width > static_cast (texture->mWidth)) width = static_cast (texture->mWidth); + if (height == 0.0f || height > static_cast (texture->mHeight)) height = static_cast (texture->mHeight); + + for (it = trackedQuads.begin(); it != trackedQuads.end(); it++) + { + if ((*it) && (*it)->resname == resname) + { + tq = (*it); + break; + } + } + + if (!tq) + { + allocated = true; + tq = NEW WTrackedQuad(resname); + if (!tq) return NULL; + } + + quad = tq->quad; + + if (!quad) + { + quad = NEW JQuad(texture, offX, offY, width, height); + /* + There's a risk this erases the texture calling the quad creation.... Erwan 2010/03/13 + if(!quad) { + //Probably out of memory. Try again. + resources.Cleanup(); + quad = NEW JQuad(texture,offX,offY,width,height); + } + */ + if (!quad) + { + if (allocated && tq) + SAFE_DELETE(tq); + fprintf(stderr, "WCACHEDRESOURCE:GetTrackedQuad - Quad is null\n"); + return NULL; //Probably a crash. + } + + tq->quad = quad; + if (allocated) trackedQuads.push_back(tq); + return tq; + } + + //Update JQ's values to what we called this with. + quad->SetTextureRect(offX, offY, width, height); return tq; - } - - //Update JQ's values to what we called this with. - quad->SetTextureRect(offX,offY,width,height); - return tq; } -JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float height,string resname){ - WTrackedQuad * tq = GetTrackedQuad(offX,offY,width,height,resname); +JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float height, string resname) +{ + WTrackedQuad * tq = GetTrackedQuad(offX, offY, width, height, resname); - if(tq) - return tq->quad; + if (tq) return tq->quad; - return NULL; + return NULL; } +JQuad * WCachedTexture::GetQuad(string resname) +{ + vector::iterator it; -JQuad * WCachedTexture::GetQuad(string resname){ - vector::iterator it; + for (it = trackedQuads.begin(); it != trackedQuads.end(); it++) + { + if ((*it) && (*it)->resname == resname) + { + return (*it)->quad; + } + } - for(it = trackedQuads.begin();it!=trackedQuads.end();it++){ - if((*it) && (*it)->resname == resname){ - return (*it)->quad; - } - } - - return NULL; + return NULL; } -JQuad * WCachedTexture::GetCard(float offX, float offY, float width, float height, string resname){ - JQuad * jq = GetQuad(offX,offY,width,height,resname); - if(jq) - jq->SetHotSpot(static_cast(jq->mTex->mWidth / 2), static_cast(jq->mTex->mHeight / 2)); - - return jq; +JQuad * WCachedTexture::GetCard(float offX, float offY, float width, float height, string resname) +{ + JQuad * jq = GetQuad(offX, offY, width, height, resname); + if (jq) jq->SetHotSpot(static_cast (jq->mTex->mWidth / 2), static_cast (jq->mTex->mHeight / 2)); + + return jq; } -unsigned long WCachedTexture::size(){ - if(!texture) return 0; +unsigned long WCachedTexture::size() +{ + if (!texture) return 0; - unsigned int pixel_size = 4; + unsigned int pixel_size = 4; #if defined WIN32 || defined LINUX #else - pixel_size = JRenderer::GetInstance()->PixelSize(texture->mTextureFormat); + pixel_size = JRenderer::GetInstance()->PixelSize(texture->mTextureFormat); #endif - return texture->mTexHeight*texture->mTexWidth*pixel_size; + return texture->mTexHeight * texture->mTexWidth * pixel_size; } -bool WCachedTexture::isGood(){ - return (texture != NULL); +bool WCachedTexture::isGood() +{ + return (texture != NULL); } -void WCachedTexture::Refresh(){ - int error = 0; - JTexture* old = texture; - texture = NULL; +void WCachedTexture::Refresh() +{ + int error = 0; + JTexture* old = texture; + texture = NULL; - if(!Attempt(mFilename,loadedMode, error)) + if (!Attempt(mFilename, loadedMode, error)) SAFE_DELETE(texture); - if(!texture) - texture = old; - else - SAFE_DELETE(old); - - for(vector::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){ - if((*it) && (*it)->quad) - (*it)->quad->mTex = texture; - } -} - -bool WCachedTexture::Attempt(string filename, int submode, int & error){ - mFilename = filename; - int format = TEXTURE_FORMAT; - loadedMode = submode; - string realname; - - //Form correct filename. - if(submode & TEXTURE_SUB_EXACT) - realname = filename; - else if(submode & TEXTURE_SUB_CARD){ - if(submode & TEXTURE_SUB_THUMB){ - for(string::size_type i= 0;i < filename.size();i++){ - if(filename[i] == '\\' || filename[i] == '/'){ - filename.insert(i+1,"thumbnails/"); - break; - } - } - - } - realname = resources.cardFile(filename); - } - else{ - if(submode & TEXTURE_SUB_THUMB) - filename.insert(0,"thumbnails/"); - - if(submode & TEXTURE_SUB_AVATAR) - realname = resources.avatarFile(filename); + if (!texture) + texture = old; else - realname = resources.graphicsFile(filename); - } + SAFE_DELETE(old); - //Apply pixel mode - if(submode & TEXTURE_SUB_5551) - format = GU_PSM_5551; + for (vector::iterator it = trackedQuads.begin(); it != trackedQuads.end(); it++) + { + if ((*it) && (*it)->quad) (*it)->quad->mTex = texture; + } +} - if(!realname.size()){ - error = CACHE_ERROR_404; - return false; - } +bool WCachedTexture::Attempt(string filename, int submode, int & error) +{ + mFilename = filename; + int format = TEXTURE_FORMAT; + loadedMode = submode; + string realname; - texture = JRenderer::GetInstance()->LoadTexture(realname.c_str(),TEX_TYPE_USE_VRAM,format); - - //Failure. - if(!texture){ - error = CACHE_ERROR_BAD; - if(!fileExists(realname.c_str())) - error = CACHE_ERROR_404; - return false; - } + //Form correct filename. + if (submode & TEXTURE_SUB_EXACT) + realname = filename; + else if (submode & TEXTURE_SUB_CARD) + { + if (submode & TEXTURE_SUB_THUMB) + { + for (string::size_type i = 0; i < filename.size(); i++) + { + if (filename[i] == '\\' || filename[i] == '/') + { + filename.insert(i + 1, "thumbnails/"); + break; + } + } - //Failure of a different sort. - if(texture->mTexId == INVALID_MTEX){ - SAFE_DELETE(texture); - error = CACHE_ERROR_BAD; - return false; - } - - error = CACHE_ERROR_NONE; - return true; -} + } + realname = resources.cardFile(filename); + } + else + { + if (submode & TEXTURE_SUB_THUMB) filename.insert(0, "thumbnails/"); + + if (submode & TEXTURE_SUB_AVATAR) + realname = resources.avatarFile(filename); + else + realname = resources.graphicsFile(filename); + } + + //Apply pixel mode + if (submode & TEXTURE_SUB_5551) format = GU_PSM_5551; + + if (!realname.size()) + { + error = CACHE_ERROR_404; + return false; + } + + texture = JRenderer::GetInstance()->LoadTexture(realname.c_str(), TEX_TYPE_USE_VRAM, format); + + //Failure. + if (!texture) + { + error = CACHE_ERROR_BAD; + if (!fileExists(realname.c_str())) error = CACHE_ERROR_404; + return false; + } + + //Failure of a different sort. + if (texture->mTexId == INVALID_MTEX) + { + SAFE_DELETE(texture); + error = CACHE_ERROR_BAD; + return false; + } + + error = CACHE_ERROR_NONE; + return true; +} //WCachedSample -WCachedSample::WCachedSample(){ - sample = NULL; +WCachedSample::WCachedSample() +{ + sample = NULL; } -WCachedSample::~WCachedSample(){ - SAFE_DELETE(sample); -} - -JSample * WCachedSample::Actual(){ - return sample; -} - - -unsigned long WCachedSample::size(){ - if(!sample || !sample->mSample) - return 0; - return sample->fileSize(); -} - -bool WCachedSample::isGood(){ - if(!sample || !sample->mSample) - return false; - - return true; -} -void WCachedSample::Refresh(){ - return; -} - -bool WCachedSample::Attempt(string filename, int submode, int & error){ - loadedMode = submode; - - sample = JSoundSystem::GetInstance()->LoadSample(resources.sfxFile(filename).c_str()); - - if(!isGood()){ +WCachedSample::~WCachedSample() +{ SAFE_DELETE(sample); - if(!fileExists(filename.c_str())) - error = CACHE_ERROR_404; - else - error = CACHE_ERROR_BAD; - return false; - } +} - error = CACHE_ERROR_NONE; - return true; +JSample * WCachedSample::Actual() +{ + return sample; +} + +unsigned long WCachedSample::size() +{ + if (!sample || !sample->mSample) return 0; + return sample->fileSize(); +} + +bool WCachedSample::isGood() +{ + if (!sample || !sample->mSample) return false; + + return true; +} + +void WCachedSample::Refresh() +{ + return; +} + +bool WCachedSample::Attempt(string filename, int submode, int & error) +{ + loadedMode = submode; + + sample = JSoundSystem::GetInstance()->LoadSample(resources.sfxFile(filename).c_str()); + + if (!isGood()) + { + SAFE_DELETE(sample); + if (!fileExists(filename.c_str())) + error = CACHE_ERROR_404; + else + error = CACHE_ERROR_BAD; + return false; + } + + error = CACHE_ERROR_NONE; + return true; } //WCachedParticles -bool WCachedParticles::isGood(){ - if(!particles) - return false; - return true; +bool WCachedParticles::isGood() +{ + if (!particles) return false; + return true; } -unsigned long WCachedParticles::size(){ - if(!particles) - return 0; //Sizeof(pointer) - return sizeof(hgeParticleSystemInfo); +unsigned long WCachedParticles::size() +{ + if (!particles) return 0; //Sizeof(pointer) + + return sizeof(hgeParticleSystemInfo); } //Only effects future particle systems, of course. -void WCachedParticles::Refresh(){ - hgeParticleSystemInfo * old = particles; +void WCachedParticles::Refresh() +{ + hgeParticleSystemInfo * old = particles; - int error = 0; - Attempt(mFilename,loadedMode,error); + int error = 0; + Attempt(mFilename, loadedMode, error); + + if (isGood()) + SAFE_DELETE(old); + else + { + SAFE_DELETE(particles); + particles = old; + } + + return; +} + +bool WCachedParticles::Attempt(string filename, int submode, int & error) +{ + + JFileSystem* fileSys = JFileSystem::GetInstance(); + + if (!fileSys->OpenFile(resources.graphicsFile(filename))) + { + error = CACHE_ERROR_404; + return false; + } - if(isGood()) - SAFE_DELETE(old); - else{ SAFE_DELETE(particles); - particles = old; - } - return; + particles = NEW hgeParticleSystemInfo; + // We Skip reading the pointer as it may be larger than 4 bytes in the structure + void *dummyPointer; + fileSys->ReadFile(&dummyPointer, 4); + // we're actually trying to read more than the file size now, but it's no problem. + // Note that this fix is only to avoid the largest problems, filling a structure + // by directly reading a file, is really a bad idea ... + fileSys->ReadFile(&(particles->nEmission), sizeof(hgeParticleSystemInfo)); + fileSys->CloseFile(); + + particles->sprite = NULL; + error = CACHE_ERROR_NONE; + return true; } -bool WCachedParticles::Attempt(string filename, int submode, int & error){ - - JFileSystem* fileSys = JFileSystem::GetInstance(); - - if(!fileSys->OpenFile(resources.graphicsFile(filename))){ - error = CACHE_ERROR_404; - return false; - } - - SAFE_DELETE(particles); - - particles = NEW hgeParticleSystemInfo; - // We Skip reading the pointer as it may be larger than 4 bytes in the structure - void *dummyPointer; - fileSys->ReadFile(&dummyPointer, 4); - // we're actually trying to read more than the file size now, but it's no problem. - // Note that this fix is only to avoid the largest problems, filling a structure - // by directly reading a file, is really a bad idea ... - fileSys->ReadFile(&(particles->nEmission), sizeof(hgeParticleSystemInfo)); - fileSys->CloseFile(); - - particles->sprite=NULL; - error = CACHE_ERROR_NONE; - return true; +hgeParticleSystemInfo * WCachedParticles::Actual() +{ + return particles; } -hgeParticleSystemInfo * WCachedParticles::Actual(){ - return particles; +WCachedParticles::WCachedParticles() +{ + particles = NULL; } - -WCachedParticles::WCachedParticles(){ - particles = NULL; -} -WCachedParticles::~WCachedParticles(){ - SAFE_DELETE(particles); +WCachedParticles::~WCachedParticles() +{ + SAFE_DELETE(particles); } //WTrackedQuad -unsigned long WTrackedQuad::size() { - return sizeof(JQuad); +unsigned long WTrackedQuad::size() +{ + return sizeof(JQuad); } -bool WTrackedQuad::isGood(){ - return (quad != NULL); + +bool WTrackedQuad::isGood() +{ + return (quad != NULL); } -WTrackedQuad::WTrackedQuad(string _resname) { - quad = NULL; resname = _resname; + +WTrackedQuad::WTrackedQuad(string _resname) +{ + quad = NULL; + resname = _resname; } -WTrackedQuad::~WTrackedQuad() { - if(quad) SAFE_DELETE(quad); + +WTrackedQuad::~WTrackedQuad() +{ + if (quad) + SAFE_DELETE(quad); } diff --git a/projects/mtg/src/WDataSrc.cpp b/projects/mtg/src/WDataSrc.cpp index fa6d8ccaf..e004cea88 100644 --- a/projects/mtg/src/WDataSrc.cpp +++ b/projects/mtg/src/WDataSrc.cpp @@ -7,591 +7,706 @@ #include "Subtypes.h" //WSyncable -bool WSyncable::Hook(WSyncable* s){ - if(hooked) - return false; - hooked = s; - return true; +bool WSyncable::Hook(WSyncable* s) +{ + if (hooked) return false; + hooked = s; + return true; } -int WSyncable::getPos(){ - if(hooked) - return hooked->getPos()+currentPos; - return currentPos; + +int WSyncable::getPos() +{ + if (hooked) return hooked->getPos() + currentPos; + return currentPos; } -bool WSyncable::next(){ - if(hooked) - return hooked->next(); - ++currentPos; - return true; + +bool WSyncable::next() +{ + if (hooked) return hooked->next(); + ++currentPos; + return true; } -bool WSyncable::prev(){ - if(hooked) - return hooked->prev(); - --currentPos; - return true; + +bool WSyncable::prev() +{ + if (hooked) return hooked->prev(); + --currentPos; + return true; } //WSrcImage -JQuad * WSrcImage::getImage( int offset){ - return resources.RetrieveTempQuad(filename); +JQuad * WSrcImage::getImage(int offset) +{ + return resources.RetrieveTempQuad(filename); } -WSrcImage::WSrcImage(string s){ - filename = s; +WSrcImage::WSrcImage(string s) +{ + filename = s; } + //WSrcCards -WSrcCards::WSrcCards(float delay){ - mDelay = delay; - mLastInput = 0; - currentPos = 0; - filtersRoot=NULL; +WSrcCards::WSrcCards(float delay) +{ + mDelay = delay; + mLastInput = 0; + currentPos = 0; + filtersRoot = NULL; } -JQuad * WSrcCards::getImage( int offset){ + +JQuad * WSrcCards::getImage(int offset) +{ #if defined WIN32 || defined LINUX //Loading delay only on PSP. #else - if(mDelay && mLastInput < mDelay){ - return resources.RetrieveCard(getCard(offset),RETRIEVE_EXISTING); - } + if (mDelay && mLastInput < mDelay) + { + return resources.RetrieveCard(getCard(offset), RETRIEVE_EXISTING); + } #endif - return resources.RetrieveCard(getCard(offset)); -} -JQuad * WSrcCards::getThumb( int offset){ - return resources.RetrieveCard(getCard(offset),RETRIEVE_THUMB); -} -WSrcCards::~WSrcCards(){ - clearFilters(); - cards.clear(); -} -void WSrcCards::bakeFilters(){ - vector temp; - - setOffset(0); - for(int t=0;tisMatch(c); +JQuad * WSrcCards::getThumb(int offset) +{ + return resources.RetrieveCard(getCard(offset), RETRIEVE_THUMB); } -int WSrcCards::Size(bool all){ - if(!all && filtersRoot) - return (int) validated.size(); - return (int) cards.size(); -} -MTGCard * WSrcCards::getCard(int offset, bool ignore){ - int oldpos; - int size = (int) cards.size(); - MTGCard * c = NULL; - if(!ignore && filtersRoot) - size = (int) validated.size(); - - if(!size) - return NULL; - oldpos = currentPos; - if(offset != 0) - currentPos += offset; - while(currentPos < 0) - currentPos = size+currentPos; - currentPos = currentPos % size; - - if(!ignore && filtersRoot) - c = cards[validated[currentPos]]; - else - c = cards[currentPos]; - currentPos = oldpos; - return c; +WSrcCards::~WSrcCards() +{ + clearFilters(); + cards.clear(); } -int WSrcCards::loadMatches(MTGAllCards* ac){ - map::iterator it; - int count = 0; - if(!ac) + +void WSrcCards::bakeFilters() +{ + vector temp; + + setOffset(0); + for (int t = 0; t < Size(); t++) + { + temp.push_back(getCard(t)); + } + setOffset(0); + cards.clear(); + cards.swap(temp); + clearFilters(); + return; +} + +bool WSrcCards::matchesFilters(MTGCard * c) +{ + if (!c) return false; + if (!filtersRoot) return true; + return filtersRoot->isMatch(c); +} + +int WSrcCards::Size(bool all) +{ + if (!all && filtersRoot) return (int) validated.size(); + return (int) cards.size(); +} + +MTGCard * WSrcCards::getCard(int offset, bool ignore) +{ + int oldpos; + int size = (int) cards.size(); + MTGCard * c = NULL; + if (!ignore && filtersRoot) size = (int) validated.size(); + + if (!size) return NULL; + + oldpos = currentPos; + if (offset != 0) currentPos += offset; + while (currentPos < 0) + currentPos = size + currentPos; + currentPos = currentPos % size; + + if (!ignore && filtersRoot) + c = cards[validated[currentPos]]; + else + c = cards[currentPos]; + currentPos = oldpos; + return c; +} + +int WSrcCards::loadMatches(MTGAllCards* ac) +{ + map::iterator it; + int count = 0; + if (!ac) return count; + + for (it = ac->collection.begin(); it != ac->collection.end(); it++) + { + if (it->second && (matchesFilters(it->second))) + { + cards.push_back(it->second); + count++; + } + } + validate(); return count; - - for(it=ac->collection.begin();it!=ac->collection.end();it++){ - if(it->second && (matchesFilters(it->second))){ - cards.push_back(it->second); - count++; - } - } - validate(); - return count; } -int WSrcCards::loadMatches(MTGDeck * deck){ - map::iterator it; - int count = 0; - if(!deck) + +int WSrcCards::loadMatches(MTGDeck * deck) +{ + map::iterator it; + int count = 0; + if (!deck) return count; + for (it = deck->cards.begin(); it != deck->cards.end(); it++) + { + MTGCard * c = deck->getCardById(it->first); + if (c && (matchesFilters(c))) + { + cards.push_back(c); + count++; + } + } + validate(); return count; - for(it=deck->cards.begin();it!=deck->cards.end();it++){ - MTGCard * c = deck->getCardById(it->first); - if(c && (matchesFilters(c))){ - cards.push_back(c); - count++; - } - } - validate(); - return count; } -int WSrcCards::loadMatches(WSrcCards* src, bool all){ - int count = 0; - if(!src) + +int WSrcCards::loadMatches(WSrcCards* src, bool all) +{ + int count = 0; + if (!src) return count; + + MTGCard * c = NULL; + size_t t = 0; + int oldp = src->getOffset(); + src->setOffset(0); + for (int t = 0; t < src->Size(all); t++) + { + c = src->getCard(t, all); + if (matchesFilters(c)) + { + cards.push_back(c); + count++; + } + } + src->setOffset(oldp); + validate(); return count; +} - MTGCard * c = NULL; - size_t t = 0; - int oldp = src->getOffset(); - src->setOffset(0); - for(int t=0;tSize(all);t++){ - c = src->getCard(t,all); - if(matchesFilters(c)){ - cards.push_back(c); - count++; +int WSrcCards::addRandomCards(MTGDeck * i, int howmany) +{ + if (!cards.size() || (filtersRoot && !validated.size())) return howmany; + for (int x = 0; x < howmany; x++) + { + if (validated.size()) + { + size_t pos = rand() % validated.size(); + MTGCard * c = cards[validated[pos]]; + i->add(c); + } + else + { + size_t pos = rand() % cards.size(); + i->add(cards[pos]); + } } - } - src->setOffset(oldp); - validate(); - return count; + return 0; } -int WSrcCards::addRandomCards(MTGDeck * i, int howmany){ - if(!cards.size() || (filtersRoot && !validated.size())) - return howmany; - for(int x=0;xadd(c); + +int WSrcCards::addToDeck(MTGDeck * i, int num) +{ + int oldpos = getOffset(); + int added = 0; + int cycles = 0; + + if (!i) + { + if (num < 0) return 0; + return num; } - else{ - size_t pos = rand() % cards.size(); - i->add(cards[pos]); + + setOffset(0); + if (num < 0) + { //Add it all; + MTGCard * c; + for (;;) + { + c = getCard(); + if (!c || !next()) break; + i->add(c); + } } - } - return 0; + else + while (added < num) + { + MTGCard * c = getCard(); + if (!next() || !c) + { + if (++cycles == WSrcCards::MAX_CYCLES) + { //Abort the search, too many cycles. + setOffset(oldpos); + return num - added; + } + setOffset(0); + continue; + } + else + { + i->add(c); + added++; + } + } + setOffset(oldpos); + return 0; } -int WSrcCards::addToDeck(MTGDeck * i, int num){ - int oldpos = getOffset(); - int added = 0; - int cycles = 0; +bool WSrcCards::next() +{ + int oldpos = currentPos; + bool bMatch = true; + int size = (int) cards.size(); + if (filtersRoot) size = (int) validated.size(); + if (currentPos + 1 >= size) return false; + currentPos++; + return true; +} - if(!i){ - if(num < 0) - return 0; - return num; - } +bool WSrcCards::prev() +{ + int oldpos = currentPos; + bool bMatch = true; + if (currentPos == 0) return false; - setOffset(0); - if(num < 0){ //Add it all; - MTGCard * c; - for(;;){ - c = getCard(); - if(!c || !next()) - break; - i->add(c); + currentPos--; + return true; +} + +bool WSrcCards::setOffset(int pos) +{ + if (pos < 0 || pos >= (int) cards.size()) return false; + + currentPos = pos; + if (!matchesFilters(cards[currentPos])) return next(); + + return true; +} + +void WSrcCards::Shuffle() +{ + vector a; + MTGCard * temp; + vector::iterator k; + + while (cards.size()) + { + k = cards.begin(); + k += rand() % cards.size(); + temp = *k; + cards.erase(k); + a.push_back(temp); } - }else while(added < num){ - MTGCard * c = getCard(); - if(!next() || !c){ - if(++cycles == WSrcCards::MAX_CYCLES){ //Abort the search, too many cycles. - setOffset(oldpos); - return num - added; - } - setOffset(0); - continue; - }else{ - i->add(c); - added++; - } - } - setOffset(oldpos); - return 0; -} -bool WSrcCards::next(){ - int oldpos = currentPos; - bool bMatch = true; - int size = (int)cards.size(); - if(filtersRoot) - size = (int)validated.size(); - if(currentPos+1 >= size) - return false; - currentPos++; - return true; -} - -bool WSrcCards::prev(){ - int oldpos = currentPos; - bool bMatch = true; - if(currentPos == 0) - return false; - - currentPos--; - return true; -} - -bool WSrcCards::setOffset(int pos){ - if(pos < 0 || pos >= (int) cards.size()) - return false; - - currentPos = pos; - if(!matchesFilters(cards[currentPos])) - return next(); - - return true; -} -void WSrcCards::Shuffle(){ - vector a; - MTGCard * temp; - vector::iterator k; - - while(cards.size()){ - k = cards.begin(); - k += rand() % cards.size(); - temp = *k; - cards.erase(k); - a.push_back(temp); - } #if defined WIN32 || defined LINUX //PC performs a double shuffle for less streaking. - while(a.size()){ - k = a.begin(); - k += rand() % a.size(); - temp = *k; - a.erase(k); - cards.push_back(temp); - } -#else //PSP does a straight swap for speed. - cards.swap(a); -#endif - validate(); -} -void WSrcCards::validate(){ - validated.clear(); - updateCounts(); - if(!filtersRoot) return; - for(size_t t=0;tgetId() == mtgid){ - currentPos = (int) t; - return matchesFilters(cards[currentPos]); + while(a.size()) + { + k = a.begin(); + k += rand() % a.size(); + temp = *k; + a.erase(k); + cards.push_back(temp); } - } - return false; -} -bool WSrcCards::isEmptySet(WCardFilter * f){ - size_t max = cards.size(); - if(validated.size()) max = validated.size(); - if(!f) return (max > 0); - for(size_t t=0;tisMatch(cards[validated[t]])) - return false; - }else if(f->isMatch(cards[t])) - return false; - } - return true; +#else //PSP does a straight swap for speed. + cards.swap(a); +#endif + validate(); } -void WSrcCards::addFilter(WCardFilter * f) { - if(filtersRoot == NULL) - filtersRoot = f; - else - filtersRoot = NEW WCFilterAND(f,filtersRoot); - validate(); - currentPos = 0; +void WSrcCards::validate() +{ + validated.clear(); + updateCounts(); + if (!filtersRoot) return; + for (size_t t = 0; t < cards.size(); t++) + { + if (matchesFilters(cards[t])) validated.push_back(t); + } } -float WSrcCards::filterFee(){ - if(filtersRoot) - return filtersRoot->filterFee(); - return 0; -}; -void WSrcCards::clearFilters() { - SAFE_DELETE(filtersRoot); - validated.clear(); + +bool WSrcCards::thisCard(int mtgid) +{ + for (size_t t = 0; t < cards.size(); t++) + { + if (cards[t] && cards[t]->getId() == mtgid) + { + currentPos = (int) t; + return matchesFilters(cards[currentPos]); + } + } + return false; } -WCardFilter* WSrcCards::unhookFilters(){ - WCardFilter* temp = filtersRoot; - filtersRoot = NULL; - clearFilters(); - return temp; + +bool WSrcCards::isEmptySet(WCardFilter * f) +{ + size_t max = cards.size(); + if (validated.size()) max = validated.size(); + if (!f) return (max > 0); + for (size_t t = 0; t < max; t++) + { + if (validated.size()) + { + if (f->isMatch(cards[validated[t]])) return false; + } + else if (f->isMatch(cards[t])) return false; + } + return true; } -void WSrcCards::Sort(int method){ - switch(method){ + +void WSrcCards::addFilter(WCardFilter * f) +{ + if (filtersRoot == NULL) + filtersRoot = f; + else + filtersRoot = NEW WCFilterAND(f, filtersRoot); + validate(); + currentPos = 0; +} +float WSrcCards::filterFee() +{ + if (filtersRoot) return filtersRoot->filterFee(); + return 0; +} + +void WSrcCards::clearFilters() +{ + SAFE_DELETE(filtersRoot); + validated.clear(); +} +WCardFilter* WSrcCards::unhookFilters() +{ + WCardFilter* temp = filtersRoot; + filtersRoot = NULL; + clearFilters(); + return temp; +} + +void WSrcCards::Sort(int method) +{ + switch (method) + { case WSrcCards::SORT_COLLECTOR: - std::sort(cards.begin(),cards.end(),WCSortCollector()); - break; + std::sort(cards.begin(), cards.end(), WCSortCollector()); + break; case WSrcCards::SORT_RARITY: - std::sort(cards.begin(),cards.end(),WCSortRarity()); - break; + std::sort(cards.begin(), cards.end(), WCSortRarity()); + break; case WSrcCards::SORT_ALPHA: default: - std::sort(cards.begin(),cards.end(),WCSortAlpha()); - break; - } - validate(); + std::sort(cards.begin(), cards.end(), WCSortAlpha()); + break; + } + validate(); } + //WSrcUnlockedCards -WSrcUnlockedCards::WSrcUnlockedCards(float delay): WSrcCards(delay){ - MTGAllCards * ac = GameApp::collection; - map::iterator it; +WSrcUnlockedCards::WSrcUnlockedCards(float delay) : + WSrcCards(delay) +{ + MTGAllCards * ac = GameApp::collection; + map::iterator it; - char * unlocked = NULL; - unlocked = (char *)calloc(setlist.size(),sizeof(char)); - //Figure out which sets are available. - for (int i = 0; i < setlist.size(); i++){ - unlocked[i] = options[Options::optionSet(i)].number; - } + char * unlocked = NULL; + unlocked = (char *) calloc(setlist.size(), sizeof(char)); + //Figure out which sets are available. + for (int i = 0; i < setlist.size(); i++) + { + unlocked[i] = options[Options::optionSet(i)].number; + } - for(it=ac->collection.begin();it!=ac->collection.end();it++){ - if(it->second && unlocked[it->second->setId]) - cards.push_back(it->second); - } - if(unlocked){ - free(unlocked); - unlocked = NULL; - } + for (it = ac->collection.begin(); it != ac->collection.end(); it++) + { + if (it->second && unlocked[it->second->setId]) cards.push_back(it->second); + } + if (unlocked) + { + free(unlocked); + unlocked = NULL; + } - - if(cards.size()){ - Shuffle(); - currentPos = 0; - } + if (cards.size()) + { + Shuffle(); + currentPos = 0; + } } //WSrcDeck -int WSrcDeck::loadMatches(MTGDeck * deck){ - map::iterator it; - int count = 0; - if(!deck) - return count; - for(it=deck->cards.begin();it!=deck->cards.end();it++){ - MTGCard * c = deck->getCardById(it->first); - if(c && matchesFilters(c)){ - Add(c,it->second); - count++; - } - } - validate(); - return count; -} -void WSrcDeck::updateCounts(){ - vector::iterator it; - map::iterator ccount; - clearCounts(); - for(it=cards.begin();it!=cards.end();it++){ - ccount = copies.find((*it)->getMTGId()); - if(ccount == copies.end()) continue; - addCount((*it),ccount->second); - } -} -void WSrcDeck::clearCounts(){ - counts[UNFILTERED_MIN_COPIES] = -1; - counts[UNFILTERED_MAX_COPIES] = 0; - for(int i=0;idata) return; - map::iterator cp = copies.find(c->getMTGId()); - - if(matchesFilters(c)){ - counts[FILTERED_COPIES]+=qty; - if(qty > 0 && cp != copies.end() && (*cp).second == qty ) counts[FILTERED_UNIQUE]++; - else if(qty < 0 && (cp == copies.end() || (*cp).second == 0) ) counts[FILTERED_UNIQUE]--; - } - counts[UNFILTERED_COPIES] += qty; - if(qty > 0 && cp != copies.end() && (*cp).second == qty ) counts[UNFILTERED_UNIQUE]++; - else if(qty < 0 && (cp == copies.end() || (*cp).second == 0) ) counts[UNFILTERED_UNIQUE]--; - for(int i=Constants::MTG_COLOR_ARTIFACT;i<=Constants::MTG_COLOR_LAND;i++) - if (c->data->hasColor(i)) counts[i]+= qty; - if(counts[UNFILTERED_MIN_COPIES] < 0 || qty < counts[UNFILTERED_MIN_COPIES]) counts[UNFILTERED_MIN_COPIES] = qty; - if(qty > counts[UNFILTERED_MAX_COPIES]) counts[UNFILTERED_MAX_COPIES] = qty; -} -int WSrcDeck::Add(MTGCard * c, int quantity){ - if(!c) return 0; - if(copies.find(c->getMTGId()) == copies.end()){ - cards.push_back(c); - } - copies[c->getMTGId()] += quantity; - addCount(c,quantity); - return 1; -} - -int WSrcDeck::Remove(MTGCard * c, int quantity, bool erase){ - if(!c) return 0; - map::iterator it = copies.find(c->getMTGId()); - if(it == copies.end()) return 0; - int amt = it->second; - if(amt < quantity) - return 0; - amt -= quantity; - it->second = amt; - if(erase && amt == 0){ - copies.erase(it); - vector::iterator i = find(cards.begin(),cards.end(),c); - if(i != cards.end()) - cards.erase(i); - } - addCount(c,-quantity); - return 1; -} - -void WSrcDeck::Rebuild(MTGDeck * d){ - d->removeAll(); - map::iterator it; - for ( it=copies.begin() ; it != copies.end(); it++ ){ - for (int i = 0; i < it->second; i++){ - d->add(it->first); - } - } -} - -int WSrcDeck::count(MTGCard * c){ - if(!c) - return counts[UNFILTERED_COPIES]; - if(copies.find(c->getMTGId()) == copies.end()) - return 0; - return copies[c->getMTGId()]; -} - -int WSrcDeck::countByName(MTGCard * card, bool editions){ - string name = card->data->getLCName(); - int total = 0; - vector::iterator it; - for(it = cards.begin();it!=cards.end();it++){ - if(*it && (*it)->data->getLCName() == name){ - if(editions) - total++; - else{ - map::iterator mi = copies.find((*it)->getMTGId()); - if(mi != copies.end()) - total += mi->second; - } - } - } - return total; -} -int WSrcDeck::getCount(int count){ - if(count < 0 || count >=MAX_COUNTS) - return counts[UNFILTERED_COPIES]; - return counts[count]; -} -int WSrcDeck::totalPrice(){ - int total = 0; - PriceList * pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(),GameApp::collection); - map::iterator it; - for ( it=copies.begin() ; it != copies.end(); it++ ){ - int nb = it->second; - if (nb) total += pricelist->getPrice(it->first); - } - SAFE_DELETE(pricelist); - return total; -} -//WSrcDeckViewer -WSrcDeckViewer::WSrcDeckViewer(WSrcCards * _active, WSrcCards * _inactive): WSrcCards(0.2f) { - active = _active; - inactive = _inactive; -} - -void WSrcDeckViewer::swapSrc(){ - WSrcCards * temp = active; - active = inactive; - inactive = temp; -} -WSrcDeckViewer::~WSrcDeckViewer(){ - //Do nothing. -} -//Sorting methods: -int WCSortRarity::rareToInt(char r){ - switch(r){ - default: case Constants::RARITY_T: return 0; - case Constants::RARITY_L: return 1; - case Constants::RARITY_C: return 2; - case Constants::RARITY_U: return 3; - case Constants::RARITY_R: return 4; - case Constants::RARITY_M: return 5; - case Constants::RARITY_S: return 6; - } -} -bool WCSortRarity::operator()(const MTGCard*l, const MTGCard*r){ - if(!l || !r || !l->data || !r->data) - return false; - return (rareToInt(l->getRarity()) < rareToInt(r->getRarity())); -} -bool WCSortAlpha::operator()(const MTGCard*l, const MTGCard*r){ - if(!l || !r || !l->data || !r->data) - return false; - string ln = l->data->getLCName(); - string rn = r->data->getLCName(); - if(ln == rn) - return l->getMTGId() < r->getMTGId(); - return (ln < rn); -} -bool WCSortCollector::operator()(const MTGCard*l, const MTGCard*r){ - if(!l || !r || !l->data || !r->data) - return false; - - if(l->setId != r->setId) - return (l->setId < r->setId); - - int lc, rc; - lc = l->data->countColors(); rc = r->data->countColors(); - if(lc == 0) lc = 999; - if(rc == 0) rc = 999; - - int isW = (int)l->data->hasColor(Constants::MTG_COLOR_WHITE) - (int) r->data->hasColor(Constants::MTG_COLOR_WHITE); - int isU = (int)l->data->hasColor(Constants::MTG_COLOR_BLUE) - (int) r->data->hasColor(Constants::MTG_COLOR_BLUE); - int isB = (int)l->data->hasColor(Constants::MTG_COLOR_BLACK) - (int) r->data->hasColor(Constants::MTG_COLOR_BLACK); - int isR = (int)l->data->hasColor(Constants::MTG_COLOR_RED) - (int) r->data->hasColor(Constants::MTG_COLOR_RED); - int isG = (int)l->data->hasColor(Constants::MTG_COLOR_GREEN) - (int) r->data->hasColor(Constants::MTG_COLOR_GREEN); - int isArt = (int)l->data->hasType(Subtypes::TYPE_ARTIFACT) - (int) r->data->hasType(Subtypes::TYPE_ARTIFACT); - int isLand = (int)l->data->hasType(Subtypes::TYPE_LAND) - (int) r->data->hasType(Subtypes::TYPE_LAND); - - //Nested if hell. TODO: Farm these out to their own objects as a user-defined filter/sort system. - if(!isLand){ - int isBasic = (int)l->data->hasType("Basic") - (int) r->data->hasType("Basic"); - if(!isBasic){ - if(!isArt){ - if(lc == rc){ - if(!isG){ - if(!isR){ - if(!isB){ - if(!isU){ - if(!isW){ - string ln = l->data->getLCName(); - string rn = r->data->getLCName(); - if(ln.substr(0,4) == "the ") - ln = ln.substr(4); - if(rn.substr(0,4) == "the ") - rn = rn.substr(4); - return (ln < rn); - } - return (isW < 0); - } - return (isU < 0); - } - return (isB < 0); - } - return (isR < 0); - } - return (isG < 0); +int WSrcDeck::loadMatches(MTGDeck * deck) +{ + map::iterator it; + int count = 0; + if (!deck) return count; + for (it = deck->cards.begin(); it != deck->cards.end(); it++) + { + MTGCard * c = deck->getCardById(it->first); + if (c && matchesFilters(c)) + { + Add(c, it->second); + count++; } - return (lc < rc); - } - return (isArt < 0); } - else return(isBasic < 0); - } - return (isLand < 0); -} \ No newline at end of file + validate(); + return count; +} + +void WSrcDeck::updateCounts() +{ + vector::iterator it; + map::iterator ccount; + clearCounts(); + for (it = cards.begin(); it != cards.end(); it++) + { + ccount = copies.find((*it)->getMTGId()); + if (ccount == copies.end()) continue; + addCount((*it), ccount->second); + } +} + +void WSrcDeck::clearCounts() +{ + counts[UNFILTERED_MIN_COPIES] = -1; + counts[UNFILTERED_MAX_COPIES] = 0; + for (int i = 0; i < MAX_COUNTS; i++) + counts[i] = 0; +} + +void WSrcDeck::addCount(MTGCard * c, int qty) +{ + if (!c || !c->data) return; + map::iterator cp = copies.find(c->getMTGId()); + + if (matchesFilters(c)) + { + counts[FILTERED_COPIES] += qty; + if (qty > 0 && cp != copies.end() && (*cp).second == qty) + counts[FILTERED_UNIQUE]++; + else if (qty < 0 && (cp == copies.end() || (*cp).second == 0)) counts[FILTERED_UNIQUE]--; + } + counts[UNFILTERED_COPIES] += qty; + if (qty > 0 && cp != copies.end() && (*cp).second == qty) + counts[UNFILTERED_UNIQUE]++; + else if (qty < 0 && (cp == copies.end() || (*cp).second == 0)) counts[UNFILTERED_UNIQUE]--; + for (int i = Constants::MTG_COLOR_ARTIFACT; i <= Constants::MTG_COLOR_LAND; i++) + if (c->data->hasColor(i)) counts[i] += qty; + if (counts[UNFILTERED_MIN_COPIES] < 0 || qty < counts[UNFILTERED_MIN_COPIES]) counts[UNFILTERED_MIN_COPIES] = qty; + if (qty > counts[UNFILTERED_MAX_COPIES]) counts[UNFILTERED_MAX_COPIES] = qty; +} + +int WSrcDeck::Add(MTGCard * c, int quantity) +{ + if (!c) return 0; + if (copies.find(c->getMTGId()) == copies.end()) + { + cards.push_back(c); + } + copies[c->getMTGId()] += quantity; + addCount(c, quantity); + return 1; +} + +int WSrcDeck::Remove(MTGCard * c, int quantity, bool erase) +{ + if (!c) return 0; + map::iterator it = copies.find(c->getMTGId()); + if (it == copies.end()) return 0; + int amt = it->second; + if (amt < quantity) return 0; + amt -= quantity; + it->second = amt; + if (erase && amt == 0) + { + copies.erase(it); + vector::iterator i = find(cards.begin(), cards.end(), c); + if (i != cards.end()) cards.erase(i); + } + addCount(c, -quantity); + return 1; +} + +void WSrcDeck::Rebuild(MTGDeck * d) +{ + d->removeAll(); + map::iterator it; + for (it = copies.begin(); it != copies.end(); it++) + { + for (int i = 0; i < it->second; i++) + { + d->add(it->first); + } + } +} + +int WSrcDeck::count(MTGCard * c) +{ + if (!c) return counts[UNFILTERED_COPIES]; + if (copies.find(c->getMTGId()) == copies.end()) return 0; + return copies[c->getMTGId()]; +} + +int WSrcDeck::countByName(MTGCard * card, bool editions) +{ + string name = card->data->getLCName(); + int total = 0; + vector::iterator it; + for (it = cards.begin(); it != cards.end(); it++) + { + if (*it && (*it)->data->getLCName() == name) + { + if (editions) + total++; + else + { + map::iterator mi = copies.find((*it)->getMTGId()); + if (mi != copies.end()) total += mi->second; + } + } + } + return total; +} + +int WSrcDeck::getCount(int count) +{ + if (count < 0 || count >= MAX_COUNTS) return counts[UNFILTERED_COPIES]; + return counts[count]; +} + +int WSrcDeck::totalPrice() +{ + int total = 0; + PriceList * pricelist = NEW PriceList(JGE_GET_RES("settings/prices.dat").c_str(), GameApp::collection); + map::iterator it; + for (it = copies.begin(); it != copies.end(); it++) + { + int nb = it->second; + if (nb) total += pricelist->getPrice(it->first); + } + SAFE_DELETE(pricelist); + return total; +} + +//WSrcDeckViewer +WSrcDeckViewer::WSrcDeckViewer(WSrcCards * _active, WSrcCards * _inactive) : + WSrcCards(0.2f) +{ + active = _active; + inactive = _inactive; +} + +void WSrcDeckViewer::swapSrc() +{ + WSrcCards * temp = active; + active = inactive; + inactive = temp; +} + +WSrcDeckViewer::~WSrcDeckViewer() +{ + //Do nothing. +} + +//Sorting methods: +int WCSortRarity::rareToInt(char r) +{ + switch (r) + { + default: + case Constants::RARITY_T: + return 0; + case Constants::RARITY_L: + return 1; + case Constants::RARITY_C: + return 2; + case Constants::RARITY_U: + return 3; + case Constants::RARITY_R: + return 4; + case Constants::RARITY_M: + return 5; + case Constants::RARITY_S: + return 6; + } +} + +bool WCSortRarity::operator()(const MTGCard*l, const MTGCard*r) +{ + if (!l || !r || !l->data || !r->data) return false; + return (rareToInt(l->getRarity()) < rareToInt(r->getRarity())); +} + +bool WCSortAlpha::operator()(const MTGCard*l, const MTGCard*r) +{ + if (!l || !r || !l->data || !r->data) return false; + string ln = l->data->getLCName(); + string rn = r->data->getLCName(); + if (ln == rn) return l->getMTGId() < r->getMTGId(); + return (ln < rn); +} + +bool WCSortCollector::operator()(const MTGCard*l, const MTGCard*r) +{ + if (!l || !r || !l->data || !r->data) return false; + + if (l->setId != r->setId) return (l->setId < r->setId); + + int lc, rc; + lc = l->data->countColors(); + rc = r->data->countColors(); + if (lc == 0) lc = 999; + if (rc == 0) rc = 999; + + int isW = (int) l->data->hasColor(Constants::MTG_COLOR_WHITE) - (int) r->data->hasColor(Constants::MTG_COLOR_WHITE); + int isU = (int) l->data->hasColor(Constants::MTG_COLOR_BLUE) - (int) r->data->hasColor(Constants::MTG_COLOR_BLUE); + int isB = (int) l->data->hasColor(Constants::MTG_COLOR_BLACK) - (int) r->data->hasColor(Constants::MTG_COLOR_BLACK); + int isR = (int) l->data->hasColor(Constants::MTG_COLOR_RED) - (int) r->data->hasColor(Constants::MTG_COLOR_RED); + int isG = (int) l->data->hasColor(Constants::MTG_COLOR_GREEN) - (int) r->data->hasColor(Constants::MTG_COLOR_GREEN); + int isArt = (int) l->data->hasType(Subtypes::TYPE_ARTIFACT) - (int) r->data->hasType(Subtypes::TYPE_ARTIFACT); + int isLand = (int) l->data->hasType(Subtypes::TYPE_LAND) - (int) r->data->hasType(Subtypes::TYPE_LAND); + + //Nested if hell. TODO: Farm these out to their own objects as a user-defined filter/sort system. + if (!isLand) + { + int isBasic = (int) l->data->hasType("Basic") - (int) r->data->hasType("Basic"); + if (!isBasic) + { + if (!isArt) + { + if (lc == rc) + { + if (!isG) + { + if (!isR) + { + if (!isB) + { + if (!isU) + { + if (!isW) + { + string ln = l->data->getLCName(); + string rn = r->data->getLCName(); + if (ln.substr(0, 4) == "the ") ln = ln.substr(4); + if (rn.substr(0, 4) == "the ") rn = rn.substr(4); + return (ln < rn); + } + return (isW < 0); + } + return (isU < 0); + } + return (isB < 0); + } + return (isR < 0); + } + return (isG < 0); + } + return (lc < rc); + } + return (isArt < 0); + } + else + return (isBasic < 0); + } + return (isLand < 0); +} diff --git a/projects/mtg/src/WEvent.cpp b/projects/mtg/src/WEvent.cpp index 9d0e81559..c54dde981 100644 --- a/projects/mtg/src/WEvent.cpp +++ b/projects/mtg/src/WEvent.cpp @@ -6,147 +6,238 @@ #include "Damage.h" #include "PhaseRing.h" -WEvent::WEvent(int type) : type(type){} - -WEventZoneChange::WEventZoneChange(MTGCardInstance * card, MTGGameZone * from, MTGGameZone *to) : WEvent(CHANGE_ZONE), card(card), from(from), to(to){} - -WEventDamage::WEventDamage(Damage *damage) : WEvent(DAMAGE), damage(damage){} - -WEventDamageStackResolved::WEventDamageStackResolved() : WEvent(){} - -WEventCardUpdate::WEventCardUpdate(MTGCardInstance * card) : WEvent(), card(card) {}; - -WEventPhaseChange::WEventPhaseChange(Phase * from, Phase * to) : WEvent(CHANGE_PHASE), from(from), to(to){} - -WEventCardTap::WEventCardTap(MTGCardInstance * card, bool before, bool after) : WEventCardUpdate(card), before(before), after(after){} - -WEventCardTappedForMana::WEventCardTappedForMana(MTGCardInstance * card, bool before, bool after) : WEventCardUpdate(card), before(before), after(after){} - -WEventCardAttacked::WEventCardAttacked(MTGCardInstance * card) : WEventCardUpdate(card){} - -WEventCardAttackedAlone::WEventCardAttackedAlone(MTGCardInstance * card) : WEventCardUpdate(card){} - -WEventCardAttackedNotBlocked::WEventCardAttackedNotBlocked(MTGCardInstance * card) : WEventCardUpdate(card){} - -WEventCardAttackedBlocked::WEventCardAttackedBlocked(MTGCardInstance * card) : WEventCardUpdate(card){} - -WEventCardBlocked::WEventCardBlocked(MTGCardInstance * card) : WEventCardUpdate(card){} - -WEventcardDraw::WEventcardDraw(Player * player,int nb_cards) : player(player), nb_cards(nb_cards){} - -WEventCardSacrifice::WEventCardSacrifice(MTGCardInstance * card) : WEventCardUpdate(card){} - -WEventCardDiscard::WEventCardDiscard(MTGCardInstance * card) : WEventCardUpdate(card){} - -WEventCardChangeType::WEventCardChangeType(MTGCardInstance * card, int type, bool before, bool after) : WEventCardUpdate(card), type(type), before(before), after(after){} - -WEventCreatureAttacker::WEventCreatureAttacker(MTGCardInstance * card, Targetable * before, Targetable * after) : WEventCardUpdate(card), before(before), after(after){} - -WEventCreatureBlocker::WEventCreatureBlocker(MTGCardInstance * card, MTGCardInstance * from,MTGCardInstance * to) : WEventCardUpdate(card), before(from), after(to){} - -WEventCreatureBlockerRank::WEventCreatureBlockerRank(MTGCardInstance * card, MTGCardInstance * exchangeWith, MTGCardInstance * attacker) : WEventCardUpdate(card), exchangeWith(exchangeWith), attacker(attacker){} - -WEventEngageMana::WEventEngageMana(int color, MTGCardInstance* card, ManaPool * destination) : WEvent(), color(color), card(card), destination(destination) {} -WEventConsumeMana::WEventConsumeMana(int color, ManaPool * source) : WEvent(), color(color),source(source) {} -WEventEmptyManaPool::WEventEmptyManaPool(ManaPool * source) : WEvent(), source(source){} - -WEventCombatStepChange::WEventCombatStepChange(CombatStep step) : WEvent(), step(step) {}; - -Targetable * WEventDamage::getTarget(int target) { - switch (target) { - case TARGET_TO : - return damage->target; - case TARGET_FROM : - return damage->source; - } - return NULL; +WEvent::WEvent(int type) : + type(type) +{ } -int WEventDamage::getValue() { - return damage->damage; +WEventZoneChange::WEventZoneChange(MTGCardInstance * card, MTGGameZone * from, MTGGameZone *to) : + WEvent(CHANGE_ZONE), card(card), from(from), to(to) +{ } -Targetable * WEventZoneChange::getTarget(int target) { - if (target) return card; - return NULL; +WEventDamage::WEventDamage(Damage *damage) : + WEvent(DAMAGE), damage(damage) +{ } -Targetable * WEventCardAttacked::getTarget(int target) { - if (target) return card; - return NULL; +WEventDamageStackResolved::WEventDamageStackResolved() : + WEvent() +{ } -Targetable * WEventCardAttackedAlone::getTarget(int target) { - if (target) return card; - return NULL; +WEventCardUpdate::WEventCardUpdate(MTGCardInstance * card) : + WEvent(), card(card) +{ +} +; + +WEventPhaseChange::WEventPhaseChange(Phase * from, Phase * to) : + WEvent(CHANGE_PHASE), from(from), to(to) +{ } -Targetable * WEventCardSacrifice::getTarget(int target) { - if (target) return card; - return NULL; +WEventCardTap::WEventCardTap(MTGCardInstance * card, bool before, bool after) : + WEventCardUpdate(card), before(before), after(after) +{ } -Targetable * WEventCardDiscard::getTarget(int target) { - if (target) return card; - return NULL; +WEventCardTappedForMana::WEventCardTappedForMana(MTGCardInstance * card, bool before, bool after) : + WEventCardUpdate(card), before(before), after(after) +{ } -Targetable * WEventCardAttackedNotBlocked::getTarget(int target) { - if (target) return card; - return NULL; +WEventCardAttacked::WEventCardAttacked(MTGCardInstance * card) : + WEventCardUpdate(card) +{ } -Targetable * WEventCardAttackedBlocked::getTarget(int target) { - switch (target) { - case TARGET_TO : - return card; - case TARGET_FROM : - return card->getNextOpponent(); - } - return NULL; +WEventCardAttackedAlone::WEventCardAttackedAlone(MTGCardInstance * card) : + WEventCardUpdate(card) +{ } -Targetable * WEventCardBlocked::getTarget(int target) { - switch (target) { - case TARGET_TO : - return card; - case TARGET_FROM : - return card->getNextOpponent(); - } - return NULL; +WEventCardAttackedNotBlocked::WEventCardAttackedNotBlocked(MTGCardInstance * card) : + WEventCardUpdate(card) +{ } -Targetable * WEventCardTap::getTarget(int target){ - if (target) return card; - return NULL; +WEventCardAttackedBlocked::WEventCardAttackedBlocked(MTGCardInstance * card) : + WEventCardUpdate(card) +{ } -Targetable * WEventCardTappedForMana::getTarget(int target){ - if (target) return card; - return NULL; +WEventCardBlocked::WEventCardBlocked(MTGCardInstance * card) : + WEventCardUpdate(card) +{ } -Targetable * WEventcardDraw::getTarget(Player * player){ - if (player) return player; - return NULL; +WEventcardDraw::WEventcardDraw(Player * player, int nb_cards) : + player(player), nb_cards(nb_cards) +{ +} + +WEventCardSacrifice::WEventCardSacrifice(MTGCardInstance * card) : + WEventCardUpdate(card) +{ +} + +WEventCardDiscard::WEventCardDiscard(MTGCardInstance * card) : + WEventCardUpdate(card) +{ +} + +WEventCardChangeType::WEventCardChangeType(MTGCardInstance * card, int type, bool before, bool after) : + WEventCardUpdate(card), type(type), before(before), after(after) +{ +} + +WEventCreatureAttacker::WEventCreatureAttacker(MTGCardInstance * card, Targetable * before, Targetable * after) : + WEventCardUpdate(card), before(before), after(after) +{ +} + +WEventCreatureBlocker::WEventCreatureBlocker(MTGCardInstance * card, MTGCardInstance * from, MTGCardInstance * to) : + WEventCardUpdate(card), before(from), after(to) +{ +} + +WEventCreatureBlockerRank::WEventCreatureBlockerRank(MTGCardInstance * card, MTGCardInstance * exchangeWith, + MTGCardInstance * attacker) : + WEventCardUpdate(card), exchangeWith(exchangeWith), attacker(attacker) +{ +} + +WEventEngageMana::WEventEngageMana(int color, MTGCardInstance* card, ManaPool * destination) : + WEvent(), color(color), card(card), destination(destination) +{ +} +WEventConsumeMana::WEventConsumeMana(int color, ManaPool * source) : + WEvent(), color(color), source(source) +{ +} +WEventEmptyManaPool::WEventEmptyManaPool(ManaPool * source) : + WEvent(), source(source) +{ +} + +WEventCombatStepChange::WEventCombatStepChange(CombatStep step) : + WEvent(), step(step) +{ +} +; + +Targetable * WEventDamage::getTarget(int target) +{ + switch (target) + { + case TARGET_TO: + return damage->target; + case TARGET_FROM: + return damage->source; + } + return NULL; +} + +int WEventDamage::getValue() +{ + return damage->damage; +} + +Targetable * WEventZoneChange::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventCardAttacked::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventCardAttackedAlone::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventCardSacrifice::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventCardDiscard::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventCardAttackedNotBlocked::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventCardAttackedBlocked::getTarget(int target) +{ + switch (target) + { + case TARGET_TO: + return card; + case TARGET_FROM: + return card->getNextOpponent(); + } + return NULL; +} + +Targetable * WEventCardBlocked::getTarget(int target) +{ + switch (target) + { + case TARGET_TO: + return card; + case TARGET_FROM: + return card->getNextOpponent(); + } + return NULL; +} + +Targetable * WEventCardTap::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventCardTappedForMana::getTarget(int target) +{ + if (target) return card; + return NULL; +} + +Targetable * WEventcardDraw::getTarget(Player * player) +{ + if (player) return player; + return NULL; } std::ostream& WEvent::toString(std::ostream& out) const { - return out << "EVENT"; + return out << "EVENT"; } std::ostream& WEventZoneChange::toString(std::ostream& out) const { - return out << "ZONEEVENT " << *card << " : " << *from << " -> " << *to; + return out << "ZONEEVENT " << *card << " : " << *from << " -> " << *to; } std::ostream& WEventDamage::toString(std::ostream& out) const { - if (MTGCardInstance* m = dynamic_cast(damage->target)) - return out << "DAMAGEEVENT " << damage->damage << " >> " << *m; - else - return out << "DAMAGEEVENT " << damage->damage << " >> " << damage->target; + if (MTGCardInstance* m = dynamic_cast(damage->target)) + return out << "DAMAGEEVENT " << damage->damage << " >> " << *m; + else + return out << "DAMAGEEVENT " << damage->damage << " >> " << damage->target; } std::ostream& operator<<(std::ostream& out, const WEvent& m) { - return m.toString(out); + return m.toString(out); } diff --git a/projects/mtg/src/WFilter.cpp b/projects/mtg/src/WFilter.cpp index 5f6b64a18..41c49634c 100644 --- a/projects/mtg/src/WFilter.cpp +++ b/projects/mtg/src/WFilter.cpp @@ -7,325 +7,389 @@ //WCFilterFactory WCFilterFactory* WCFilterFactory::me = NULL; -WCFilterFactory* WCFilterFactory::GetInstance() { - if(!me) - me = NEW WCFilterFactory(); - return me; +WCFilterFactory* WCFilterFactory::GetInstance() +{ + if (!me) me = NEW WCFilterFactory(); + return me; } -void WCFilterFactory::Destroy(){ - SAFE_DELETE(me); +void WCFilterFactory::Destroy() +{ + SAFE_DELETE(me); } -size_t WCFilterFactory::findNext(string src, size_t start,char open, char close){ - int num = 0; - for(size_t x=start;xdata) +bool WCFilterLetter::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + string s = c->data->getLCName(); + if (!s.size()) return false; + if (s[0] == alpha || (alpha == '#' && (isdigit(s[0]) || ispunct(s[0])))) return true; return false; - string s = c->data->getLCName(); - if(!s.size()) - return false; - if(s[0] == alpha || (alpha == '#' && (isdigit(s[0]) || ispunct(s[0])))) - return true; - return false; } -string WCFilterLetter::getCode(){ - char buf[24]; - sprintf(buf,"alpha:%c;",alpha); - return buf; +string WCFilterLetter::getCode() +{ + char buf[24]; + sprintf(buf, "alpha:%c;", alpha); + return buf; } //WCFilterSet -WCFilterSet::WCFilterSet(string arg){ - setid = setlist.findSet(arg); +WCFilterSet::WCFilterSet(string arg) +{ + setid = setlist.findSet(arg); } -string WCFilterSet::getCode(){ - char buf[256]; - sprintf(buf,"set:%s;",setlist[setid].c_str()); - return buf; -}; +string WCFilterSet::getCode() +{ + char buf[256]; + sprintf(buf, "set:%s;", setlist[setid].c_str()); + return buf; +} +; //WCFilterColor -bool WCFilterColor::isMatch(MTGCard * c){ - if(!c || !c->data) - return false; - return (c->data->hasColor(color) > 0); +bool WCFilterColor::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + return (c->data->hasColor(color) > 0); } -string WCFilterColor::getCode(){ - char buf[12]; - char c = '?'; - if(color < 0 || color >= Constants::MTG_NB_COLORS) - c = Constants::MTGColorChars[color]; - sprintf(buf,"color:%c;",c); - return buf; -}; -WCFilterColor::WCFilterColor(string arg){ - color = -1; - char c = tolower(arg[0]); - for(int i=0;i= Constants::MTG_NB_COLORS) c = Constants::MTGColorChars[color]; + sprintf(buf, "color:%c;", c); + return buf; +} +; +WCFilterColor::WCFilterColor(string arg) +{ + color = -1; + char c = tolower(arg[0]); + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + if (Constants::MTGColorChars[i] == c) + { + color = i; + break; + } } - } } //WCFilterOnlyColor -bool WCFilterOnlyColor::isMatch(MTGCard * c){ - if(!c || !c->data) - return false; - for(int i=0;idata->hasColor(i) > 0) - return false; - } - return (c->data->hasColor(color) > 0); +bool WCFilterOnlyColor::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + for (int i = 0; i < Constants::MTG_NB_COLORS; i++) + { + if (i == color) continue; + if (c->data->hasColor(i) > 0) return false; + } + return (c->data->hasColor(color) > 0); } -string WCFilterOnlyColor::getCode(){ - char buf[12]; - char c = '?'; - if(color < 0 || color >= Constants::MTG_NB_COLORS) - c = Constants::MTGColorChars[color]; - sprintf(buf,"xcolor:%c;",c); - return buf; +string WCFilterOnlyColor::getCode() +{ + char buf[12]; + char c = '?'; + if (color < 0 || color >= Constants::MTG_NB_COLORS) c = Constants::MTGColorChars[color]; + sprintf(buf, "xcolor:%c;", c); + return buf; } //WCFilterProducesColor -bool WCFilterProducesColor::isMatch(MTGCard * c){ - bool bMatch = false; - if(!c || !c->data) - return false; - string s = c->data->magicText; - size_t t = s.find("add"); - while(t != string::npos){ - s = s.substr(t+3); - ManaCost * mc = ManaCost::parseManaCost(s); - if(mc->hasColor(color) > 0) {bMatch = true; SAFE_DELETE(mc); break;} - SAFE_DELETE(mc); - t = s.find("add"); - } - return bMatch; +bool WCFilterProducesColor::isMatch(MTGCard * c) +{ + bool bMatch = false; + if (!c || !c->data) return false; + string s = c->data->magicText; + size_t t = s.find("add"); + while (t != string::npos) + { + s = s.substr(t + 3); + ManaCost * mc = ManaCost::parseManaCost(s); + if (mc->hasColor(color) > 0) + { + bMatch = true; + SAFE_DELETE(mc); + break; + } + SAFE_DELETE(mc); + t = s.find("add"); + } + return bMatch; } -string WCFilterProducesColor::getCode(){ - char buf[12]; - char c = '?'; - if(color < 0 || color >= Constants::MTG_NB_COLORS) - c = Constants::MTGColorChars[color]; - sprintf(buf,"produces:%c;",c); - return buf; +string WCFilterProducesColor::getCode() +{ + char buf[12]; + char c = '?'; + if (color < 0 || color >= Constants::MTG_NB_COLORS) c = Constants::MTGColorChars[color]; + sprintf(buf, "produces:%c;", c); + return buf; } //WCFilterNumeric -WCFilterNumeric::WCFilterNumeric(string arg){ - number = atoi(arg.c_str()); +WCFilterNumeric::WCFilterNumeric(string arg) +{ + number = atoi(arg.c_str()); } //WCFilterCMC -bool WCFilterCMC::isMatch(MTGCard * c){ - if(!c || !c->data) - return false; - ManaCost * mc = c->data->getManaCost(); - return (mc->getConvertedCost() == number); +bool WCFilterCMC::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + ManaCost * mc = c->data->getManaCost(); + return (mc->getConvertedCost() == number); } -string WCFilterCMC::getCode(){ - char buf[64]; - sprintf(buf,"cmc:%i;",number); - return buf; +string WCFilterCMC::getCode() +{ + char buf[64]; + sprintf(buf, "cmc:%i;", number); + return buf; } //WCFilterPower -bool WCFilterPower::isMatch(MTGCard * c){ - if(!c || !c->data) - return false; - return (c->data->getPower() == number); +bool WCFilterPower::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + return (c->data->getPower() == number); } -string WCFilterPower::getCode(){ - char buf[64]; - sprintf(buf,"power:%i;",number); - return buf; +string WCFilterPower::getCode() +{ + char buf[64]; + sprintf(buf, "power:%i;", number); + return buf; } //WCFilterPower -bool WCFilterToughness::isMatch(MTGCard * c){ - if(!c || !c->data) - return false; - return (c->data->getToughness() == number); +bool WCFilterToughness::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + return (c->data->getToughness() == number); } -string WCFilterToughness::getCode(){ - char buf[64]; - sprintf(buf,"toughness:%i;",number); - return buf; +string WCFilterToughness::getCode() +{ + char buf[64]; + sprintf(buf, "toughness:%i;", number); + return buf; } //WCFilterRarity -float WCFilterRarity::filterFee(){ - switch(rarity){ - case 'M': return 2.0f; - case 'R': return 1.0f; - case 'U': return 0.5f; - case 'C': return 0.2f; - } - return 0.0f; +float WCFilterRarity::filterFee() +{ + switch (rarity) + { + case 'M': + return 2.0f; + case 'R': + return 1.0f; + case 'U': + return 0.5f; + case 'C': + return 0.2f; + } + return 0.0f; } -bool WCFilterRarity::isMatch(MTGCard * c){ - if(!c || !c->data) - return false; - if(rarity == 'A') return true; //A for "Any" or "All" - return (c->getRarity() == rarity); +bool WCFilterRarity::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + if (rarity == 'A') return true; //A for "Any" or "All" + return (c->getRarity() == rarity); } -string WCFilterRarity::getCode(){ - char buf[64]; - const char* rarities[8] = {"any","token","land","common","uncommon","rare","mythic","special"}; - int x = 0; - switch(rarity){ - case 'S': x=7; break; - case 'M': x=6; break; - case 'R': x=5; break; - case 'U': x=4; break; - case 'C': x=3; break; - case 'L': x=2; break; - case 'T': x=1; break; - } - sprintf(buf,"rarity:%s;",rarities[x]); - return buf; -}; -WCFilterRarity::WCFilterRarity(string arg){ - rarity = -1; - char c = toupper(arg[0]); - switch(c){ +string WCFilterRarity::getCode() +{ + char buf[64]; + const char* rarities[8] = { "any", "token", "land", "common", "uncommon", "rare", "mythic", "special" }; + int x = 0; + switch (rarity) + { + case 'S': + x = 7; + break; + case 'M': + x = 6; + break; + case 'R': + x = 5; + break; + case 'U': + x = 4; + break; + case 'C': + x = 3; + break; + case 'L': + x = 2; + break; + case 'T': + x = 1; + break; + } + sprintf(buf, "rarity:%s;", rarities[x]); + return buf; +} +; +WCFilterRarity::WCFilterRarity(string arg) +{ + rarity = -1; + char c = toupper(arg[0]); + switch (c) + { case 'S': case 'M': case 'R': @@ -333,48 +397,54 @@ WCFilterRarity::WCFilterRarity(string arg){ case 'C': case 'L': case 'T': - rarity = c; - return; - } - rarity = 'A'; + rarity = c; + return; + } + rarity = 'A'; } //WCFilterAbility -bool WCFilterAbility::isMatch(MTGCard * c){ - if(ability < 0) - return false; - map::iterator it = c->data->basicAbilities.find(ability); +bool WCFilterAbility::isMatch(MTGCard * c) +{ + if (ability < 0) return false; + map::iterator it = c->data->basicAbilities.find(ability); - if(it != c->data->basicAbilities.end()){ - if(it->second > 0) - return true; - } - return false; -} -WCFilterAbility::WCFilterAbility(string arg){ - std::transform(arg.begin(),arg.end(),arg.begin(),::tolower); - for(int i = 0;idata->basicAbilities.end()) + { + if (it->second > 0) return true; } - } - ability = -1; + return false; } -string WCFilterAbility::getCode(){ - char buf[64]; - if(ability < 0 || ability >= Constants::NB_BASIC_ABILITIES) - return ""; - sprintf(buf,"ability:%s;",Constants::MTGBasicAbilities[ability]); - return buf; -}; -float WCFilterAbility::filterFee(){ - switch(ability){ +WCFilterAbility::WCFilterAbility(string arg) +{ + std::transform(arg.begin(), arg.end(), arg.begin(), ::tolower); + for (int i = 0; i < Constants::NB_BASIC_ABILITIES; i++) + { + if (arg == Constants::MTGBasicAbilities[i]) + { + ability = i; + return; + } + } + ability = -1; +} +string WCFilterAbility::getCode() +{ + char buf[64]; + if (ability < 0 || ability >= Constants::NB_BASIC_ABILITIES) return ""; + sprintf(buf, "ability:%s;", Constants::MTGBasicAbilities[ability]); + return buf; +} +; +float WCFilterAbility::filterFee() +{ + switch (ability) + { case Constants::SHROUD: case Constants::DEATHTOUCH: case Constants::UNBLOCKABLE: case Constants::WITHER: case Constants::PERSIST: - return 0.8f; + return 0.8f; case Constants::PROTECTIONBLACK: case Constants::PROTECTIONWHITE: case Constants::PROTECTIONBLUE: @@ -382,72 +452,78 @@ float WCFilterAbility::filterFee(){ case Constants::PROTECTIONGREEN: case Constants::DOUBLESTRIKE: case Constants::LIFELINK: - return 0.7f; + return 0.7f; case Constants::TRAMPLE: case Constants::FLYING: case Constants::FEAR: case Constants::VIGILANCE: case Constants::FIRSTSTRIKE: - return 0.6f; + return 0.6f; case Constants::PLAINSHOME: case Constants::SWAMPHOME: - case Constants::ISLANDHOME: + case Constants::ISLANDHOME: case Constants::MOUNTAINHOME: case Constants::FORESTHOME: - return -0.2f; + return -0.2f; case Constants::DEFENDER: case Constants::CLOUD: - return 0.2f; + return 0.2f; default: - return 0.4f; - } - return 0.0f; + return 0.4f; + } + return 0.0f; } //WCFilterType -bool WCFilterType::isMatch(MTGCard * c){ - return c->data->hasType(type.c_str()); +bool WCFilterType::isMatch(MTGCard * c) +{ + return c->data->hasType(type.c_str()); } -string WCFilterType::getCode(){ - char buf[4068]; - sprintf(buf,"type:%s;",type.c_str()); - return buf; -} -//Misc. filter code -float WCFilterAND::filterFee(){ - return lhs->filterFee() + rhs->filterFee(); -} -float WCFilterOR::filterFee(){ - if(lhs->filterFee() > rhs->filterFee()) - return lhs->filterFee(); - return rhs->filterFee(); -} -string WCFilterNOT::getCode(){ +string WCFilterType::getCode() +{ char buf[4068]; - sprintf(buf,"{%s}",kid->getCode().c_str()); + sprintf(buf, "type:%s;", type.c_str()); return buf; } -string WCFilterGROUP::getCode(){ - char buf[4068]; - sprintf(buf,"(%s)",kid->getCode().c_str()); - return buf; +//Misc. filter code +float WCFilterAND::filterFee() +{ + return lhs->filterFee() + rhs->filterFee(); +} +float WCFilterOR::filterFee() +{ + if (lhs->filterFee() > rhs->filterFee()) return lhs->filterFee(); + return rhs->filterFee(); +} +string WCFilterNOT::getCode() +{ + char buf[4068]; + sprintf(buf, "{%s}", kid->getCode().c_str()); + return buf; +} +string WCFilterGROUP::getCode() +{ + char buf[4068]; + sprintf(buf, "(%s)", kid->getCode().c_str()); + return buf; } -string WCFilterAND::getCode(){ - char buf[4068]; - sprintf(buf,"%s&%s",lhs->getCode().c_str(),rhs->getCode().c_str()); - return buf; +string WCFilterAND::getCode() +{ + char buf[4068]; + sprintf(buf, "%s&%s", lhs->getCode().c_str(), rhs->getCode().c_str()); + return buf; } -string WCFilterOR::getCode(){ - char buf[4068]; - sprintf(buf,"%s|%s",lhs->getCode().c_str(),rhs->getCode().c_str()); - return buf; +string WCFilterOR::getCode() +{ + char buf[4068]; + sprintf(buf, "%s|%s", lhs->getCode().c_str(), rhs->getCode().c_str()); + return buf; } - -bool WCFilterOR::isMatch(MTGCard *c){ - if(lhs->isMatch(c)) - return true; - if(rhs->isMatch(c)) - return true; - return false; -}; \ No newline at end of file +bool WCFilterOR::isMatch(MTGCard *c) +{ + if (lhs->isMatch(c)) return true; + if (rhs->isMatch(c)) return true; + return false; +} +; diff --git a/projects/mtg/src/WFont.cpp b/projects/mtg/src/WFont.cpp index d17d45c67..20b632f9b 100644 --- a/projects/mtg/src/WFont.cpp +++ b/projects/mtg/src/WFont.cpp @@ -8,69 +8,78 @@ static PIXEL_TYPE gencolor(int id, PIXEL_TYPE color) { - unsigned int a, r, g, b, r0, g0, b0; + unsigned int a, r, g, b, r0, g0, b0; #if defined (WIN32) || defined (LINUX) - a = (color >> 24) & 0xFF; - r = (color >> 16) & 0xFF; - g = (color >> 8) & 0xFF; - b = (color >> 0) & 0xFF; + a = (color >> 24) & 0xFF; + r = (color >> 16) & 0xFF; + g = (color >> 8) & 0xFF; + b = (color >> 0) & 0xFF; #else // PSP # if defined (ABGR8888) - a = (color >> 24) & 0xFF; - b = (color >> 16) & 0xFF; - g = (color >> 8) & 0xFF; - r = (color >> 0) & 0xFF; + a = (color >> 24) & 0xFF; + b = (color >> 16) & 0xFF; + g = (color >> 8) & 0xFF; + r = (color >> 0) & 0xFF; # elif defined (ABGR5551) - a = ((color >> 15) & 0x01) << 7; - b = ((color >> 10) & 0x1F) << 3; - g = ((color >> 5) & 0x1F) << 3; - r = ((color >> 0) & 0x1F) << 3; + a = ((color >> 15) & 0x01) << 7; + b = ((color >> 10) & 0x1F) << 3; + g = ((color >> 5) & 0x1F) << 3; + r = ((color >> 0) & 0x1F) << 3; # elif defined (ABGR4444) - a = ((color >> 12) & 0x0F) << 4; - b = ((color >> 8) & 0x0F) << 4; - g = ((color >> 4) & 0x0F) << 4; - r = ((color >> 0) & 0x0F) << 4; + a = ((color >> 12) & 0x0F) << 4; + b = ((color >> 8) & 0x0F) << 4; + g = ((color >> 4) & 0x0F) << 4; + r = ((color >> 0) & 0x0F) << 4; # endif #endif - r0 = g0 = b0 = 255; + r0 = g0 = b0 = 255; - switch (id) { - case Fonts::MAIN_FONT: // simon 245, 228, 156 - r0 = 245; g0 = 228; b0 = 156; - break; - case Fonts::MENU_FONT: // f3 255, 252, 175 - r0 = 255; g0 = 252; b0 = 175; - break; - case Fonts::MAGIC_FONT: // magic 219, 255, 151 - r0 = 219; g0 = 255; b0 = 151; - break; - case Fonts::SMALLFACE_FONT: // smallface 255, 255, 255 - r0 = 255; g0 = 255; b0 = 255; - break; - default: - ; - } - r = r * r0 / 255; - g = g * g0 / 255; - b = b * b0 / 255; + switch (id) + { + case Fonts::MAIN_FONT: // simon 245, 228, 156 + r0 = 245; + g0 = 228; + b0 = 156; + break; + case Fonts::MENU_FONT: // f3 255, 252, 175 + r0 = 255; + g0 = 252; + b0 = 175; + break; + case Fonts::MAGIC_FONT: // magic 219, 255, 151 + r0 = 219; + g0 = 255; + b0 = 151; + break; + case Fonts::SMALLFACE_FONT: // smallface 255, 255, 255 + r0 = 255; + g0 = 255; + b0 = 255; + break; + default: + ; + } + r = r * r0 / 255; + g = g * g0 / 255; + b = b * b0 / 255; - return ARGB(a,r,g,b); + return ARGB(a,r,g,b); } static inline bool doubleWidthChar(const u8* const src) { - // Determination of this is done with < 0xC0, which is not - // right but okay for now (in particular it will return 2 - // for european accented characters) - return *src >= 0xC0; + // Determination of this is done with < 0xC0, which is not + // right but okay for now (in particular it will return 2 + // for european accented characters) + return *src >= 0xC0; } static inline bool GBKDoubleWidthChar(const u8* const src) { - // Determination of this is done with < 0xC0, which is not - // right but okay for now (in particular it will return 2 - // for european accented characters) - return *src >= 0x80; + // Determination of this is done with < 0xC0, which is not + // right but okay for now (in particular it will return 2 + // for european accented characters) + return *src >= 0x80; } // This returns the size in bytes of a character. @@ -79,934 +88,1015 @@ static inline bool GBKDoubleWidthChar(const u8* const src) // only found in trailing bytes. static inline int charWidth(const u8 s) { - // The following is the "correct" one, but if called on incorrect strings - // the presence of 0's may create an infinite loop, so replace them with - // 1's. This may happen when changing from chinese to japanese because the - // encoding for chinese is not regular. - // static const int sizes[] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 4}; - static const int sizes[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4}; + // The following is the "correct" one, but if called on incorrect strings + // the presence of 0's may create an infinite loop, so replace them with + // 1's. This may happen when changing from chinese to japanese because the + // encoding for chinese is not regular. + // static const int sizes[] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 4}; + static const int sizes[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4 }; #if 0 - // Reactivate to support being called on trailing bytes. This is not needed at the moment - // as this function will always be passed leading bytes. - while (0 == sizes[s >> 4]) --s; + // Reactivate to support being called on trailing bytes. This is not needed at the moment + // as this function will always be passed leading bytes. + while (0 == sizes[s >> 4]) --s; #endif - return sizes[s >> 4]; + return sizes[s >> 4]; } - // JRenderer * WFBFont::mRenderer = NULL; -WLBFont::WLBFont(int inFontID, const char *fontname, int lineheight, bool useVideoRAM) - : WFont(inFontID) +WLBFont::WLBFont(int inFontID, const char *fontname, int lineheight, bool useVideoRAM) : + WFont(inFontID) { - string path(fontname); - if (path.size() > 4 ) path = path.substr(0, path.size() - 4); //some stupid manipulation because of the way Font works in JGE - it = NEW JLBFont(path.c_str(), lineheight, useVideoRAM); + string path(fontname); + if (path.size() > 4) path = path.substr(0, path.size() - 4); //some stupid manipulation because of the way Font works in JGE + it = NEW JLBFont(path.c_str(), lineheight, useVideoRAM); } -WFBFont::WFBFont(int inFontID, const char *fontname, int lineheight, bool useVideoRAM) - : WFont(inFontID) +WFBFont::WFBFont(int inFontID, const char *fontname, int lineheight, bool useVideoRAM) : + WFont(inFontID) { - mRenderer = JRenderer::GetInstance(); + mRenderer = JRenderer::GetInstance(); - mCharBuffer = NULL; - mSprites = NULL; - mGBCode = NULL; - mCurr = 0; + mCharBuffer = NULL; + mSprites = NULL; + mGBCode = NULL; + mCurr = 0; - char tmpFileName[32], engFileName[32]; - strcpy(tmpFileName, fontname); - char * ep = strrchr(tmpFileName, '.'); - *ep = '\0'; - sprintf(engFileName, "%s.asc", tmpFileName); - JFileSystem *fileSys = JFileSystem::GetInstance(); - int size = 0; - struct { - unsigned short chars; - unsigned char width; - unsigned char height; - } sizeStr = {0, 0, 0}; + char tmpFileName[32], engFileName[32]; + strcpy(tmpFileName, fontname); + char * ep = strrchr(tmpFileName, '.'); + *ep = '\0'; + sprintf(engFileName, "%s.asc", tmpFileName); + JFileSystem *fileSys = JFileSystem::GetInstance(); + int size = 0; + struct + { + unsigned short chars; + unsigned char width; + unsigned char height; + } sizeStr = { 0, 0, 0 }; - if (!fileSys->OpenFile(engFileName)) - return; - size = fileSys->GetFileSize(); - mStdFont = NEW u8[size]; - fileSys->ReadFile(mStdFont, size); - fileSys->CloseFile(); + if (!fileSys->OpenFile(engFileName)) return; + size = fileSys->GetFileSize(); + mStdFont = NEW u8[size]; + fileSys->ReadFile(mStdFont, size); + fileSys->CloseFile(); - if (!fileSys->OpenFile(fontname)) - return; - fileSys->ReadFile(&sizeStr, 4); // Works only for little-endian machines (PSP and PC are) - size = sizeStr.chars * sizeStr.width * sizeStr.height / 2; - mExtraFont = NEW u8[size]; // 4 bits for a pixel - mIndex = NEW u16[65536]; - fileSys->ReadFile(mIndex, 65536 * sizeof(u16)); - fileSys->ReadFile(mExtraFont, size); - fileSys->CloseFile(); + if (!fileSys->OpenFile(fontname)) return; + fileSys->ReadFile(&sizeStr, 4); // Works only for little-endian machines (PSP and PC are) + size = sizeStr.chars * sizeStr.width * sizeStr.height / 2; + mExtraFont = NEW u8[size]; // 4 bits for a pixel + mIndex = NEW u16[65536]; + fileSys->ReadFile(mIndex, 65536 * sizeof(u16)); + fileSys->ReadFile(mExtraFont, size); + fileSys->CloseFile(); - mColor0 = ARGB(255, 255, 255, 255); - mColor = mColor0; - mFontSize = lineheight; - mScale = 1.0f; + mColor0 = ARGB(255, 255, 255, 255); + mColor = mColor0; + mFontSize = lineheight; + mScale = 1.0f; - // using 4-bit(half-byte) to store 1 pixel - mBytesPerRow = static_cast(mFontSize / 2); - mBytesPerChar = static_cast(mBytesPerRow*mFontSize); + // using 4-bit(half-byte) to store 1 pixel + mBytesPerRow = static_cast (mFontSize / 2); + mBytesPerChar = static_cast (mBytesPerRow * mFontSize); - mCacheImageWidth = 256; - mCacheImageHeight = 256; - mCol = mCacheImageWidth / mFontSize; - mRow = mCacheImageHeight / mFontSize; - mCacheSize = mCol * mRow; + mCacheImageWidth = 256; + mCacheImageHeight = 256; + mCol = mCacheImageWidth / mFontSize; + mRow = mCacheImageHeight / mFontSize; + mCacheSize = mCol * mRow; - mSprites = NEW JQuad*[mCacheSize]; - mGBCode = NEW int[mCacheSize]; + mSprites = NEW JQuad*[mCacheSize]; + mGBCode = NEW int[mCacheSize]; #if defined (WIN32) || defined (LINUX) - mCharBuffer = NEW u32[mFontSize*mFontSize]; + mCharBuffer = NEW u32[mFontSize*mFontSize]; #endif - mTexture = mRenderer->CreateTexture(mCacheImageWidth, mCacheImageHeight, true); + mTexture = mRenderer->CreateTexture(mCacheImageWidth, mCacheImageHeight, true); - int index = 0; - for (int y = 0; y < mRow; y++) { - for (int x = 0; x < mCol; x++) { - mGBCode[index] = -1; - mSprites[index] = NEW JQuad(mTexture, - static_cast(x*mFontSize), - static_cast(y*mFontSize), - static_cast(mFontSize), - static_cast(mFontSize)); - mSprites[index]->SetHotSpot(static_cast(mFontSize / 2), static_cast(mFontSize / 2)); - index++; + int index = 0; + for (int y = 0; y < mRow; y++) + { + for (int x = 0; x < mCol; x++) + { + mGBCode[index] = -1; + mSprites[index] = NEW JQuad(mTexture, static_cast (x * mFontSize), static_cast (y * mFontSize), + static_cast (mFontSize), static_cast (mFontSize)); + mSprites[index]->SetHotSpot(static_cast (mFontSize / 2), static_cast (mFontSize / 2)); + index++; + } } - } } WFBFont::~WFBFont() { - SAFE_DELETE(mStdFont); - SAFE_DELETE(mExtraFont); - SAFE_DELETE(mTexture); + SAFE_DELETE(mStdFont); + SAFE_DELETE(mExtraFont); + SAFE_DELETE(mTexture); - if (mSprites) { - for (int i = 0; i < mCacheSize; i++) { - if (mSprites[i]) - delete mSprites[i]; + if (mSprites) + { + for (int i = 0; i < mCacheSize; i++) + { + if (mSprites[i]) delete mSprites[i]; + } + delete[] mSprites; } - delete [] mSprites; - } - if (NULL != mIndex) delete[] mIndex; + if (NULL != mIndex) delete[] mIndex; - if (mGBCode) - delete [] mGBCode; + if (mGBCode) delete[] mGBCode; - if (mCharBuffer) - delete [] mCharBuffer; + if (mCharBuffer) delete[] mCharBuffer; } #if defined (WIN32) || defined (LINUX) #else static void SwizzlePlot(u8* out, PIXEL_TYPE color, int i, int j, unsigned int width) { - unsigned int rowblocks = (width >> 4); + unsigned int rowblocks = (width >> 4); - unsigned int blockx = (i >> 4); - unsigned int blocky = (j >> 3); + unsigned int blockx = (i >> 4); + unsigned int blocky = (j >> 3); - unsigned int x = (i - (blockx << 4)); - unsigned int y = (j - (blocky << 3)); - unsigned int block_index = blockx + ((blocky) * rowblocks); - unsigned int block_address = block_index << 7; + unsigned int x = (i - (blockx << 4)); + unsigned int y = (j - (blocky << 3)); + unsigned int block_index = blockx + ((blocky) * rowblocks); + unsigned int block_address = block_index << 7; - u8* p = out + (block_address + x + (y << 4)); - PIXEL_TYPE* dest = (PIXEL_TYPE *)p; - *dest = color; + u8* p = out + (block_address + x + (y << 4)); + PIXEL_TYPE* dest = (PIXEL_TYPE *) p; + *dest = color; } #endif int WFBFont::PreCacheChar(const u8 *ch) { - int code; - int charLength = 1; - u8 * src; - unsigned int size, offset; - u8 gray; + int code; + int charLength = 1; + u8 * src; + unsigned int size, offset; + u8 gray; - code = this->GetCode(ch, &charLength); + code = this->GetCode(ch, &charLength); - if (mGBCode[mCurr] != -1) - for (int i = 0; i < mCacheSize; i++) - if (mGBCode[i] == code) - return i; + if (mGBCode[mCurr] != -1) for (int i = 0; i < mCacheSize; i++) + if (mGBCode[i] == code) return i; - int index = mCurr++; - if (mCurr >= mCacheSize) - mCurr = 0; + int index = mCurr++; + if (mCurr >= mCacheSize) mCurr = 0; #if defined (WIN32) || defined (LINUX) - int x = 0; - int y = 0; - memset(mCharBuffer, 0, sizeof(u32) * mFontSize * mFontSize); + int x = 0; + int y = 0; + memset(mCharBuffer, 0, sizeof(u32) * mFontSize * mFontSize); #else - u8* pTexture = (u8*) mTexture->mBits; - int x; - int y = (int)mSprites[index]->mY; + u8* pTexture = (u8*) mTexture->mBits; + int x; + int y = (int) mSprites[index]->mY; #endif - if (doubleWidthChar(ch)) { - if (mIndex) code = mIndex[code]; - size = mFontSize; - src = mExtraFont + code * mBytesPerChar; - offset = 0; - } - else { - size = mFontSize / 2; - src = mStdFont + code * (mFontSize * size / 2); - offset = 0; - } + if (doubleWidthChar(ch)) + { + if (mIndex) code = mIndex[code]; + size = mFontSize; + src = mExtraFont + code * mBytesPerChar; + offset = 0; + } + else + { + size = mFontSize / 2; + src = mStdFont + code * (mFontSize * size / 2); + offset = 0; + } - // set up the font texture buffer - for (unsigned int i = 0; i < mFontSize; i++) { + // set up the font texture buffer + for (unsigned int i = 0; i < mFontSize; i++) + { #if defined (WIN32) || defined (LINUX) - x = 0; + x = 0; #else - x = (int)mSprites[index]->mX; + x = (int) mSprites[index]->mX; #endif - unsigned int j = 0; + unsigned int j = 0; #if 1 - for (; j < offset; j++) { + for (; j < offset; j++) + { #if defined (WIN32) || defined (LINUX) - mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); + mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); #else - SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); + SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); #endif - x++; - } + x++; + } #endif - for (; j < offset + size; j++) { - // as 4-bit(half-byte) stores 1 pixel - // get out the proper data according to the even or odd quality of the counter - gray = src[(i * size + j - offset) / 2]; - gray = ((j - offset) & 1) ? (gray & 0xF0) : ((gray & 0x0F) << 4); - if (gray) gray |= 0x0F; + for (; j < offset + size; j++) + { + // as 4-bit(half-byte) stores 1 pixel + // get out the proper data according to the even or odd quality of the counter + gray = src[(i * size + j - offset) / 2]; + gray = ((j - offset) & 1) ? (gray & 0xF0) : ((gray & 0x0F) << 4); + if (gray) gray |= 0x0F; #if defined (WIN32) || defined (LINUX) - mCharBuffer[y * mFontSize + x] = ARGB(gray, 255, 255, 255); + mCharBuffer[y * mFontSize + x] = ARGB(gray, 255, 255, 255); #else - SwizzlePlot(pTexture, ARGB(gray, 255, 255, 255), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); + SwizzlePlot(pTexture, ARGB(gray, 255, 255, 255), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); #endif - x++; - } - for (; j < mFontSize; j++) { + x++; + } + for (; j < mFontSize; j++) + { #if defined (WIN32) || defined (LINUX) - mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); + mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); #else - SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); + SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); #endif - x++; + x++; + } + y++; } - y++; - } - mGBCode[index] = code; + mGBCode[index] = code; #if defined (WIN32) || defined (LINUX) - x = (int)mSprites[index]->mX; - y = (int)mSprites[index]->mY; - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, mFontSize, mFontSize, GL_RGBA, GL_UNSIGNED_BYTE, mCharBuffer); + x = (int)mSprites[index]->mX; + y = (int)mSprites[index]->mY; + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, mFontSize, mFontSize, GL_RGBA, GL_UNSIGNED_BYTE, mCharBuffer); #else - sceKernelDcacheWritebackAll(); + sceKernelDcacheWritebackAll(); #endif - return index; + return index; } void WFBFont::DrawString(const char *s, float x, float y, int align, float leftOffset, float width) { - u8 * str = (u8 *)s; - if (*str < 0x80) { - // tricky: the single byte font is always mFontID + kSingleByteFontOffset! - // See WResourceManager::InitFonts() - WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); - mFont->SetScale(GetScale()); - mFont->SetColor(GetColor()); - mFont->DrawString(s, x, y, align, leftOffset, width); - return; - } - - // (0, 0) refers to the center of the word, so fix it to the upper-left corner - x += (mFontSize * mScale) / 2; - y += (mFontSize * mScale) / 2; - // Warning : non-left alignment is not supported for multiline strings - // (this is because GetStringWidth is not aware of line breaks). - switch (align) { - case JGETEXT_RIGHT: - x -= GetStringWidth(s); - break; - case JGETEXT_CENTER: - x -= GetStringWidth(s) / 2; - break; - case JGETEXT_LEFT: - default: - break; - } - - mRenderer->BindTexture(mTexture); - - u8 * src = str; - float xx = x; - float yy = y; - int index = 0; - - while (*src != 0) { - if (yy > SCREEN_HEIGHT_F) // don't render or count outside the buttom of viewport - return; - else if (yy + mFontSize < 0.0f) { // don't render when outside the top of viewport, but counted - if (*src < 0x20) { // control characters - if (*src == 0x0a) { // NEWLINE - xx = x; - yy += (mFontSize*mScale); - } - src += 1; - } - else { - xx += (mFontSize*mScale); - - if (xx >= width) { - xx = x; - yy += (mFontSize*mScale); - } - } + u8 * str = (u8 *) s; + if (*str < 0x80) + { + // tricky: the single byte font is always mFontID + kSingleByteFontOffset! + // See WResourceManager::InitFonts() + WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); + mFont->SetScale(GetScale()); + mFont->SetColor(GetColor()); + mFont->DrawString(s, x, y, align, leftOffset, width); + return; } - else { - if (*src < 0x20) { // control characters - if (*src == 0x0a) { // NEWLINE - xx = x; - yy += (mFontSize * mScale); - } - src += 1; - } - else { - int mana = this->GetMana(src); - bool doubleW = doubleWidthChar(src); - index = PreCacheChar(src); - src += charWidth(*src); - // fix for leftoffset and width's setting - float xPos, yPos, charW, charHeight; - mSprites[index]->GetTextureRect(&xPos, &yPos, &charW, &charHeight); - float xPos0 = xPos; - float charW0 = charW; - float delta = doubleW ? (charW * mScale) : (charW * mScale / 2); - if (leftOffset) { - if (leftOffset < 0) { - xx -= leftOffset; - leftOffset = 0; - } - else if (leftOffset - delta > 0) { - leftOffset -= delta; - continue; - } - else { - xPos += leftOffset / mScale; - delta -= leftOffset; - leftOffset = 0; - charW = delta / mScale; - } - } - else if (width) { - if (xx > x + width) + // (0, 0) refers to the center of the word, so fix it to the upper-left corner + x += (mFontSize * mScale) / 2; + y += (mFontSize * mScale) / 2; + // Warning : non-left alignment is not supported for multiline strings + // (this is because GetStringWidth is not aware of line breaks). + switch (align) + { + case JGETEXT_RIGHT: + x -= GetStringWidth(s); + break; + case JGETEXT_CENTER: + x -= GetStringWidth(s) / 2; + break; + case JGETEXT_LEFT: + default: + break; + } + + mRenderer->BindTexture(mTexture); + + u8 * src = str; + float xx = x; + float yy = y; + int index = 0; + + while (*src != 0) + { + if (yy > SCREEN_HEIGHT_F) // don't render or count outside the buttom of viewport return; - if (xx + delta > x + width) { - delta = x + width - xx; - charW = delta / mScale; - } - } - - if (mana >= 0) { - int mana2 = -1; - if (*src == '/' && (mana2 = this->GetMana(src+1)) >= 0) { // hybrid mana cost - src += 1 + charWidth(*src); - unsigned char t = (JGE::GetInstance()->GetTime() / 3) & 0xFF; - unsigned char v = t + 127; - float scale = 0.05f * cosf(2*M_PI*((float)t)/256.0f); - if (scale < 0) { - mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2*M_PI*((float)t)/256.0f), yy + 3 * cosf(2*M_PI*((float)(t-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); - mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2*M_PI*((float)v)/256.0f), yy + 3 * cosf(2*M_PI*((float)(v-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); + else if (yy + mFontSize < 0.0f) + { // don't render when outside the top of viewport, but counted + if (*src < 0x20) + { // control characters + if (*src == 0x0a) + { // NEWLINE + xx = x; + yy += (mFontSize * mScale); + } + src += 1; } - else { - mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2*M_PI*((float)v)/256.0f), yy + 3 * cosf(2*M_PI*((float)(v-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); - mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2*M_PI*((float)t)/256.0f), yy + 3 * cosf(2*M_PI*((float)(t-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); + else + { + xx += (mFontSize * mScale); + + if (xx >= width) + { + xx = x; + yy += (mFontSize * mScale); + } } - mana = Constants::MTG_NB_COLORS + 1; // do not draw colorless cost in hybrid mana cost - } - else - mRenderer->RenderQuad(manaIcons[mana], xx, yy, 0, 0.5f * mScale, 0.5f * mScale); - mRenderer->BindTexture(mTexture); // manaIcons use different texture, so we need to rebind it. } + else + { + if (*src < 0x20) + { // control characters + if (*src == 0x0a) + { // NEWLINE + xx = x; + yy += (mFontSize * mScale); + } + src += 1; + } + else + { + int mana = this->GetMana(src); + bool doubleW = doubleWidthChar(src); + index = PreCacheChar(src); + src += charWidth(*src); - if (mana <= 0) { - mSprites[index]->SetTextureRect(xPos, yPos, charW, charHeight); - mSprites[index]->SetColor(mColor); - mRenderer->RenderQuad(mSprites[index], xx, yy, 0, mScale, mScale); - mSprites[index]->SetTextureRect(xPos0, yPos, charW0, charHeight); + // fix for leftoffset and width's setting + float xPos, yPos, charW, charHeight; + mSprites[index]->GetTextureRect(&xPos, &yPos, &charW, &charHeight); + float xPos0 = xPos; + float charW0 = charW; + float delta = doubleW ? (charW * mScale) : (charW * mScale / 2); + if (leftOffset) + { + if (leftOffset < 0) + { + xx -= leftOffset; + leftOffset = 0; + } + else if (leftOffset - delta > 0) + { + leftOffset -= delta; + continue; + } + else + { + xPos += leftOffset / mScale; + delta -= leftOffset; + leftOffset = 0; + charW = delta / mScale; + } + } + else if (width) + { + if (xx > x + width) return; + if (xx + delta > x + width) + { + delta = x + width - xx; + charW = delta / mScale; + } + } + + if (mana >= 0) + { + int mana2 = -1; + if (*src == '/' && (mana2 = this->GetMana(src + 1)) >= 0) + { // hybrid mana cost + src += 1 + charWidth(*src); + unsigned char t = (JGE::GetInstance()->GetTime() / 3) & 0xFF; + unsigned char v = t + 127; + float scale = 0.05f * cosf(2 * M_PI * ((float) t) / 256.0f); + if (scale < 0) + { + mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2 * M_PI * ((float) t) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (t - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2 * M_PI * ((float) v) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (v - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + } + else + { + mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2 * M_PI * ((float) v) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (v - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2 * M_PI * ((float) t) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (t - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + } + mana = Constants::MTG_NB_COLORS + 1; // do not draw colorless cost in hybrid mana cost + } + else + mRenderer->RenderQuad(manaIcons[mana], xx, yy, 0, 0.5f * mScale, 0.5f * mScale); + mRenderer->BindTexture(mTexture); // manaIcons use different texture, so we need to rebind it. + } + + if (mana <= 0) + { + mSprites[index]->SetTextureRect(xPos, yPos, charW, charHeight); + mSprites[index]->SetColor(mColor); + mRenderer->RenderQuad(mSprites[index], xx, yy, 0, mScale, mScale); + mSprites[index]->SetTextureRect(xPos0, yPos, charW0, charHeight); + } + + xx += delta; + + if (xx >= 480) + { + xx = x; + yy += (mFontSize * mScale); + } + } } - - xx += delta; - - if (xx >= 480) { - xx = x; - yy += (mFontSize * mScale); - } - } } - } } void WFBFont::DrawString(std::string s, float x, float y, int align, float leftOffset, float width) { - DrawString(s.c_str(),x,y,align,leftOffset,width); + DrawString(s.c_str(), x, y, align, leftOffset, width); } void WFBFont::SetColor(PIXEL_TYPE color) { - mColor0 = color; - mColor = gencolor(mFontID, color); + mColor0 = color; + mColor = gencolor(mFontID, color); } float WFBFont::GetStringWidth(const char *s) const { - u8 * src = (u8 *)s; - int width = 0; + u8 * src = (u8 *) s; + int width = 0; - if (doubleWidthChar(src)) { - while (*src != 0) { - // Add the number of single-char widths according to whether - // this is a single or double-width char. - width += (doubleWidthChar(src)) ? 2 : 1; - src += charWidth(*src); + if (doubleWidthChar(src)) + { + while (*src != 0) + { + // Add the number of single-char widths according to whether + // this is a single or double-width char. + width += (doubleWidthChar(src)) ? 2 : 1; + src += charWidth(*src); + } + return width * mFontSize * mScale / 2; + } + else + { + WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); + mFont->SetScale(GetScale()); + return mFont->GetStringWidth(s); } - return width * mFontSize * mScale / 2; - } - else { - WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); - mFont->SetScale(GetScale()); - return mFont->GetStringWidth(s); - } } void WFBFont::SetScale(float scale) { - mScale = scale; + mScale = scale; } -float WFBFont::GetScale() const {return mScale;} -float WFBFont::GetHeight() const {return (mFontSize * mScale);} +float WFBFont::GetScale() const +{ + return mScale; +} +float WFBFont::GetHeight() const +{ + return (mFontSize * mScale); +} // Legacy : GBK encoding WGBKFont::WGBKFont(int inFontID, const char *fontname, int lineheight, bool useVideoRAM) : - WFBFont(inFontID) + WFBFont(inFontID) { - mRenderer = JRenderer::GetInstance(); + mRenderer = JRenderer::GetInstance(); - mCharBuffer = NULL; - mSprites = NULL; - mGBCode = NULL; - mCurr = 0; + mCharBuffer = NULL; + mSprites = NULL; + mGBCode = NULL; + mCurr = 0; - char tmpFileName[32], engFileName[32]; - strcpy(tmpFileName, fontname); - char * ep = strrchr(tmpFileName, '.'); - *ep = '\0'; - sprintf(engFileName, "%s.asc", tmpFileName); - JFileSystem *fileSys = JFileSystem::GetInstance(); - int size = 0; + char tmpFileName[32], engFileName[32]; + strcpy(tmpFileName, fontname); + char * ep = strrchr(tmpFileName, '.'); + *ep = '\0'; + sprintf(engFileName, "%s.asc", tmpFileName); + JFileSystem *fileSys = JFileSystem::GetInstance(); + int size = 0; - if (!fileSys->OpenFile(fontname)) - return; - size = fileSys->GetFileSize(); - mExtraFont = NEW u8[size]; - fileSys->ReadFile(mExtraFont, size); - fileSys->CloseFile(); + if (!fileSys->OpenFile(fontname)) return; + size = fileSys->GetFileSize(); + mExtraFont = NEW u8[size]; + fileSys->ReadFile(mExtraFont, size); + fileSys->CloseFile(); - if (!fileSys->OpenFile(engFileName)) - return; - size = fileSys->GetFileSize(); - mStdFont = NEW u8[size]; - fileSys->ReadFile(mStdFont, size); - fileSys->CloseFile(); + if (!fileSys->OpenFile(engFileName)) return; + size = fileSys->GetFileSize(); + mStdFont = NEW u8[size]; + fileSys->ReadFile(mStdFont, size); + fileSys->CloseFile(); - mIndex = 0; + mIndex = 0; - mColor0 = ARGB(255, 255, 255, 255); - mColor = mColor0; - mFontSize = lineheight; - mScale = 1.0f; + mColor0 = ARGB(255, 255, 255, 255); + mColor = mColor0; + mFontSize = lineheight; + mScale = 1.0f; - // using 4-bit(half-byte) to store 1 pixel - mBytesPerRow = static_cast(mFontSize / 2); - mBytesPerChar = static_cast(mBytesPerRow*mFontSize); + // using 4-bit(half-byte) to store 1 pixel + mBytesPerRow = static_cast (mFontSize / 2); + mBytesPerChar = static_cast (mBytesPerRow * mFontSize); - mCacheImageWidth = 256; - mCacheImageHeight = 256; - mCol = mCacheImageWidth / mFontSize; - mRow = mCacheImageHeight / mFontSize; - mCacheSize = mCol * mRow; + mCacheImageWidth = 256; + mCacheImageHeight = 256; + mCol = mCacheImageWidth / mFontSize; + mRow = mCacheImageHeight / mFontSize; + mCacheSize = mCol * mRow; - mSprites = NEW JQuad*[mCacheSize]; - mGBCode = NEW int[mCacheSize]; + mSprites = NEW JQuad*[mCacheSize]; + mGBCode = NEW int[mCacheSize]; #if defined (WIN32) || defined (LINUX) - mCharBuffer = NEW u32[mFontSize*mFontSize]; + mCharBuffer = NEW u32[mFontSize*mFontSize]; #endif - mTexture = mRenderer->CreateTexture(mCacheImageWidth, mCacheImageHeight, true); + mTexture = mRenderer->CreateTexture(mCacheImageWidth, mCacheImageHeight, true); - int index = 0; - for (int y = 0; y < mRow; y++) { - for (int x = 0; x < mCol; x++) { - mGBCode[index] = -1; - mSprites[index] = NEW JQuad(mTexture, - static_cast(x*mFontSize), - static_cast(y*mFontSize), - static_cast(mFontSize), - static_cast(mFontSize)); - mSprites[index]->SetHotSpot(static_cast(mFontSize / 2), static_cast(mFontSize / 2)); - index++; + int index = 0; + for (int y = 0; y < mRow; y++) + { + for (int x = 0; x < mCol; x++) + { + mGBCode[index] = -1; + mSprites[index] = NEW JQuad(mTexture, static_cast (x * mFontSize), static_cast (y * mFontSize), + static_cast (mFontSize), static_cast (mFontSize)); + mSprites[index]->SetHotSpot(static_cast (mFontSize / 2), static_cast (mFontSize / 2)); + index++; + } } - } } int WGBKFont::PreCacheChar(const u8 *ch) { - int code; - int charLength = 1; - u8 * src; - unsigned int size, offset; - u8 gray; + int code; + int charLength = 1; + u8 * src; + unsigned int size, offset; + u8 gray; #if 0 - if (*ch > 0xA0 && *(ch + 1) > 0xA0) { - // get offset to the proper character bits (GB2312 encoding) - code = (((u32)(*ch - 0xA1)) * 0x5E + ((u32)(*(ch + 1) - 0xA1))); - charLength = 2; - } - else if (*ch > 0x80) { - // get offset to the character space's bits (GBK encoding) - code = 0; - charLength = 2; - } - else { - code = ((u32)*ch); - charLength = 1; - } + if (*ch > 0xA0 && *(ch + 1) > 0xA0) + { + // get offset to the proper character bits (GB2312 encoding) + code = (((u32)(*ch - 0xA1)) * 0x5E + ((u32)(*(ch + 1) - 0xA1))); + charLength = 2; + } + else if (*ch > 0x80) + { + // get offset to the character space's bits (GBK encoding) + code = 0; + charLength = 2; + } + else + { + code = ((u32)*ch); + charLength = 1; + } #else - code = this->GetCode(ch, &charLength); + code = this->GetCode(ch, &charLength); #endif - if (mGBCode[mCurr] != -1) - for (int i = 0; i < mCacheSize; i++) - if (mGBCode[i] == code) - return i; + if (mGBCode[mCurr] != -1) for (int i = 0; i < mCacheSize; i++) + if (mGBCode[i] == code) return i; - int index = mCurr++; - if (mCurr >= mCacheSize) - mCurr = 0; + int index = mCurr++; + if (mCurr >= mCacheSize) mCurr = 0; #if defined (WIN32) || defined (LINUX) - int x = 0; - int y = 0; - memset(mCharBuffer, 0, sizeof(u32) * mFontSize * mFontSize); + int x = 0; + int y = 0; + memset(mCharBuffer, 0, sizeof(u32) * mFontSize * mFontSize); #else - u8* pTexture = (u8*) mTexture->mBits; - int x; - int y = (int)mSprites[index]->mY; + u8* pTexture = (u8*) mTexture->mBits; + int x; + int y = (int) mSprites[index]->mY; #endif - if (mIndex) code = mIndex[code]; + if (mIndex) code = mIndex[code]; - if (GBKDoubleWidthChar(ch)) { - size = mFontSize; - src = mExtraFont + code * mBytesPerChar; - offset = 0; - } - else { - size = mFontSize / 2; - src = mStdFont + code * (mFontSize * size / 2); - offset = 0; - } + if (GBKDoubleWidthChar(ch)) + { + size = mFontSize; + src = mExtraFont + code * mBytesPerChar; + offset = 0; + } + else + { + size = mFontSize / 2; + src = mStdFont + code * (mFontSize * size / 2); + offset = 0; + } - // set up the font texture buffer - for (unsigned int i = 0; i < mFontSize; i++) { + // set up the font texture buffer + for (unsigned int i = 0; i < mFontSize; i++) + { #if defined (WIN32) || defined (LINUX) - x = 0; + x = 0; #else - x = (int)mSprites[index]->mX; + x = (int) mSprites[index]->mX; #endif - unsigned int j = 0; + unsigned int j = 0; #if 1 - for (; j < offset; j++) { + for (; j < offset; j++) + { #if defined (WIN32) || defined (LINUX) - mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); + mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); #else - SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); + SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); #endif - x++; - } + x++; + } #endif - for (; j < offset + size; j++) { - // as 4-bit(half-byte) stores 1 pixel - // get out the proper data according to the even or odd quality of the counter - gray = src[(i * size + j - offset) / 2]; - gray = ((j - offset) & 1) ? (gray & 0xF0) : ((gray & 0x0F) << 4); - if (gray) gray |= 0x0F; + for (; j < offset + size; j++) + { + // as 4-bit(half-byte) stores 1 pixel + // get out the proper data according to the even or odd quality of the counter + gray = src[(i * size + j - offset) / 2]; + gray = ((j - offset) & 1) ? (gray & 0xF0) : ((gray & 0x0F) << 4); + if (gray) gray |= 0x0F; #if defined (WIN32) || defined (LINUX) - mCharBuffer[y * mFontSize + x] = ARGB(gray, 255, 255, 255); + mCharBuffer[y * mFontSize + x] = ARGB(gray, 255, 255, 255); #else - SwizzlePlot(pTexture, ARGB(gray, 255, 255, 255), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); + SwizzlePlot(pTexture, ARGB(gray, 255, 255, 255), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); #endif - x++; - } - for (; j < mFontSize; j++) { + x++; + } + for (; j < mFontSize; j++) + { #if defined (WIN32) || defined (LINUX) - mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); + mCharBuffer[y * mFontSize + x] = ARGB(0, 0, 0, 0); #else - SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); + SwizzlePlot(pTexture, ARGB(0, 0, 0, 0), x * PIXEL_SIZE, y, mTexture->mTexWidth * PIXEL_SIZE); #endif - x++; + x++; + } + y++; } - y++; - } - mGBCode[index] = code; + mGBCode[index] = code; #if defined (WIN32) || defined (LINUX) - x = (int)mSprites[index]->mX; - y = (int)mSprites[index]->mY; - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, mFontSize, mFontSize, GL_RGBA, GL_UNSIGNED_BYTE, mCharBuffer); + x = (int)mSprites[index]->mX; + y = (int)mSprites[index]->mY; + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, mFontSize, mFontSize, GL_RGBA, GL_UNSIGNED_BYTE, mCharBuffer); #else - sceKernelDcacheWritebackAll(); + sceKernelDcacheWritebackAll(); #endif - return index; + return index; } void WGBKFont::DrawString(const char *s, float x, float y, int align, float leftOffset, float width) { - unsigned char c = *(unsigned short *)s & 0xFF; - if (ISGBK(c) || (s[1] == ':' && s[2] == ' ')) {} - else { - // tricky: the single byte font is always mFontID + kSingleByteFontOffset! - // See WResourceManager::InitFonts() - WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); - mFont->SetScale(GetScale()); - mFont->SetColor(GetColor()); - mFont->DrawString(s, x, y, align, leftOffset, width); - return; - } - - u8 * str = (u8 *)s; - - // (0, 0) refers to the center of the word, so fix it to the upper-left corner - x += (mFontSize * mScale) / 2; - y += (mFontSize * mScale) / 2; - switch (align) { - case JGETEXT_RIGHT: - x -= GetStringWidth(s); - break; - case JGETEXT_CENTER: - x -= GetStringWidth(s) / 2; - break; - case JGETEXT_LEFT: - default: - break; - } - - mRenderer->BindTexture(mTexture); - - u8 * src = str; - float xx = x; - float yy = y; - int index = 0; - - bool dualByteFont=true; - - while (*src != 0) { - if (yy > SCREEN_HEIGHT_F) // don't render or count outside the buttom of viewport - return; - else if (yy + mFontSize < 0.0f) { // don't render when outside the top of viewport, but counted - if (*src < 0x20) { // control characters - if (*src == 0x0a) { // NEWLINE - xx = x; - yy += (mFontSize*mScale); - } - src += 1; - } - else { - if (*src > 0x80) // 2-bytes char - src += 2; - else - src += 1; - - xx += (mFontSize*mScale); - - if (xx >= 480) { - xx = x; - yy += (mFontSize*mScale); - } - } + unsigned char c = *(unsigned short *) s & 0xFF; + if (ISGBK(c) || (s[1] == ':' && s[2] == ' ')) + { + } + else + { + // tricky: the single byte font is always mFontID + kSingleByteFontOffset! + // See WResourceManager::InitFonts() + WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); + mFont->SetScale(GetScale()); + mFont->SetColor(GetColor()); + mFont->DrawString(s, x, y, align, leftOffset, width); + return; } - else { - if (*src < 0x20) { // control characters - if (*src == 0x0a) { // NEWLINE - xx = x; - yy += (mFontSize * mScale); - } - src += 1; - } - else { - int mana = -1; - if (*src > 0x80) { // 2-bytes char - mana = this->GetMana(src); - index = PreCacheChar(src); - src += 2; - dualByteFont = true; - } - else { - index = PreCacheChar(src); - src += 1; - dualByteFont = false; - } - // fix for leftoffset and witdth's setting - float xPos, yPos, charW, charHeight; - mSprites[index]->GetTextureRect(&xPos, &yPos, &charW, &charHeight); - float xPos0 = xPos; - float charW0 = charW; - float delta = (dualByteFont) ? (charW * mScale) : (charW * mScale / 2); - if (leftOffset) { - if (leftOffset < 0) { - xx -= leftOffset; - leftOffset = 0; - } - else if (leftOffset - delta > 0) { - leftOffset -= delta; - continue; - } - else { - xPos += leftOffset / mScale; - delta -= leftOffset; - leftOffset = 0; - charW = delta / mScale; - } - } - else if (width) { - if (xx > x + width) + u8 * str = (u8 *) s; + + // (0, 0) refers to the center of the word, so fix it to the upper-left corner + x += (mFontSize * mScale) / 2; + y += (mFontSize * mScale) / 2; + switch (align) + { + case JGETEXT_RIGHT: + x -= GetStringWidth(s); + break; + case JGETEXT_CENTER: + x -= GetStringWidth(s) / 2; + break; + case JGETEXT_LEFT: + default: + break; + } + + mRenderer->BindTexture(mTexture); + + u8 * src = str; + float xx = x; + float yy = y; + int index = 0; + + bool dualByteFont = true; + + while (*src != 0) + { + if (yy > SCREEN_HEIGHT_F) // don't render or count outside the buttom of viewport return; - if (xx + delta > x + width) { - delta = x + width - xx; - charW = delta / mScale; - } - } - - if (mana >= 0) { - int mana2 = -1; - if (*src == '/' && (mana2 = this->GetMana(src+1)) >= 0) { // hybrid mana cost - src += 3; - unsigned char t = (JGE::GetInstance()->GetTime() / 3) & 0xFF; - unsigned char v = t + 127; - float scale = 0.05f * cosf(2*M_PI*((float)t)/256.0f); - if (scale < 0) { - mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2*M_PI*((float)t)/256.0f), yy + 3 * cosf(2*M_PI*((float)(t-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); - mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2*M_PI*((float)v)/256.0f), yy + 3 * cosf(2*M_PI*((float)(v-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); + else if (yy + mFontSize < 0.0f) + { // don't render when outside the top of viewport, but counted + if (*src < 0x20) + { // control characters + if (*src == 0x0a) + { // NEWLINE + xx = x; + yy += (mFontSize * mScale); + } + src += 1; } - else { - mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2*M_PI*((float)v)/256.0f), yy + 3 * cosf(2*M_PI*((float)(v-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); - mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2*M_PI*((float)t)/256.0f), yy + 3 * cosf(2*M_PI*((float)(t-35))/256.0f), 0, 0.5f * mScale, 0.5f * mScale); + else + { + if (*src > 0x80) // 2-bytes char + src += 2; + else + src += 1; + + xx += (mFontSize * mScale); + + if (xx >= 480) + { + xx = x; + yy += (mFontSize * mScale); + } } - mana = Constants::MTG_NB_COLORS + 1; // donot draw colorless cost in hybrid mana cost - } - else - mRenderer->RenderQuad(manaIcons[mana], xx, yy, 0, 0.5f * mScale, 0.5f * mScale); - mRenderer->BindTexture(mTexture); // manaIcons use different texture, so we need to rebind it. } + else + { + if (*src < 0x20) + { // control characters + if (*src == 0x0a) + { // NEWLINE + xx = x; + yy += (mFontSize * mScale); + } + src += 1; + } + else + { + int mana = -1; + if (*src > 0x80) + { // 2-bytes char + mana = this->GetMana(src); + index = PreCacheChar(src); + src += 2; + dualByteFont = true; + } + else + { + index = PreCacheChar(src); + src += 1; + dualByteFont = false; + } - if (mana <= 0) { - mSprites[index]->SetTextureRect(xPos, yPos, charW, charHeight); - mSprites[index]->SetColor(mColor); - mRenderer->RenderQuad(mSprites[index], xx, yy, 0, mScale, mScale); - mSprites[index]->SetTextureRect(xPos0, yPos, charW0, charHeight); + // fix for leftoffset and witdth's setting + float xPos, yPos, charW, charHeight; + mSprites[index]->GetTextureRect(&xPos, &yPos, &charW, &charHeight); + float xPos0 = xPos; + float charW0 = charW; + float delta = (dualByteFont) ? (charW * mScale) : (charW * mScale / 2); + if (leftOffset) + { + if (leftOffset < 0) + { + xx -= leftOffset; + leftOffset = 0; + } + else if (leftOffset - delta > 0) + { + leftOffset -= delta; + continue; + } + else + { + xPos += leftOffset / mScale; + delta -= leftOffset; + leftOffset = 0; + charW = delta / mScale; + } + } + else if (width) + { + if (xx > x + width) return; + if (xx + delta > x + width) + { + delta = x + width - xx; + charW = delta / mScale; + } + } + + if (mana >= 0) + { + int mana2 = -1; + if (*src == '/' && (mana2 = this->GetMana(src + 1)) >= 0) + { // hybrid mana cost + src += 3; + unsigned char t = (JGE::GetInstance()->GetTime() / 3) & 0xFF; + unsigned char v = t + 127; + float scale = 0.05f * cosf(2 * M_PI * ((float) t) / 256.0f); + if (scale < 0) + { + mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2 * M_PI * ((float) t) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (t - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2 * M_PI * ((float) v) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (v - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + } + else + { + mRenderer->RenderQuad(manaIcons[mana2], xx + 3 * sinf(2 * M_PI * ((float) v) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (v - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + mRenderer->RenderQuad(manaIcons[mana], xx + 3 * sinf(2 * M_PI * ((float) t) / 256.0f), yy + 3 * cosf(2 + * M_PI * ((float) (t - 35)) / 256.0f), 0, 0.5f * mScale, 0.5f * mScale); + } + mana = Constants::MTG_NB_COLORS + 1; // donot draw colorless cost in hybrid mana cost + } + else + mRenderer->RenderQuad(manaIcons[mana], xx, yy, 0, 0.5f * mScale, 0.5f * mScale); + mRenderer->BindTexture(mTexture); // manaIcons use different texture, so we need to rebind it. + } + + if (mana <= 0) + { + mSprites[index]->SetTextureRect(xPos, yPos, charW, charHeight); + mSprites[index]->SetColor(mColor); + mRenderer->RenderQuad(mSprites[index], xx, yy, 0, mScale, mScale); + mSprites[index]->SetTextureRect(xPos0, yPos, charW0, charHeight); + } + + xx += delta; + + if (xx >= 480) + { + xx = x; + yy += (mFontSize * mScale); + } + } } - - xx += delta; - - if (xx >= 480) { - xx = x; - yy += (mFontSize * mScale); - } - } } - } } float WGBKFont::GetStringWidth(const char *s) const { - unsigned char c = *(unsigned short *)s & 0xFF; + unsigned char c = *(unsigned short *) s & 0xFF; - if (ISGBK(c)) { - u8 * src = (u8 *)s; - float xx = 0; - bool dualByteFont = true; + if (ISGBK(c)) + { + u8 * src = (u8 *) s; + float xx = 0; + bool dualByteFont = true; - while (*src != 0) { - if (*src > 0x80) { // Chinese and Japanese - src += 2; - dualByteFont = true; - } - else { // Latin 1 - src += 1; - dualByteFont = false; - } - if (dualByteFont) - xx += (mFontSize * mScale); - else - xx += (mFontSize * mScale) / 2; + while (*src != 0) + { + if (*src > 0x80) + { // Chinese and Japanese + src += 2; + dualByteFont = true; + } + else + { // Latin 1 + src += 1; + dualByteFont = false; + } + if (dualByteFont) + xx += (mFontSize * mScale); + else + xx += (mFontSize * mScale) / 2; + } + return xx; + } + else + { + WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); + mFont->SetScale(GetScale()); + return mFont->GetStringWidth(s); } - return xx; - } - else { - WFont * mFont = resources.GetWFont(mFontID + Fonts::kSingleByteFontOffset); - mFont->SetScale(GetScale()); - return mFont->GetStringWidth(s); - } } int WGBKFont::GetCode(const u8 *ch, int *charLength) const { - int code = 0; - *charLength = 2; + int code = 0; + *charLength = 2; - if (*ch > 0xA0 && *(ch + 1) > 0xA0) { - // get offset to the proper character bits (GB2312 encoding) - code = (((u32)(*ch - 0xA1)) * 0x5E + ((u32)(*(ch + 1) - 0xA1))); - } - else if (*ch > 0x80) { - // get offset to the character space's bits (GBK encoding) - code = 0; - } - else { - code = ((u32)*ch); - *charLength = 1; - } - return code; + if (*ch > 0xA0 && *(ch + 1) > 0xA0) + { + // get offset to the proper character bits (GB2312 encoding) + code = (((u32)(*ch - 0xA1)) * 0x5E + ((u32)(*(ch + 1) - 0xA1))); + } + else if (*ch > 0x80) + { + // get offset to the character space's bits (GBK encoding) + code = 0; + } + else + { + code = ((u32) * ch); + *charLength = 1; + } + return code; } int WGBKFont::GetMana(const u8 *ch) const { - int mana = -1; + int mana = -1; - if (*ch != 0xa3) return mana; - switch (*(ch+1)) { - case 0xC7: - mana = Constants::MTG_COLOR_GREEN; - break; - case 0xD5: - mana = Constants::MTG_COLOR_BLUE; - break; - case 0xD2: - mana = Constants::MTG_COLOR_RED; - break; - case 0xC2: - mana = Constants::MTG_COLOR_BLACK; - break; - case 0xD7: - mana = Constants::MTG_COLOR_WHITE; - break; - case 0xD4: // T - case 0xD8: // X - case 0xD9: // Y - mana = Constants::MTG_UNCOLORED; - break; - default: - if (*(ch+1) >= 0xB0 && *(ch+1) <= 0xB9) - mana = Constants::MTG_UNCOLORED; - } - return mana; + if (*ch != 0xa3) return mana; + switch (*(ch + 1)) + { + case 0xC7: + mana = Constants::MTG_COLOR_GREEN; + break; + case 0xD5: + mana = Constants::MTG_COLOR_BLUE; + break; + case 0xD2: + mana = Constants::MTG_COLOR_RED; + break; + case 0xC2: + mana = Constants::MTG_COLOR_BLACK; + break; + case 0xD7: + mana = Constants::MTG_COLOR_WHITE; + break; + case 0xD4: // T + case 0xD8: // X + case 0xD9: // Y + mana = Constants::MTG_UNCOLORED; + break; + default: + if (*(ch + 1) >= 0xB0 && *(ch + 1) <= 0xB9) mana = Constants::MTG_UNCOLORED; + } + return mana; } int WUFont::GetCode(const u8 *ch, int *charLength) const { - int code = 0; + int code = 0; - // This assumes the string is valid. We could test for - // validity by ensuring all trailing bytes are & 0xC0 == F0 - // and that no first byte is. + // This assumes the string is valid. We could test for + // validity by ensuring all trailing bytes are & 0xC0 == F0 + // and that no first byte is. - // For a description of the binary representation, look at wikipedia://utf-8 + // For a description of the binary representation, look at wikipedia://utf-8 - if ((*ch & 0xF8) == 0xF0) { // Four bytes - *charLength = 4; - code = ((*ch * 0x7) << 18) + ((*(ch+1) & 0x3F) << 12) + ((*(ch+2) & 0x3F) << 6) + ((*(ch+3) * 0x3F)); - } - else if ((*ch & 0xF0) == 0xE0) { // Three bytes - *charLength = 3; - code = ((*ch & 0xF) << 12) + ((*(ch+1) & 0x3F) << 6) + ((*(ch+2) & 0x3F)); - } - else if ((*ch & 0xE0) == 0xC0) { // Two bytes - *charLength = 2; - code = ((*ch & 0x1F) << 6) + ((*(ch+2) & 0x3F)); - } - else { - *charLength = 1; - code = *ch; - } - return code; + if ((*ch & 0xF8) == 0xF0) + { // Four bytes + *charLength = 4; + code = ((*ch * 0x7) << 18) + ((*(ch + 1) & 0x3F) << 12) + ((*(ch + 2) & 0x3F) << 6) + ((*(ch + 3) * 0x3F)); + } + else if ((*ch & 0xF0) == 0xE0) + { // Three bytes + *charLength = 3; + code = ((*ch & 0xF) << 12) + ((*(ch + 1) & 0x3F) << 6) + ((*(ch + 2) & 0x3F)); + } + else if ((*ch & 0xE0) == 0xC0) + { // Two bytes + *charLength = 2; + code = ((*ch & 0x1F) << 6) + ((*(ch + 2) & 0x3F)); + } + else + { + *charLength = 1; + code = *ch; + } + return code; } int WUFont::GetMana(const u8 *ch) const { - /* - * Reactivate the following code to be able to use - * single-width characters too, if needed. - **/ - /* - switch (*ch) + /* + * Reactivate the following code to be able to use + * single-width characters too, if needed. + **/ + /* + switch (*ch) + { + case 0x67: return Constants::MTG_COLOR_GREEN; + case 0x75: return Constants::MTG_COLOR_BLUE; + case 0x72: return Constants::MTG_COLOR_RED; + case 0x62: return Constants::MTG_COLOR_BLACK; + case 0x77: return Constants::MTG_COLOR_WHITE; + case 0x74: + case 0x78: + case 0x79: return Constants::MTG_UNCOLORED; + default: + if (*ch >= 0x30 && *ch <= 0x39) + return Constants::MTG_UNCOLORED; + } + */ + if (*ch != 0xef || *(ch + 1) != 0xbc) return -1; + ch += 2; + switch (*ch) { - case 0x67: return Constants::MTG_COLOR_GREEN; - case 0x75: return Constants::MTG_COLOR_BLUE; - case 0x72: return Constants::MTG_COLOR_RED; - case 0x62: return Constants::MTG_COLOR_BLACK; - case 0x77: return Constants::MTG_COLOR_WHITE; - case 0x74: - case 0x78: - case 0x79: return Constants::MTG_UNCOLORED; + case 0xa7: // G : 0xefbca7 + return Constants::MTG_COLOR_GREEN; + case 0xb5: // U : 0xefbcb5 + return Constants::MTG_COLOR_BLUE; + case 0xb2: // R : 0xefbcb2 + return Constants::MTG_COLOR_RED; + case 0xa2: // B : 0xefbca2 + return Constants::MTG_COLOR_BLACK; + case 0xb7: // W : 0xefbcb7 + return Constants::MTG_COLOR_WHITE; + case 0xb4: // T : 0xefbcb4 + case 0xb8: // X : 0xefbcb8 + case 0xb9: // Y : 0xefbcb9 + return Constants::MTG_UNCOLORED; default: - if (*ch >= 0x30 && *ch <= 0x39) - return Constants::MTG_UNCOLORED; + if (*ch >= 0x90 && *ch <= 0x99) return Constants::MTG_UNCOLORED; } - */ - if (*ch != 0xef || *(ch+1) != 0xbc) return -1; - ch += 2; - switch (*ch) { - case 0xa7: // G : 0xefbca7 - return Constants::MTG_COLOR_GREEN; - case 0xb5: // U : 0xefbcb5 - return Constants::MTG_COLOR_BLUE; - case 0xb2: // R : 0xefbcb2 - return Constants::MTG_COLOR_RED; - case 0xa2: // B : 0xefbca2 - return Constants::MTG_COLOR_BLACK; - case 0xb7: // W : 0xefbcb7 - return Constants::MTG_COLOR_WHITE; - case 0xb4: // T : 0xefbcb4 - case 0xb8: // X : 0xefbcb8 - case 0xb9: // Y : 0xefbcb9 - return Constants::MTG_UNCOLORED; - default: - if (*ch >= 0x90 && *ch <= 0x99) - return Constants::MTG_UNCOLORED; - } - return -1; + return -1; } diff --git a/projects/mtg/src/WGui.cpp b/projects/mtg/src/WGui.cpp index 96229c6c1..0cd4e9fca 100644 --- a/projects/mtg/src/WGui.cpp +++ b/projects/mtg/src/WGui.cpp @@ -8,1957 +8,2212 @@ #include //WGuiBase -PIXEL_TYPE WGuiBase::getColor(int type){ - switch(type){ +PIXEL_TYPE WGuiBase::getColor(int type) +{ + switch (type) + { case WGuiColor::TEXT_BODY: case WGuiColor::SCROLLBUTTON: - return ARGB(255,255,255,255); + return ARGB(255,255,255,255); case WGuiColor::SCROLLBAR: - return ARGB(150,50,50,50); + return ARGB(150,50,50,50); case WGuiColor::BACK_HEADER: - return ARGB(150,80,80,80); + return ARGB(150,80,80,80); default: - if(type < WGuiColor::BACK){ - if(hasFocus()) - return ARGB(255,255,255,0); + if (type < WGuiColor::BACK) + { + if (hasFocus()) + return ARGB(255,255,255,0); + else + return ARGB(255,255,255,255); + } + else if (hasFocus()) + return ARGB(150,200,200,200); else - return ARGB(255,255,255,255); - } - else - if(hasFocus()) - return ARGB(150,200,200,200); - else - return ARGB(150,50,50,50); - } - return ARGB(150,50,50,50); -} - - -void WGuiBase::renderBack(WGuiBase * it){ - if(!it) return; - WDecoStyled * styled = dynamic_cast(it); - if(styled) - styled->renderBack(styled->getDecorated()); - else - subBack(it); -} -WGuiBase::CONFIRM_TYPE WGuiBase::needsConfirm() { - for (vector::iterator it = items.begin(); it != items.end(); ++it) { - switch((*it)->needsConfirm()) { - case CONFIRM_NEED: return CONFIRM_NEED; - case CONFIRM_CANCEL: return CONFIRM_CANCEL; - case CONFIRM_OK: /* Nothing special : continue iteration */ ; + return ARGB(150,50,50,50); } - } - return CONFIRM_OK; -} -bool WGuiBase::yieldFocus() { - for (vector::iterator it = items.begin(); it != items.end(); ++it) - if ((*it)->yieldFocus()) { return true; } - return false; + return ARGB(150,50,50,50); } +void WGuiBase::renderBack(WGuiBase * it) +{ + if (!it) return; + WDecoStyled * styled = dynamic_cast (it); + if (styled) + styled->renderBack(styled->getDecorated()); + else + subBack(it); +} +WGuiBase::CONFIRM_TYPE WGuiBase::needsConfirm() +{ + for (vector::iterator it = items.begin(); it != items.end(); ++it) + { + switch ((*it)->needsConfirm()) + { + case CONFIRM_NEED: + return CONFIRM_NEED; + case CONFIRM_CANCEL: + return CONFIRM_CANCEL; + case CONFIRM_OK: /* Nothing special : continue iteration */ + ; + } + } + return CONFIRM_OK; +} +bool WGuiBase::yieldFocus() +{ + for (vector::iterator it = items.begin(); it != items.end(); ++it) + if ((*it)->yieldFocus()) + { + return true; + } + return false; +} //WGuiItem -void WGuiItem::Entering(JButton key){ - mFocus = true; -} -float WGuiItem::minWidth(){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - return mFont->GetStringWidth(_(displayValue).c_str())+4; +void WGuiItem::Entering(JButton key) +{ + mFocus = true; } -float WGuiItem::minHeight(){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - return mFont->GetHeight(); +float WGuiItem::minWidth() +{ + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + return mFont->GetStringWidth(_(displayValue).c_str()) + 4; +} +float WGuiItem::minHeight() +{ + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + return mFont->GetHeight(); } -bool WGuiItem::Leaving(JButton key){ - mFocus = false; - return true; -} - -void WGuiItem::Render(){ - JRenderer * renderer = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - DWORD oldcolor = mFont->GetColor(); - mFont->SetColor(getColor(WGuiColor::TEXT)); - float fH = (height-mFont->GetHeight())/2; - string trans = _(displayValue); - float fW = mFont->GetStringWidth(trans.c_str()); - float boxW = getWidth(); - float oldS = mFont->GetScale(); - if(fW > boxW){ - mFont->SetScale(boxW/fW); - } - mFont->DrawString(trans,x+(width/2),y+fH,JGETEXT_CENTER); - mFont->SetScale(oldS); - mFont->SetColor(oldcolor); -} - -WGuiItem::WGuiItem(string _display, u8 _mF){ - mFlags=_mF; - displayValue = _display; - mFocus = false; - width=SCREEN_WIDTH; - height=20; - x=0; - y=0; -} - -string WGuiItem::_(string input){ - if(mFlags & WGuiItem::NO_TRANSLATE) - return input; - return ::_(input); -} -bool WGuiItem::CheckUserInput(JButton key){ - if(mFocus && key == JGE_BTN_OK){ - updateValue(); +bool WGuiItem::Leaving(JButton key) +{ + mFocus = false; return true; - } - return false; +} + +void WGuiItem::Render() +{ + JRenderer * renderer = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + DWORD oldcolor = mFont->GetColor(); + mFont->SetColor(getColor(WGuiColor::TEXT)); + float fH = (height - mFont->GetHeight()) / 2; + string trans = _(displayValue); + float fW = mFont->GetStringWidth(trans.c_str()); + float boxW = getWidth(); + float oldS = mFont->GetScale(); + if (fW > boxW) + { + mFont->SetScale(boxW / fW); + } + mFont->DrawString(trans, x + (width / 2), y + fH, JGETEXT_CENTER); + mFont->SetScale(oldS); + mFont->SetColor(oldcolor); +} + +WGuiItem::WGuiItem(string _display, u8 _mF) +{ + mFlags = _mF; + displayValue = _display; + mFocus = false; + width = SCREEN_WIDTH; + height = 20; + x = 0; + y = 0; +} + +string WGuiItem::_(string input) +{ + if (mFlags & WGuiItem::NO_TRANSLATE) return input; + return ::_(input); +} +bool WGuiItem::CheckUserInput(JButton key) +{ + if (mFocus && key == JGE_BTN_OK) + { + updateValue(); + return true; + } + return false; } //WDecoStyled -void WDecoStyled::subBack(WGuiBase * item){ - if(!item) - return; - JRenderer * renderer = JRenderer::GetInstance(); - if(mStyle & DS_STYLE_BACKLESS) - return; - //TODO: if(mStyle & DS_STYLE_EDGED) Draw the edged box ala SimpleMenu - else{ //Draw standard style - WGuiSplit * split = dynamic_cast(item); - if(split && split->left->Visible() && split->right->Visible()){ - if(split->left) - renderer->FillRoundRect(split->left->getX()-2,split->getY()-2,split->left->getWidth()-6,split->getHeight(),2,split->left->getColor(WGuiColor::BACK)); - if(split->right) - renderer->FillRoundRect(split->right->getX()-2,split->getY()-2,split->right->getWidth(),split->getHeight(),2,split->right->getColor(WGuiColor::BACK)); +void WDecoStyled::subBack(WGuiBase * item) +{ + if (!item) return; + JRenderer * renderer = JRenderer::GetInstance(); + if (mStyle & DS_STYLE_BACKLESS) + return; + //TODO: if(mStyle & DS_STYLE_EDGED) Draw the edged box ala SimpleMenu + else + { //Draw standard style + WGuiSplit * split = dynamic_cast (item); + if (split && split->left->Visible() && split->right->Visible()) + { + if (split->left) renderer->FillRoundRect(split->left->getX() - 2, split->getY() - 2, split->left->getWidth() - 6, + split->getHeight(), 2, split->left->getColor(WGuiColor::BACK)); + if (split->right) renderer->FillRoundRect(split->right->getX() - 2, split->getY() - 2, split->right->getWidth(), + split->getHeight(), 2, split->right->getColor(WGuiColor::BACK)); + } + else + { + renderer->FillRoundRect(item->getX() - 2, item->getY() - 2, item->getWidth(), item->getHeight(), 2, getColor( + WGuiColor::BACK)); + } } - else{ - renderer->FillRoundRect(item->getX()-2,item->getY()-2,item->getWidth(),item->getHeight(),2,getColor(WGuiColor::BACK)); - } - } - + } -PIXEL_TYPE WDecoStyled::getColor(int type){ - switch(type){ +PIXEL_TYPE WDecoStyled::getColor(int type) +{ + switch (type) + { case WGuiColor::BACK: case WGuiColor::BACK_HEADER: - if(mStyle & DS_COLOR_DARK) - return ARGB(150,35,35,35); - else if(mStyle & DS_COLOR_BRIGHT) - return ARGB(150,80,80,80); - else if(mStyle & DS_STYLE_ALERT) - return ARGB(150,120,80,80); - else - return ARGB(150,50,50,50); + if (mStyle & DS_COLOR_DARK) + return ARGB(150,35,35,35); + else if (mStyle & DS_COLOR_BRIGHT) + return ARGB(150,80,80,80); + else if (mStyle & DS_STYLE_ALERT) + return ARGB(150,120,80,80); + else + return ARGB(150,50,50,50); default: - return WGuiBase::getColor(type); - } - return ARGB(150,50,50,50); + return WGuiBase::getColor(type); + } + return ARGB(150,50,50,50); } //WGuiHeader -void WGuiHeader::Render(){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT)); - - JRenderer * renderer = JRenderer::GetInstance(); - mFont->DrawString(_(displayValue).c_str(),x+width/2,y,JGETEXT_CENTER); +void WGuiHeader::Render() +{ + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT)); + + JRenderer * renderer = JRenderer::GetInstance(); + mFont->DrawString(_(displayValue).c_str(), x + width / 2, y, JGETEXT_CENTER); } +bool WGuiMenu::Leaving(JButton key) +{ + int nbitems = (int) items.size(); + if (key == buttonNext && currentItem < nbitems - 1) + return false; + else if (key == buttonPrev && currentItem > 0) return false; -bool WGuiMenu::Leaving(JButton key){ - int nbitems = (int) items.size(); - if(key == buttonNext && currentItem < nbitems-1) - return false; - else if(key == buttonPrev && currentItem > 0) - return false; + if (currentItem >= 0 && currentItem < nbitems) if (!items[currentItem]->Leaving(key)) return false; - if(currentItem >= 0 && currentItem < nbitems) - if(!items[currentItem]->Leaving(key)) - return false; - - mFocus = false; - return true; + mFocus = false; + return true; } -void WGuiMenu::Entering(JButton key){ - mFocus = true; +void WGuiMenu::Entering(JButton key) +{ + mFocus = true; - //Try to force a selectable option. - if(currentItem == -1){ - for (size_t i = 0 ; i < items.size(); i++){ - if(items[i]->Selectable()) { - currentItem = i; - break; - } - } - } - - if(currentItem >= 0 && currentItem < (int) items.size()) - items[currentItem]->Entering(key); - return; -} - -void WGuiMenu::subBack(WGuiBase * item){ - if(!item) - return; - JRenderer * renderer = JRenderer::GetInstance(); - - WGuiSplit * split = dynamic_cast(item); - if(split && split->left->Visible() && split->right->Visible()){ - if(split->left) - subBack(split->left);//renderer->FillRoundRect(split->left->getX()-2,split->getY()-2,split->left->getWidth()-6,split->getHeight(),2,split->left->getColor(WGuiColor::BACK)); - if(split->right) - subBack(split->right);//renderer->FillRoundRect(split->right->getX()-2,split->getY()-2,split->right->getWidth(),split->getHeight(),2,split->right->getColor(WGuiColor::BACK)); - } - else - renderer->FillRoundRect(item->getX(),item->getY(),item->getWidth()-4,item->getHeight()-2,2,item->getColor(WGuiColor::BACK)); - -} - -void WGuiMenu::setSelected(vector::iterator& it) { - int c = it - items.begin(); - if (c != currentItem) + //Try to force a selectable option. + if (currentItem == -1) { - items[currentItem]->Leaving(JGE_BTN_NONE); - currentItem = c; - items[currentItem]->Entering(JGE_BTN_NONE); + for (size_t i = 0; i < items.size(); i++) + { + if (items[i]->Selectable()) + { + currentItem = i; + break; + } + } } -} -bool WGuiMenu::yieldFocus() { - for (vector::iterator it = items.begin(); it != items.end(); ++it) - if ((*it)->yieldFocus()) { setSelected(it); return true; } - return false; + + if (currentItem >= 0 && currentItem < (int) items.size()) items[currentItem]->Entering(key); + return; } +void WGuiMenu::subBack(WGuiBase * item) +{ + if (!item) return; + JRenderer * renderer = JRenderer::GetInstance(); + + WGuiSplit * split = dynamic_cast (item); + if (split && split->left->Visible() && split->right->Visible()) + { + if (split->left) subBack(split->left);//renderer->FillRoundRect(split->left->getX()-2,split->getY()-2,split->left->getWidth()-6,split->getHeight(),2,split->left->getColor(WGuiColor::BACK)); + if (split->right) subBack(split->right);//renderer->FillRoundRect(split->right->getX()-2,split->getY()-2,split->right->getWidth(),split->getHeight(),2,split->right->getColor(WGuiColor::BACK)); + } + else + renderer->FillRoundRect(item->getX(), item->getY(), item->getWidth() - 4, item->getHeight() - 2, 2, item->getColor( + WGuiColor::BACK)); + +} + +void WGuiMenu::setSelected(vector::iterator& it) +{ + int c = it - items.begin(); + if (c != currentItem) + { + items[currentItem]->Leaving(JGE_BTN_NONE); + currentItem = c; + items[currentItem]->Entering(JGE_BTN_NONE); + } +} +bool WGuiMenu::yieldFocus() +{ + for (vector::iterator it = items.begin(); it != items.end(); ++it) + if ((*it)->yieldFocus()) + { + setSelected(it); + return true; + } + return false; +} //WGuiList -WGuiList::WGuiList(string name, WSyncable * syncme): WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP, false, syncme){ - failMsg = "NO OPTIONS AVAILABLE"; - width = SCREEN_WIDTH-10; - height = SCREEN_HEIGHT-10; - y = 5; - x = 5; - mFocus = false; - sync = syncme; - displayValue = name; +WGuiList::WGuiList(string name, WSyncable * syncme) : + WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP, false, syncme) +{ + failMsg = "NO OPTIONS AVAILABLE"; + width = SCREEN_WIDTH - 10; + height = SCREEN_HEIGHT - 10; + y = 5; + x = 5; + mFocus = false; + sync = syncme; + displayValue = name; } -void WGuiList::confirmChange(bool confirmed){ - for(size_t x=0;xconfirmChange(confirmed); - } +void WGuiList::confirmChange(bool confirmed) +{ + for (size_t x = 0; x < items.size(); x++) + { + if (!items[x]) continue; + items[x]->confirmChange(confirmed); + } } -void WGuiList::Render(){ - JRenderer * renderer = JRenderer::GetInstance(); - int listHeight=40; - int listSelectable=0; - int adjustedCurrent=0; - int start = 0, nowPos = 0, vHeight=0; - int nbitems = (int) items.size(); +void WGuiList::Render() +{ + JRenderer * renderer = JRenderer::GetInstance(); + int listHeight = 40; + int listSelectable = 0; + int adjustedCurrent = 0; + int start = 0, nowPos = 0, vHeight = 0; + int nbitems = (int) items.size(); - //List is empty. - if (!items.size() && failMsg != ""){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT_FAIL)); - mFont->DrawString(_(failMsg).c_str(),x+width/2, y, JGETEXT_RIGHT); - return; - } - - //Force a selectable option. - if(currentItem == -1){ - for (int i = 0 ; i < nbitems; i++){ - if(items[i]->Selectable()) { - currentItem = i; - if(hasFocus()) - items[currentItem]->Entering(JGE_BTN_NONE); - break; - } + //List is empty. + if (!items.size() && failMsg != "") + { + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT_FAIL)); + mFont->DrawString(_(failMsg).c_str(), x + width / 2, y, JGETEXT_RIGHT); + return; } - } - //Find out how large our list is, with all items and margin. - for (int pos=0;pos < nbitems; pos++){ - listHeight+=static_cast(items[pos]->getHeight()+1); //What does the +1 do exactly ? - if(items[pos]->Selectable()){ - listSelectable++; - if(pos < currentItem) adjustedCurrent++; - } - } - //Always fill screen - if(listHeight > SCREEN_HEIGHT) - { - for (start=currentItem;start > 0; start--){ - if(!items[start]->Visible()) - continue; - - vHeight += static_cast(items[start]->getHeight()+5); - if(vHeight >= (SCREEN_HEIGHT-60)/2) - break; + //Force a selectable option. + if (currentItem == -1) + { + for (int i = 0; i < nbitems; i++) + { + if (items[i]->Selectable()) + { + currentItem = i; + if (hasFocus()) items[currentItem]->Entering(JGE_BTN_NONE); + break; + } + } } + //Find out how large our list is, with all items and margin. + for (int pos = 0; pos < nbitems; pos++) + { + listHeight += static_cast (items[pos]->getHeight() + 1); //What does the +1 do exactly ? + if (items[pos]->Selectable()) + { + listSelectable++; + if (pos < currentItem) adjustedCurrent++; + } + } + + //Always fill screen + if (listHeight > SCREEN_HEIGHT) + { + for (start = currentItem; start > 0; start--) + { + if (!items[start]->Visible()) continue; + + vHeight += static_cast (items[start]->getHeight() + 5); + if (vHeight >= (SCREEN_HEIGHT - 60) / 2) break; + } + vHeight = 0; + if (start >= 0) for (nowPos = nbitems; nowPos > 1; nowPos--) + { + if (!items[start]->Visible()) continue; + vHeight += static_cast (items[nowPos - 1]->getHeight() + 5); + } + + if (vHeight <= SCREEN_HEIGHT - 40 && nowPos < start) start = nowPos; + } + vHeight = 0; - if(start >= 0) - for (nowPos=nbitems;nowPos > 1; nowPos--){ - if(!items[start]->Visible()) - continue; - vHeight += static_cast(items[nowPos-1]->getHeight()+5); - } + nowPos = 0; - if(vHeight <= SCREEN_HEIGHT-40 && nowPos < start) - start = nowPos; - } + //Render items. + if (start >= 0) + { + //Render current underlay. + if (currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) items[currentItem]->Underlay(); - vHeight = 0; - nowPos = 0; + for (int pos = 0; pos < nbitems; pos++) + { + if (!items[pos]->Visible()) continue; - //Render items. - if(start >= 0) - { - //Render current underlay. - if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) - items[currentItem]->Underlay(); + if (pos < start) + { + vHeight += static_cast (items[pos]->getHeight() + 5); + continue; + } - for (int pos=0;pos < nbitems; pos++){ - if(!items[pos]->Visible()) - continue; + items[pos]->setY(y + nowPos); + items[pos]->setX(x); + if (listHeight > SCREEN_HEIGHT && listSelectable > 1) + items[pos]->setWidth(width - 10); + else + items[pos]->setWidth(width); + nowPos += static_cast (items[pos]->getHeight() + 5); + renderBack(items[pos]); + items[pos]->Render(); + if (nowPos > SCREEN_HEIGHT) //Stop displaying things once we reach the bottom of the screen. + break; + } - if(pos < start){ - vHeight += static_cast(items[pos]->getHeight() + 5); - continue; - } + //Draw scrollbar + if (listHeight > SCREEN_HEIGHT && listSelectable > 1) + { + float barPosition = static_cast (y - 5 + ((float) adjustedCurrent / listSelectable) * (SCREEN_HEIGHT - y)); + float barLength = static_cast ((SCREEN_HEIGHT - y) / listSelectable); + if (barLength < 4) barLength = 4; + renderer->FillRect(x + width - 2, y - 1, 2, SCREEN_HEIGHT - y, getColor(WGuiColor::SCROLLBAR)); + renderer->FillRoundRect(x + width - 5, barPosition, 5, barLength, 2, getColor(WGuiColor::SCROLLBUTTON)); + } - items[pos]->setY(y+nowPos); - items[pos]->setX(x); - if(listHeight > SCREEN_HEIGHT && listSelectable > 1) - items[pos]->setWidth(width-10); - else - items[pos]->setWidth(width); - nowPos += static_cast(items[pos]->getHeight() + 5); - renderBack(items[pos]); - items[pos]->Render(); - if(nowPos > SCREEN_HEIGHT) //Stop displaying things once we reach the bottom of the screen. - break; - } - - //Draw scrollbar - if(listHeight > SCREEN_HEIGHT && listSelectable > 1){ - float barPosition = static_cast(y-5+((float)adjustedCurrent/listSelectable)*(SCREEN_HEIGHT-y)); - float barLength = static_cast((SCREEN_HEIGHT-y) / listSelectable); - if(barLength < 4) barLength = 4; - renderer->FillRect(x+width-2,y-1,2,SCREEN_HEIGHT-y, - getColor(WGuiColor::SCROLLBAR)); - renderer->FillRoundRect(x+width-5,barPosition,5,barLength,2, - getColor(WGuiColor::SCROLLBUTTON)); - } - - //Render current overlay. - if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) - items[currentItem]->Overlay(); + //Render current overlay. + if (currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) items[currentItem]->Overlay(); } } -void WGuiList::setData(){ - for (size_t i = 0; i < items.size(); i++){ - items[i]->setData(); - } -} - -void WGuiList::ButtonPressed(int controllerId, int controlId){ - WGuiBase * it; - - if(!(it = Current())) - return; - - it->ButtonPressed(controllerId,controlId); -} - - -string WDecoEnum::lookupVal(int value){ - - if(edef == NULL){ - int id = getId(); - if(id != INVALID_ID){ - GameOptionEnum * goEnum = dynamic_cast(options.get(getId())); - if(goEnum) - edef = goEnum->def; +void WGuiList::setData() +{ + for (size_t i = 0; i < items.size(); i++) + { + items[i]->setData(); } - } +} - if(edef){ - int idx = edef->findIndex(value); - if(idx != INVALID_ID) - return edef->values[idx].second; - } +void WGuiList::ButtonPressed(int controllerId, int controlId) +{ + WGuiBase * it; - char buf[32]; - sprintf(buf,"%d",value); - return buf; + if (!(it = Current())) return; + + it->ButtonPressed(controllerId, controlId); +} + +string WDecoEnum::lookupVal(int value) +{ + + if (edef == NULL) + { + int id = getId(); + if (id != INVALID_ID) + { + GameOptionEnum * goEnum = dynamic_cast (options.get(getId())); + if (goEnum) edef = goEnum->def; + } + } + + if (edef) + { + int idx = edef->findIndex(value); + if (idx != INVALID_ID) return edef->values[idx].second; + } + + char buf[32]; + sprintf(buf, "%d", value); + return buf; } void WDecoEnum::Render() { - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT)); - JRenderer * renderer = JRenderer::GetInstance(); - mFont->DrawString(_(getDisplay()).c_str(), getX() + 2, getY() + 3); - OptionInteger* opt = dynamic_cast(it); - if(opt) - mFont->DrawString(_(lookupVal(opt->value)).c_str(), getWidth() - 5, getY() + 3, JGETEXT_RIGHT); + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT)); + JRenderer * renderer = JRenderer::GetInstance(); + mFont->DrawString(_(getDisplay()).c_str(), getX() + 2, getY() + 3); + OptionInteger* opt = dynamic_cast (it); + if (opt) mFont->DrawString(_(lookupVal(opt->value)).c_str(), getWidth() - 5, getY() + 3, JGETEXT_RIGHT); } -WDecoEnum::WDecoEnum(WGuiBase * _it, EnumDefinition *_edef) : WGuiDeco(_it) {edef = _edef;} +WDecoEnum::WDecoEnum(WGuiBase * _it, EnumDefinition *_edef) : + WGuiDeco(_it) +{ + edef = _edef; +} //WDecoCheat -WDecoCheat::WDecoCheat(WGuiBase * _it): WGuiDeco(_it){ - bVisible = (options[Options::ACTIVE_PROFILE].str == SECRET_PROFILE); +WDecoCheat::WDecoCheat(WGuiBase * _it) : + WGuiDeco(_it) +{ + bVisible = (options[Options::ACTIVE_PROFILE].str == SECRET_PROFILE); } -void WDecoCheat::Reload(){ - bVisible = (options[Options::ACTIVE_PROFILE].str == SECRET_PROFILE); +void WDecoCheat::Reload() +{ + bVisible = (options[Options::ACTIVE_PROFILE].str == SECRET_PROFILE); } -bool WDecoCheat::Visible(){ - if(bVisible && it && it->Visible()) - return true; - return false; -} -bool WDecoCheat::Selectable(){ - if(!it || !Visible()) +bool WDecoCheat::Visible() +{ + if (bVisible && it && it->Visible()) return true; return false; - return it->Selectable(); +} +bool WDecoCheat::Selectable() +{ + if (!it || !Visible()) return false; + return it->Selectable(); } //WDecoConfirm -WDecoConfirm::WDecoConfirm(JGuiListener * _listener, WGuiBase * _it): WGuiDeco(_it){ - listener = _listener; - confirm = "Confirm"; - cancel = "Cancel"; - confirmMenu = NULL; - bModal = false; - mState = OP_CONFIRMED; +WDecoConfirm::WDecoConfirm(JGuiListener * _listener, WGuiBase * _it) : + WGuiDeco(_it) +{ + listener = _listener; + confirm = "Confirm"; + cancel = "Cancel"; + confirmMenu = NULL; + bModal = false; + mState = OP_CONFIRMED; } -WDecoConfirm::~WDecoConfirm(){ - SAFE_DELETE(confirmMenu); +WDecoConfirm::~WDecoConfirm() +{ + SAFE_DELETE(confirmMenu); } -void WDecoConfirm::Entering(JButton key){ - setFocus(true); +void WDecoConfirm::Entering(JButton key) +{ + setFocus(true); - if(it) - it->Entering(key); + if (it) it->Entering(key); - SAFE_DELETE(confirmMenu); - mState = OP_CONFIRMED; - confirmMenu = NEW SimpleMenu(444, listener,Fonts::MENU_FONT, 50,170); - confirmMenu->Add(1,confirm.c_str()); - confirmMenu->Add(2,cancel.c_str()); + SAFE_DELETE(confirmMenu); + mState = OP_CONFIRMED; + confirmMenu = NEW SimpleMenu(444, listener, Fonts::MENU_FONT, 50, 170); + confirmMenu->Add(1, confirm.c_str()); + confirmMenu->Add(2, cancel.c_str()); } -bool WDecoConfirm::isModal(){ - if(bModal || (it && it->isModal())) - return true; +bool WDecoConfirm::isModal() +{ + if (bModal || (it && it->isModal())) return true; - return false; + return false; } -void WDecoConfirm::setModal(bool val){ - bModal = val; +void WDecoConfirm::setModal(bool val) +{ + bModal = val; } -void WDecoConfirm::setData(){ - if(!it) - return; +void WDecoConfirm::setData() +{ + if (!it) return; - it->setData(); + it->setData(); } -bool WDecoConfirm::Leaving(JButton key){ - if(!it) - return true; +bool WDecoConfirm::Leaving(JButton key) +{ + if (!it) return true; - //Choice must be confirmed. - if(mState == OP_UNCONFIRMED){ - if(!isModal()) - setModal(true); - if(!it->Changed()) - mState = OP_CONFIRMED; + //Choice must be confirmed. + if (mState == OP_UNCONFIRMED) + { + if (!isModal()) setModal(true); + if (!it->Changed()) + mState = OP_CONFIRMED; else - mState = OP_CONFIRMING; + mState = OP_CONFIRMING; } - - if(mState == OP_CONFIRMED && it->Leaving(key)){ - setFocus(false); - setModal(false); - SAFE_DELETE(confirmMenu); - return true; - } - - return false; -} -bool WDecoConfirm::CheckUserInput(JButton key){ - if(hasFocus()){ - if (mState == OP_CONFIRMED && key == JGE_BTN_OK) - mState = OP_UNCONFIRMED; - - if (mState != OP_CONFIRMING && it){ - if(it->CheckUserInput(key)) + + if (mState == OP_CONFIRMED && it->Leaving(key)) + { + setFocus(false); + setModal(false); + SAFE_DELETE(confirmMenu); return true; - } else if(confirmMenu && confirmMenu->CheckUserInput(key)) - return true; - } - return false; + } + + return false; +} +bool WDecoConfirm::CheckUserInput(JButton key) +{ + if (hasFocus()) + { + if (mState == OP_CONFIRMED && key == JGE_BTN_OK) mState = OP_UNCONFIRMED; + + if (mState != OP_CONFIRMING && it) + { + if (it->CheckUserInput(key)) return true; + } + else if (confirmMenu && confirmMenu->CheckUserInput(key)) return true; + } + return false; } -void WDecoConfirm::Update(float dt){ - if (hasFocus()){ - if (it && mState != OP_CONFIRMING) - it->Update(dt); +void WDecoConfirm::Update(float dt) +{ + if (hasFocus()) + { + if (it && mState != OP_CONFIRMING) + it->Update(dt); + else + confirmMenu->Update(dt); + } +} + +void WDecoConfirm::Overlay() +{ + if (confirmMenu && mState == OP_CONFIRMING) confirmMenu->Render(); + + if (it) it->Overlay(); +} + +void WDecoConfirm::ButtonPressed(int controllerId, int controlId) +{ + if (controllerId == 444) + { + setModal(false); + switch (controlId) + { + case 1: + mState = OP_CONFIRMED; + if (it) it->confirmChange(true); + break; + case 2: + mState = OP_CONFIRMED; + if (it) it->confirmChange(false); + break; + } + } else - confirmMenu->Update(dt); - } + it->ButtonPressed(controllerId, controlId); } -void WDecoConfirm::Overlay(){ - if (confirmMenu && mState == OP_CONFIRMING) - confirmMenu->Render(); - - if(it) - it->Overlay(); +WGuiButton::WGuiButton(WGuiBase* _it, int _controller, int _control, JGuiListener * jgl) : + WGuiDeco(_it) +{ + control = _control; + controller = _controller; + mListener = jgl; } -void WDecoConfirm::ButtonPressed(int controllerId, int controlId){ - if(controllerId == 444){ - setModal(false); - switch(controlId){ - case 1: - mState = OP_CONFIRMED; - if(it) - it->confirmChange(true); - break; - case 2: - mState = OP_CONFIRMED; - if(it) - it->confirmChange(false); - break; +void WGuiButton::updateValue() +{ + if (mListener) mListener->ButtonPressed(controller, control); +} + +bool WGuiButton::CheckUserInput(JButton key) +{ + if (hasFocus() && key == JGE_BTN_OK) + { + updateValue(); + return true; } - } - else - it->ButtonPressed(controllerId,controlId); + return false; } -WGuiButton::WGuiButton( WGuiBase* _it, int _controller, int _control, JGuiListener * jgl): WGuiDeco(_it) { - control = _control; - controller = _controller; - mListener = jgl; +PIXEL_TYPE WGuiButton::getColor(int type) +{ + if (type == WGuiColor::BACK && hasFocus()) return it->getColor(WGuiColor::BACK_HEADER); + return it->getColor(type); +} +; + +WGuiSplit::WGuiSplit(WGuiBase* _left, WGuiBase* _right) : + WGuiItem("") +{ + right = _right; + left = _left; + bRight = false; + percentRight = 0.5f; + if (!left->Selectable()) bRight = true; +} +WGuiSplit::~WGuiSplit() +{ + SAFE_DELETE(left); + SAFE_DELETE(right); } -void WGuiButton::updateValue(){ - if(mListener) - mListener->ButtonPressed(controller, control); +void WGuiSplit::setData() +{ + left->setData(); + right->setData(); +} +void WGuiSplit::setX(float _x) +{ + x = _x; + left->setX(x); + right->setX(x + (1 - percentRight) * width); +} +void WGuiSplit::setY(float _y) +{ + y = _y; + left->setY(y); + right->setY(y); +} +void WGuiSplit::setWidth(float _w) +{ + width = _w; + if (right->Visible()) + left->setWidth((1 - percentRight) * width); + else + left->setWidth(width); + + right->setWidth(percentRight * width); +} +void WGuiSplit::setHeight(float _h) +{ + left->setHeight(_h); + right->setHeight(_h); + height = _h; +} +float WGuiSplit::getHeight() +{ + float lH, rH; + lH = left->getHeight(); + rH = right->getHeight(); + if (lH > rH) return lH; + + return rH; } -bool WGuiButton::CheckUserInput(JButton key){ - if (hasFocus() && key == JGE_BTN_OK){ - updateValue(); - return true; - } - return false; +void WGuiSplit::Render() +{ + if (right->Visible()) right->Render(); + if (left->Visible()) left->Render(); } -PIXEL_TYPE WGuiButton::getColor(int type){ - if(type == WGuiColor::BACK && hasFocus()) - return it->getColor(WGuiColor::BACK_HEADER); - return it->getColor(type); -}; +bool WGuiSplit::isModal() +{ + if (bRight) return right->isModal(); -WGuiSplit::WGuiSplit(WGuiBase* _left, WGuiBase* _right) : WGuiItem("") { - right = _right; - left = _left; - bRight = false; - percentRight = 0.5f; - if(!left->Selectable()) - bRight = true; + return left->isModal(); } -WGuiSplit::~WGuiSplit(){ - SAFE_DELETE(left); - SAFE_DELETE(right); +void WGuiSplit::setModal(bool val) +{ + if (bRight) return right->setModal(val); + + return left->setModal(val); } -void WGuiSplit::setData(){ - left->setData(); - right->setData(); -} -void WGuiSplit::setX(float _x){ - x = _x; - left->setX(x); - right->setX(x+(1-percentRight)*width); -} -void WGuiSplit::setY(float _y){ - y = _y; - left->setY(y); - right->setY(y); -} -void WGuiSplit::setWidth(float _w){ - width = _w; - if(right->Visible()) - left->setWidth((1-percentRight)*width); - else - left->setWidth(width); - - right->setWidth(percentRight*width); -} -void WGuiSplit::setHeight(float _h){ - left->setHeight(_h); - right->setHeight(_h); - height = _h; -} -float WGuiSplit::getHeight(){ - float lH, rH; - lH = left->getHeight(); - rH = right->getHeight(); - if(lH > rH) - return lH; - - return rH; -} - -void WGuiSplit::Render(){ - if(right->Visible()) - right->Render(); - if(left->Visible()) - left->Render(); -} - -bool WGuiSplit::isModal(){ - if(bRight) - return right->isModal(); - - return left->isModal(); -} -void WGuiSplit::setModal(bool val){ - if(bRight) - return right->setModal(val); - - return left->setModal(val); -} - -bool WGuiSplit::CheckUserInput(JButton key){ - if(hasFocus()){ - if (!bRight){ - if(left->CheckUserInput(key)) - return true; - if(key == JGE_BTN_RIGHT && !isModal() - && right->Selectable() && left->Leaving(JGE_BTN_RIGHT)){ - bRight = !bRight; - right->Entering(JGE_BTN_RIGHT); - return true; +bool WGuiSplit::CheckUserInput(JButton key) +{ + if (hasFocus()) + { + if (!bRight) + { + if (left->CheckUserInput(key)) return true; + if (key == JGE_BTN_RIGHT && !isModal() && right->Selectable() && left->Leaving(JGE_BTN_RIGHT)) + { + bRight = !bRight; + right->Entering(JGE_BTN_RIGHT); + return true; + } } - } - else - { - if(right->CheckUserInput(key)) - return true; - if (key == JGE_BTN_LEFT && !isModal() - && left->Selectable() && right->Leaving(JGE_BTN_LEFT)){ - bRight = !bRight; - left->Entering(JGE_BTN_LEFT); - return true; + else + { + if (right->CheckUserInput(key)) return true; + if (key == JGE_BTN_LEFT && !isModal() && left->Selectable() && right->Leaving(JGE_BTN_LEFT)) + { + bRight = !bRight; + left->Entering(JGE_BTN_LEFT); + return true; + } } - } } - - return false; + + return false; } -void WGuiSplit::Update(float dt){ - if(bRight) - right->Update(dt); - else - left->Update(dt); +void WGuiSplit::Update(float dt) +{ + if (bRight) + right->Update(dt); + else + left->Update(dt); } -void WGuiSplit::Entering(JButton key){ - mFocus = true; - if(bRight) - right->Entering(key); - else - left->Entering(key); +void WGuiSplit::Entering(JButton key) +{ + mFocus = true; + if (bRight) + right->Entering(key); + else + left->Entering(key); } -bool WGuiSplit::Leaving(JButton key){ +bool WGuiSplit::Leaving(JButton key) +{ - if(bRight){ - if(right->Leaving(key)){ - mFocus = false; - return true; - } - } - else{ - if(left->Leaving(key)){ - mFocus = false; - return true; - } - } + if (bRight) + { + if (right->Leaving(key)) + { + mFocus = false; + return true; + } + } + else + { + if (left->Leaving(key)) + { + mFocus = false; + return true; + } + } - return false; + return false; } -void WGuiSplit::Overlay(){ - if(bRight) - right->Overlay(); - else - left->Overlay(); +void WGuiSplit::Overlay() +{ + if (bRight) + right->Overlay(); + else + left->Overlay(); } -void WGuiSplit::Underlay(){ - if(bRight) - right->Underlay(); - else - left->Underlay(); +void WGuiSplit::Underlay() +{ + if (bRight) + right->Underlay(); + else + left->Underlay(); } void WGuiSplit::ButtonPressed(int controllerId, int controlId) { - if(bRight) - right->ButtonPressed(controllerId, controlId); - else - left->ButtonPressed(controllerId, controlId); + if (bRight) + right->ButtonPressed(controllerId, controlId); + else + left->ButtonPressed(controllerId, controlId); } -void WGuiSplit::Reload(){ - left->Reload(); - right->Reload(); +void WGuiSplit::Reload() +{ + left->Reload(); + right->Reload(); } -void WGuiSplit::confirmChange(bool confirmed){ - right->confirmChange(confirmed); - left->confirmChange(confirmed); +void WGuiSplit::confirmChange(bool confirmed) +{ + right->confirmChange(confirmed); + left->confirmChange(confirmed); } -bool WGuiSplit::yieldFocus() { - if (right->yieldFocus()) { bRight = true; return true; } - if (left->yieldFocus()) { bRight = false; return true; } - return false; +bool WGuiSplit::yieldFocus() +{ + if (right->yieldFocus()) + { + bRight = true; + return true; + } + if (left->yieldFocus()) + { + bRight = false; + return true; + } + return false; } //WGuiMenu -WGuiMenu::WGuiMenu(JButton next = JGE_BTN_RIGHT, JButton prev = JGE_BTN_LEFT, bool m, WSyncable * syncme): WGuiItem(""){ - buttonNext = next; - buttonPrev = prev; - currentItem = -1; - mDPad = m; - sync = syncme; - held = JGE_BTN_NONE; +WGuiMenu::WGuiMenu(JButton next = JGE_BTN_RIGHT, JButton prev = JGE_BTN_LEFT, bool m, WSyncable * syncme) : + WGuiItem("") +{ + buttonNext = next; + buttonPrev = prev; + currentItem = -1; + mDPad = m; + sync = syncme; + held = JGE_BTN_NONE; } -WGuiMenu::~WGuiMenu(){ - for(vector::iterator it = items.begin();it!=items.end();it++) - SAFE_DELETE(*it); +WGuiMenu::~WGuiMenu() +{ + for (vector::iterator it = items.begin(); it != items.end(); it++) + SAFE_DELETE(*it); } -void WGuiMenu::setData(){ - for(vector::iterator it = items.begin();it!=items.end();it++) - (*it)->setData(); -}; +void WGuiMenu::setData() +{ + for (vector::iterator it = items.begin(); it != items.end(); it++) + (*it)->setData(); +} +; -void WGuiMenu::Reload(){ - for(vector::iterator it = items.begin();it!=items.end();it++) - (*it)->Reload(); -}; - -void WGuiMenu::Render(){ - for(vector::iterator it = items.begin();it!=items.end();it++) - (*it)->Render(); +void WGuiMenu::Reload() +{ + for (vector::iterator it = items.begin(); it != items.end(); it++) + (*it)->Reload(); } -void WGuiMenu::confirmChange(bool confirmed){ - for(vector::iterator it = items.begin();it!=items.end();it++) - (*it)->confirmChange(confirmed); +; + +void WGuiMenu::Render() +{ + for (vector::iterator it = items.begin(); it != items.end(); it++) + (*it)->Render(); +} +void WGuiMenu::confirmChange(bool confirmed) +{ + for (vector::iterator it = items.begin(); it != items.end(); it++) + (*it)->confirmChange(confirmed); } -void WGuiMenu::ButtonPressed(int controllerId, int controlId){ - WGuiBase * it = Current(); - if(!it) return; - it->ButtonPressed(controllerId,controlId); +void WGuiMenu::ButtonPressed(int controllerId, int controlId) +{ + WGuiBase * it = Current(); + if (!it) return; + it->ButtonPressed(controllerId, controlId); } -WGuiBase * WGuiMenu::Current(){ - if(currentItem >= 0 && currentItem < (int) items.size()) - return items[currentItem]; - return NULL; +WGuiBase * WGuiMenu::Current() +{ + if (currentItem >= 0 && currentItem < (int) items.size()) return items[currentItem]; + return NULL; } -void WGuiMenu::Add(WGuiBase * it){ - if(it) - items.push_back(it); +void WGuiMenu::Add(WGuiBase * it) +{ + if (it) items.push_back(it); } -bool WGuiMenu::CheckUserInput(JButton key){ - bool kidModal = false; - bool handledInput = false; - int nbitems = (int) items.size(); - JGE * mEngine = JGE::GetInstance(); +bool WGuiMenu::CheckUserInput(JButton key) +{ + bool kidModal = false; + bool handledInput = false; + int nbitems = (int) items.size(); + JGE * mEngine = JGE::GetInstance(); - if(!mEngine->GetButtonState(held)) //Key isn't held down. + if (!mEngine->GetButtonState(held)) //Key isn't held down. held = JGE_BTN_NONE; - if(currentItem >= 0 && currentItem < nbitems) - kidModal = items[currentItem]->isModal(); + if (currentItem >= 0 && currentItem < nbitems) kidModal = items[currentItem]->isModal(); - if(!kidModal && hasFocus()){ - if (isButtonDir(key,-1)){ - held = buttonPrev; - duration = 0; - if(prevItem()) - return true; - } - else if(held == buttonPrev && duration > 1){ - duration = .92f; - if(prevItem()) - return true; - } - else if (isButtonDir(key,1)){ - held = buttonNext; - duration = 0; - if(nextItem()) - return true; + if (!kidModal && hasFocus()) + { + if (isButtonDir(key, -1)) + { + held = buttonPrev; + duration = 0; + if (prevItem()) return true; + } + else if (held == buttonPrev && duration > 1) + { + duration = .92f; + if (prevItem()) return true; + } + else if (isButtonDir(key, 1)) + { + held = buttonNext; + duration = 0; + if (nextItem()) return true; + } + else if (held == buttonNext && duration > 1) + { + duration = .92f; + if (nextItem()) return true; + } } - else if(held == buttonNext && duration > 1){ - duration = .92f; - if(nextItem()) - return true; - } - } - if(currentItem >= 0 && currentItem < nbitems) - return items[currentItem]->CheckUserInput(key); + if (currentItem >= 0 && currentItem < nbitems) return items[currentItem]->CheckUserInput(key); - return false; -} -void WGuiMenu::syncMove(){ - if(!sync) - return; - int i = currentItem - sync->getPos(); - - while(i < 0 && sync->prev()) - i = currentItem - sync->getPos(); - while(i > 0 && sync->next()) - i = currentItem - sync->getPos(); -} -bool WGuiMenu::isButtonDir(JButton key, int dir){ - if(!mDPad) - return ((dir > 0 && key == buttonNext) || (dir <= 0 && key == buttonPrev)); - - if(dir <= 0){ - switch(buttonPrev){ - case JGE_BTN_LEFT: - if(key == JGE_BTN_UP) - return true; - break; - case JGE_BTN_UP: - if(key == JGE_BTN_LEFT) - return true; - break; - default: ; // Nothing - } - return (key == buttonPrev); - }else { - switch(buttonNext){ - case JGE_BTN_RIGHT: - if(key == JGE_BTN_DOWN) - return true; - break; - case JGE_BTN_DOWN: - if(key == JGE_BTN_RIGHT) - return true; - break; - default: ; // Nothing - } - return (key == buttonNext); - } -} -void WGuiMenu::Update(float dt){ - int nbitems = (int) items.size(); - JGE * mEngine = JGE::GetInstance(); - - if(held) - duration += dt; - - if(currentItem >= 0 && currentItem < nbitems) - items[currentItem]->Update(dt); - - for (int i = 0 ; i < nbitems; i++){ - if(i != currentItem) - items[i]->Update(dt); - } -} - -bool WGuiMenu::nextItem(){ - int potential = currentItem; - int nbitems = (int) items.size(); - if(nbitems < 2) return false; +} +void WGuiMenu::syncMove() +{ + if (!sync) return; + int i = currentItem - sync->getPos(); - WGuiBase * now = NULL; - if(currentItem < nbitems && currentItem > -1) - now = items[currentItem]; + while (i < 0 && sync->prev()) + i = currentItem - sync->getPos(); + while (i > 0 && sync->next()) + i = currentItem - sync->getPos(); +} +bool WGuiMenu::isButtonDir(JButton key, int dir) +{ + if (!mDPad) return ((dir > 0 && key == buttonNext) || (dir <= 0 && key == buttonPrev)); - if (potential < nbitems-1) - potential++; - else - potential = 0; + if (dir <= 0) + { + switch (buttonPrev) + { + case JGE_BTN_LEFT: + if (key == JGE_BTN_UP) return true; + break; + case JGE_BTN_UP: + if (key == JGE_BTN_LEFT) return true; + break; + default: + ; // Nothing + } + return (key == buttonPrev); + } + else + { + switch (buttonNext) + { + case JGE_BTN_RIGHT: + if (key == JGE_BTN_DOWN) return true; + break; + case JGE_BTN_DOWN: + if (key == JGE_BTN_RIGHT) return true; + break; + default: + ; // Nothing + } + return (key == buttonNext); + } +} +void WGuiMenu::Update(float dt) +{ + int nbitems = (int) items.size(); + JGE * mEngine = JGE::GetInstance(); - while(potential < nbitems-1 && items[potential]->Selectable() == false) - potential++; - if(potential == nbitems || !items[potential]->Selectable()) - potential = -1; - else if(potential != currentItem && (!now || now->Leaving(buttonNext))){ + if (held) duration += dt; + + if (currentItem >= 0 && currentItem < nbitems) items[currentItem]->Update(dt); + + for (int i = 0; i < nbitems; i++) + { + if (i != currentItem) items[i]->Update(dt); + } +} + +bool WGuiMenu::nextItem() +{ + int potential = currentItem; + int nbitems = (int) items.size(); + if (nbitems < 2) return false; + + WGuiBase * now = NULL; + if (currentItem < nbitems && currentItem > -1) now = items[currentItem]; + + if (potential < nbitems - 1) + potential++; + else + potential = 0; + + while (potential < nbitems - 1 && items[potential]->Selectable() == false) + potential++; + if (potential == nbitems || !items[potential]->Selectable()) + potential = -1; + else if (potential != currentItem && (!now || now->Leaving(buttonNext))) + { currentItem = potential; items[currentItem]->Entering(buttonNext); - - if(sync) - syncMove(); + + if (sync) syncMove(); return true; } - - if(sync) - syncMove(); - return false; -} -bool WGuiMenu::prevItem(){ - int potential = currentItem; - WGuiBase * now = NULL; - int nbitems = (int) items.size(); - if(nbitems < 2) + if (sync) syncMove(); return false; - - if(currentItem < (int)items.size() && currentItem > -1) - now = items[currentItem]; - - if (potential > 0) - potential--; - else - potential = nbitems-1; - - while(potential > 0 && items[potential]->Selectable() == false) - potential--; - if(potential < 0 || !items[potential]->Selectable()) - potential = -1; - else if(potential != currentItem && (!now || now->Leaving(buttonNext))){ - currentItem = potential; - items[currentItem]->Entering(buttonPrev); - if(sync) - syncMove(); - return true; - } - if(sync) - syncMove(); - return false; } -void WGuiMenu::setModal(bool val){ - WGuiBase* c = Current(); - if(c) - c->setModal(val); -} -bool WGuiMenu::isModal(){ - WGuiBase* c = Current(); - if(c) - return c->isModal(); +bool WGuiMenu::prevItem() +{ + int potential = currentItem; + WGuiBase * now = NULL; + int nbitems = (int) items.size(); + if (nbitems < 2) return false; - return false; + if (currentItem < (int) items.size() && currentItem > -1) now = items[currentItem]; + + if (potential > 0) + potential--; + else + potential = nbitems - 1; + + while (potential > 0 && items[potential]->Selectable() == false) + potential--; + if (potential < 0 || !items[potential]->Selectable()) + potential = -1; + else if (potential != currentItem && (!now || now->Leaving(buttonNext))) + { + currentItem = potential; + items[currentItem]->Entering(buttonPrev); + if (sync) syncMove(); + return true; + } + if (sync) syncMove(); + return false; +} + +void WGuiMenu::setModal(bool val) +{ + WGuiBase* c = Current(); + if (c) c->setModal(val); +} +bool WGuiMenu::isModal() +{ + WGuiBase* c = Current(); + if (c) return c->isModal(); + + return false; } //WGuiTabMenu -void WGuiTabMenu::Add(WGuiBase * it){ - if (it){ - it->setY(it->getY()+35); - it->setHeight(it->getHeight()-35); - WGuiMenu::Add(it); - } +void WGuiTabMenu::Add(WGuiBase * it) +{ + if (it) + { + it->setY(it->getY() + 35); + it->setHeight(it->getHeight() - 35); + WGuiMenu::Add(it); + } } -void WGuiTabMenu::Render(){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - JRenderer * renderer = JRenderer::GetInstance(); +void WGuiTabMenu::Render() +{ + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + JRenderer * renderer = JRenderer::GetInstance(); - if (!items.size()) - return; + if (!items.size()) return; - float offset = x; - mFont->SetScale(0.8f); - for(vector::iterator it = items.begin();it!=items.end();it++){ - float w = mFont->GetStringWidth(_((*it)->getDisplay()).c_str()); - mFont->SetColor((*it)->getColor(WGuiColor::TEXT_TAB)); - renderer->FillRoundRect(offset+5,5,w + 5,25,2,(*it)->getColor(WGuiColor::BACK_TAB)); - mFont->DrawString(_((*it)->getDisplay()).c_str(),offset+10,10); - offset += w + 10 + 2; - } - mFont->SetScale(1); + float offset = x; + mFont->SetScale(0.8f); + for (vector::iterator it = items.begin(); it != items.end(); it++) + { + float w = mFont->GetStringWidth(_((*it)->getDisplay()).c_str()); + mFont->SetColor((*it)->getColor(WGuiColor::TEXT_TAB)); + renderer->FillRoundRect(offset + 5, 5, w + 5, 25, 2, (*it)->getColor(WGuiColor::BACK_TAB)); + mFont->DrawString(_((*it)->getDisplay()).c_str(), offset + 10, 10); + offset += w + 10 + 2; + } + mFont->SetScale(1); - WGuiBase * c = Current(); - if(c) - c->Render(); + WGuiBase * c = Current(); + if (c) c->Render(); } -void WGuiTabMenu::save(){ - confirmChange(true); - setData(); - ::options.save(); +void WGuiTabMenu::save() +{ + confirmChange(true); + setData(); + ::options.save(); } - //WGuiAward -void WGuiAward::Overlay(){ - JRenderer * r = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetScale(0.8f); - mFont->SetColor(getColor(WGuiColor::TEXT)); +void WGuiAward::Overlay() +{ + JRenderer * r = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetScale(0.8f); + mFont->SetColor(getColor(WGuiColor::TEXT)); - string s = details; - if(s.size()){ - float fW = mFont->GetStringWidth(s.c_str()); + string s = details; + if (s.size()) + { + float fW = mFont->GetStringWidth(s.c_str()); + float fH = mFont->GetHeight(); + + if (fH < 16) fH = 18; + JQuad * button = resources.RetrieveQuad("iconspsp.png", (float) 4 * 32, 0, 32, 32, "", RETRIEVE_NORMAL); + + r->FillRoundRect(5, 10, fW + 32, fH + 2, 2, getColor(WGuiColor::BACK)); + if (button) r->RenderQuad(button, 10, 12, 0, .5, .5); + mFont->DrawString(::_(s), 30, 16); + } + + mFont->SetScale(1); +} +void WGuiAward::Underlay() +{ + char buf[1024]; + JRenderer * r = JRenderer::GetInstance(); + JQuad * trophy = NULL; + + string n = Options::getName(id); + if (n.size()) + { + sprintf(buf, "trophy_%s.png", n.c_str()); //Trophy specific to the award + trophy = resources.RetrieveTempQuad(buf); //Themed version... + } + + if (!trophy && id >= Options::SET_UNLOCKS) + { + trophy = resources.RetrieveTempQuad("trophy_set.png"); //TODO FIXME: Should look in set dir too. + } + + if (!trophy) //Fallback to basic trophy image. + trophy = resources.RetrieveTempQuad("trophy.png"); + + if (trophy) + { + r->RenderQuad(trophy, 0, SCREEN_HEIGHT - trophy->mHeight); + } + +} +void WGuiAward::Render() +{ + GameOptionAward * goa = dynamic_cast (&options[id]); + + if (!goa) return; + + JRenderer * renderer = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetScale(1); + mFont->SetColor(getColor(WGuiColor::TEXT)); + + float myX = x; + float myY = y; float fH = mFont->GetHeight(); + float fM = fH / 5; //Font Margin is 20% font height - if(fH < 16) - fH = 18; - JQuad * button = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32,"",RETRIEVE_NORMAL); + myX += fM; + renderer->FillRoundRect(x - fM / 2, y - fM, getWidth() - fM, fH - fM, fM, getColor(WGuiColor::BACK_TAB)); + mFont->DrawString(::_(displayValue).c_str(), myX, myY, JGETEXT_LEFT); - r->FillRoundRect(5,10,fW+32,fH+2,2,getColor(WGuiColor::BACK)); - if(button) - r->RenderQuad(button, 10,12,0,.5,.5); - mFont->DrawString(::_(s),30,16); - } - - mFont->SetScale(1); -} -void WGuiAward::Underlay(){ - char buf[1024]; - JRenderer * r = JRenderer::GetInstance(); - JQuad * trophy = NULL; - - string n = Options::getName(id); - if(n.size()){ - sprintf(buf,"trophy_%s.png",n.c_str()); //Trophy specific to the award - trophy = resources.RetrieveTempQuad(buf); //Themed version... - } - - if(!trophy && id >= Options::SET_UNLOCKS){ - trophy = resources.RetrieveTempQuad("trophy_set.png"); //TODO FIXME: Should look in set dir too. - } - - if(!trophy) //Fallback to basic trophy image. - trophy = resources.RetrieveTempQuad("trophy.png"); - - if(trophy){ - r->RenderQuad(trophy, 0, SCREEN_HEIGHT-trophy->mHeight); - } - -} -void WGuiAward::Render(){ - GameOptionAward * goa = dynamic_cast(&options[id]); - - if(!goa) - return; - - JRenderer * renderer = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetScale(1); - mFont->SetColor(getColor(WGuiColor::TEXT)); - - float myX = x; - float myY = y; - float fH = mFont->GetHeight(); - float fM = fH / 5; //Font Margin is 20% font height - - myX += fM; - renderer->FillRoundRect(x-fM/2,y-fM,getWidth()-fM,fH-fM,fM,getColor(WGuiColor::BACK_TAB)); - mFont->DrawString(::_(displayValue).c_str(),myX,myY,JGETEXT_LEFT); - - myY += fH + 3*fM; - mFont->SetScale(.75); - fH = mFont->GetHeight(); - if(text.size()){ - mFont->DrawString(_(text.c_str()),myX,myY,JGETEXT_LEFT); - myY+=fH + fM; - } - string s = goa->menuStr(); - if(s.size()){ - mFont->DrawString(s.c_str(),myX,myY,JGETEXT_LEFT); - myY+=fH + fM; - } - setHeight(myY-y); - mFont->SetScale(1); + myY += fH + 3 * fM; + mFont->SetScale(.75); + fH = mFont->GetHeight(); + if (text.size()) + { + mFont->DrawString(_(text.c_str()), myX, myY, JGETEXT_LEFT); + myY += fH + fM; + } + string s = goa->menuStr(); + if (s.size()) + { + mFont->DrawString(s.c_str(), myX, myY, JGETEXT_LEFT); + myY += fH + fM; + } + setHeight(myY - y); + mFont->SetScale(1); } -WGuiAward::WGuiAward(int _id, string name, string _text, string _details): WGuiItem(name){ - id = _id; - text = _text; - height = 60; - details = _details; +WGuiAward::WGuiAward(int _id, string name, string _text, string _details) : + WGuiItem(name) +{ + id = _id; + text = _text; + height = 60; + details = _details; } -WGuiAward::~WGuiAward(){ - GameOptionAward * goa = dynamic_cast(&options[id]); - if(goa) - goa->setViewed(true); +WGuiAward::~WGuiAward() +{ + GameOptionAward * goa = dynamic_cast (&options[id]); + if (goa) goa->setViewed(true); } -bool WGuiAward::Visible(){ - //WGuiAward is only visible when it's tied to an already acchieved award. - GameOptionAward * goa = dynamic_cast(&options[id]); - if(!goa || !goa->number) - return false; - return true; +bool WGuiAward::Visible() +{ + //WGuiAward is only visible when it's tied to an already acchieved award. + GameOptionAward * goa = dynamic_cast (&options[id]); + if (!goa || !goa->number) return false; + return true; } //WGuiImage -WGuiImage::WGuiImage(WDataSource * wds, float _w, float _h, int _margin): WGuiItem("") { - imgW = _w; - imgH = _h; - margin = _margin; - source = wds; +WGuiImage::WGuiImage(WDataSource * wds, float _w, float _h, int _margin) : + WGuiItem("") +{ + imgW = _w; + imgH = _h; + margin = _margin; + source = wds; } -void WGuiImage::imageScale(float _w, float _h){ - imgH = _h; - imgW = _w; +void WGuiImage::imageScale(float _w, float _h) +{ + imgH = _h; + imgW = _w; } -float WGuiImage::getHeight(){ - JQuad * q = NULL; +float WGuiImage::getHeight() +{ + JQuad * q = NULL; - if(imgH == 0 ){ - if(source && (q = source->getImage())) //Intentional assignment. - return MAX(height,q->mHeight+(2*margin)); - } - - return MAX(height,imgH+(2*margin)); + if (imgH == 0) + { + if (source && (q = source->getImage())) //Intentional assignment. + return MAX(height,q->mHeight+(2*margin)); + } + + return MAX(height,imgH+(2*margin)); } -void WGuiImage::Render(){ - if(!source) - return; +void WGuiImage::Render() +{ + if (!source) return; - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * q = source->getImage(); - if(q){ - float xS = 1, yS = 1; - if(imgH != 0 && q->mHeight != 0) - yS = imgH / q->mHeight; - if(imgW != 0 && q->mWidth != 0) - xS = imgW / q->mWidth; + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * q = source->getImage(); + if (q) + { + float xS = 1, yS = 1; + if (imgH != 0 && q->mHeight != 0) yS = imgH / q->mHeight; + if (imgW != 0 && q->mWidth != 0) xS = imgW / q->mWidth; - renderer->RenderQuad(q,x+margin, y+margin,0,xS,yS); - } + renderer->RenderQuad(q, x + margin, y + margin, 0, xS, yS); + } } -WGuiCardImage::WGuiCardImage(WDataSource * wds, bool _thumb) : WGuiImage(wds){ - bThumb = _thumb; -}; +WGuiCardImage::WGuiCardImage(WDataSource * wds, bool _thumb) : + WGuiImage(wds) +{ + bThumb = _thumb; +} +; void WGuiCardImage::Render() { - JRenderer * renderer = JRenderer::GetInstance(); - MTGCard * c = NULL; - Pos p(x+margin, y+margin, 1,0,255); + JRenderer * renderer = JRenderer::GetInstance(); + MTGCard * c = NULL; + Pos p(x + margin, y + margin, 1, 0, 255); - if(!source || (c = source->getCard(mOffset.getPos())) == NULL){ //No card, use card back. - JQuad * q; - if(bThumb){ - q = resources.GetQuad("back_thumb"); + if (!source || (c = source->getCard(mOffset.getPos())) == NULL) + { //No card, use card back. + JQuad * q; + if (bThumb) + { + q = resources.GetQuad("back_thumb"); #if defined WIN32 || defined LINUX - if(!q) - q = resources.GetQuad("back"); + if(!q) + q = resources.GetQuad("back"); #endif - } - else - q = resources.GetQuad("back"); - float scale = p.actZ * 257.f / q->mHeight; - q->SetColor(ARGB(255,255,255,255)); - renderer->RenderQuad(q,p.x,p.y,0,scale,scale); - } - else - { //Have card. - if(bThumb) - { //Thumbnail. - JQuad * q = NULL; - if(!options[Options::DISABLECARDS].number) - { - q = source->getThumb(mOffset.getPos()); -#if defined WIN32 || defined LINUX - if(!q) - q = source->getImage(mOffset.getPos()); -#endif - } - if(!q && (q = CardGui::AlternateThumbQuad(c)) == NULL) - return; //TODO Some kind of error image. - renderer->RenderQuad(q,p.x,p.y); + } + else + q = resources.GetQuad("back"); + float scale = p.actZ * 257.f / q->mHeight; + q->SetColor(ARGB(255,255,255,255)); + renderer->RenderQuad(q, p.x, p.y, 0, scale, scale); } else - { //Normal card. - JQuad * q = source->getImage(mOffset.getPos()); + { //Have card. + if (bThumb) + { //Thumbnail. + JQuad * q = NULL; + if (!options[Options::DISABLECARDS].number) + { + q = source->getThumb(mOffset.getPos()); +#if defined WIN32 || defined LINUX + if(!q) + q = source->getImage(mOffset.getPos()); +#endif + } + if (!q && (q = CardGui::AlternateThumbQuad(c)) == NULL) return; //TODO Some kind of error image. + renderer->RenderQuad(q, p.x, p.y); + } + else + { //Normal card. + JQuad * q = source->getImage(mOffset.getPos()); - int mode = (!q || options[Options::DISABLECARDS].number) ? DrawMode::kText : DrawMode::kNormal; - CardGui::DrawCard(c,p, mode); + int mode = (!q || options[Options::DISABLECARDS].number) ? DrawMode::kText : DrawMode::kNormal; + CardGui::DrawCard(c, p, mode); + } } - } } //WGuiCardDistort -WGuiCardDistort::WGuiCardDistort(WDataSource * wds, bool _thumb, WDataSource * _distort): WGuiCardImage(wds,_thumb){ - mesh = NEW hgeDistortionMesh(2,2); - distortSrc = NULL; +WGuiCardDistort::WGuiCardDistort(WDataSource * wds, bool _thumb, WDataSource * _distort) : + WGuiCardImage(wds, _thumb) +{ + mesh = NEW hgeDistortionMesh(2, 2); + distortSrc = NULL; } -WGuiCardDistort::~WGuiCardDistort(){ - SAFE_DELETE(mesh); +WGuiCardDistort::~WGuiCardDistort() +{ + SAFE_DELETE(mesh); } -void WGuiCardDistort::Render(){ - JRenderer * renderer = JRenderer::GetInstance(); - JQuad * q = NULL; +void WGuiCardDistort::Render() +{ + JRenderer * renderer = JRenderer::GetInstance(); + JQuad * q = NULL; - if(distortSrc) { - WDistort * dt = distortSrc->getDistort(mOffset.getPos()); - if(dt) - xy = *dt; - } - - if(!source){ - //Default to back. - if(bThumb){ - q = resources.GetQuad("back_thumb"); + if (distortSrc) + { + WDistort * dt = distortSrc->getDistort(mOffset.getPos()); + if (dt) xy = *dt; + } + + if (!source) + { + //Default to back. + if (bThumb) + { + q = resources.GetQuad("back_thumb"); #if defined WIN32 || defined LINUX - if(!q) - q = resources.GetQuad("back"); + if(!q) + q = resources.GetQuad("back"); #endif + } + else + q = resources.GetQuad("back"); } else - q = resources.GetQuad("back"); - }else { - MTGCard * c = source->getCard(mOffset.getPos()); - if(!c) - return; - - if(bThumb){ - q = source->getThumb(mOffset.getPos()); + { + MTGCard * c = source->getCard(mOffset.getPos()); + if (!c) return; + + if (bThumb) + { + q = source->getThumb(mOffset.getPos()); #if defined WIN32 || defined LINUX - if(!q) - q = source->getImage(mOffset.getPos()); + if(!q) + q = source->getImage(mOffset.getPos()); #endif - if(!q || options[Options::DISABLECARDS].number) - q = CardGui::AlternateThumbQuad(c); + if (!q || options[Options::DISABLECARDS].number) q = CardGui::AlternateThumbQuad(c); + } + else + { + q = source->getImage(mOffset.getPos()); + if (!q || options[Options::DISABLECARDS].number) q = CardGui::AlternateThumbQuad(c); //TODO alternateX should render to texture. + } } - else { - q = source->getImage(mOffset.getPos()); - if(!q || options[Options::DISABLECARDS].number) - q = CardGui::AlternateThumbQuad(c); //TODO alternateX should render to texture. + if (!q) return; + mesh->SetTexture(q->mTex); + float x0, y0, w0, h0; + q->GetTextureRect(&x0, &y0, &w0, &h0); + mesh->SetTextureRect(x0, y0, w0, h0); + mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); + mesh->SetDisplacement(0, 0, xy[0], xy[1], HGEDISP_NODE); + mesh->SetDisplacement(1, 0, xy[2] - w0, xy[3], HGEDISP_NODE); + mesh->SetDisplacement(0, 1, xy[4], xy[5] - h0, HGEDISP_NODE); + mesh->SetDisplacement(1, 1, xy[6] - w0, xy[7] - h0, HGEDISP_NODE); + if (hasFocus()) + { + mesh->SetColor(1, 1, ARGB(255,200,200,200)); + mesh->SetColor(0, 1, ARGB(255,200,200,200)); + mesh->SetColor(1, 0, ARGB(255,200,200,200)); + mesh->SetColor(0, 0, ARGB(255,255,255,200)); } - } - if(!q) - return; - mesh->SetTexture(q->mTex); - float x0,y0,w0,h0; - q->GetTextureRect(&x0,&y0,&w0,&h0); - mesh->SetTextureRect(x0,y0,w0,h0); - mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); - mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE); - mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE); - mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE); - mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE); - if(hasFocus()){ - mesh->SetColor(1,1,ARGB(255,200,200,200)); - mesh->SetColor(0,1,ARGB(255,200,200,200)); - mesh->SetColor(1,0,ARGB(255,200,200,200)); - mesh->SetColor(0,0,ARGB(255,255,255,200)); - }else{ - mesh->SetColor(1,1,ARGB(255,100,100,100)); - mesh->SetColor(0,1,ARGB(255,100,100,100)); - mesh->SetColor(1,0,ARGB(255,100,100,100)); - mesh->SetColor(0,0,ARGB(255,200,200,200)); - } - mesh->Render(0,0); + else + { + mesh->SetColor(1, 1, ARGB(255,100,100,100)); + mesh->SetColor(0, 1, ARGB(255,100,100,100)); + mesh->SetColor(1, 0, ARGB(255,100,100,100)); + mesh->SetColor(0, 0, ARGB(255,200,200,200)); + } + mesh->Render(0, 0); } //WDistort -WDistort::WDistort(){ - for(int i=0;i<8;i++) - xy[i] = 0; +WDistort::WDistort() +{ + for (int i = 0; i < 8; i++) + xy[i] = 0; } -float & WDistort::operator[](int p){ - return xy[p]; +float & WDistort::operator[](int p) +{ + return xy[p]; } -WDistort::WDistort(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4){ - xy[0] = x1; xy[1] = y1; - xy[2] = x2; xy[3] = y2; - xy[4] = x3; xy[5] = y3; - xy[6] = x4; xy[7] = y4; +WDistort::WDistort(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) +{ + xy[0] = x1; + xy[1] = y1; + xy[2] = x2; + xy[3] = y2; + xy[4] = x3; + xy[5] = y3; + xy[6] = x4; + xy[7] = y4; } //WGuiListRow -void WGuiListRow::Render(){ - JRenderer * renderer = JRenderer::GetInstance(); - int listHeight=40; - int listSelectable=0; - int adjustedCurrent=0; - int start = 0, nowPos = 0, vHeight=0; - int nbitems = (int) items.size(); +void WGuiListRow::Render() +{ + JRenderer * renderer = JRenderer::GetInstance(); + int listHeight = 40; + int listSelectable = 0; + int adjustedCurrent = 0; + int start = 0, nowPos = 0, vHeight = 0; + int nbitems = (int) items.size(); - //List is empty. - if (!items.size() && failMsg != ""){ - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(getColor(WGuiColor::TEXT_FAIL)); - mFont->DrawString(_(failMsg).c_str(),x+width/2, y, JGETEXT_RIGHT); - return; - } - - //Force a selectable option. - if(currentItem == -1){ - for (int i = 0 ; i < nbitems; i++){ - if(items[i]->Selectable()) { - currentItem = i; - if(hasFocus()) - items[currentItem]->Entering(JGE_BTN_NONE); - break; - } - } - } - - vHeight = 0; - nowPos = 4; - float nowVPos = 4; - float tallestRow = 0; - int numRows = 1; - float cTallest = 0; - - //Render items. - if(start >= 0) - { - //Render current underlay. - if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) - items[currentItem]->Underlay(); - - for (int pos=0;pos < nbitems; pos++){ - if(!items[pos]->Visible()) - continue; - - items[pos]->setX(x+nowPos); - items[pos]->setY(y+nowVPos); - //items[pos]->setWidth(width/nbitems); - items[pos]->setWidth(items[pos]->minWidth()); - float temp = items[pos]->getHeight() + 3; - if(temp > tallestRow) - tallestRow = temp; - if(temp > cTallest) - cTallest = temp; - nowPos += static_cast(items[pos]->getWidth() + 5); - renderBack(items[pos]); - if(x+nowPos+items[pos]->getWidth()+10 > SCREEN_WIDTH){ - nowPos = 0 + 20; //Indent newlines. - nowVPos += cTallest; - cTallest = 0; - numRows++; - } - items[pos]->Render(); - if(nowVPos > SCREEN_HEIGHT) - break; + //List is empty. + if (!items.size() && failMsg != "") + { + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(getColor(WGuiColor::TEXT_FAIL)); + mFont->DrawString(_(failMsg).c_str(), x + width / 2, y, JGETEXT_RIGHT); + return; } - //Render current overlay. - if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) - items[currentItem]->Overlay(); + //Force a selectable option. + if (currentItem == -1) + { + for (int i = 0; i < nbitems; i++) + { + if (items[i]->Selectable()) + { + currentItem = i; + if (hasFocus()) items[currentItem]->Entering(JGE_BTN_NONE); + break; + } + } } - setHeight(tallestRow*numRows+10); + + vHeight = 0; + nowPos = 4; + float nowVPos = 4; + float tallestRow = 0; + int numRows = 1; + float cTallest = 0; + + //Render items. + if (start >= 0) + { + //Render current underlay. + if (currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) items[currentItem]->Underlay(); + + for (int pos = 0; pos < nbitems; pos++) + { + if (!items[pos]->Visible()) continue; + + items[pos]->setX(x + nowPos); + items[pos]->setY(y + nowVPos); + //items[pos]->setWidth(width/nbitems); + items[pos]->setWidth(items[pos]->minWidth()); + float temp = items[pos]->getHeight() + 3; + if (temp > tallestRow) tallestRow = temp; + if (temp > cTallest) cTallest = temp; + nowPos += static_cast (items[pos]->getWidth() + 5); + renderBack(items[pos]); + if (x + nowPos + items[pos]->getWidth() + 10 > SCREEN_WIDTH) + { + nowPos = 0 + 20; //Indent newlines. + nowVPos += cTallest; + cTallest = 0; + numRows++; + } + items[pos]->Render(); + if (nowVPos > SCREEN_HEIGHT) break; + } + + //Render current overlay. + if (currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) items[currentItem]->Overlay(); + } + setHeight(tallestRow * numRows + 10); } -WGuiListRow::WGuiListRow(string n, WSyncable * s) : WGuiList(n,s) { - buttonNext = JGE_BTN_RIGHT; - buttonPrev = JGE_BTN_LEFT; - width = SCREEN_WIDTH; - height = 20; +WGuiListRow::WGuiListRow(string n, WSyncable * s) : + WGuiList(n, s) +{ + buttonNext = JGE_BTN_RIGHT; + buttonPrev = JGE_BTN_LEFT; + width = SCREEN_WIDTH; + height = 20; } //WGuiFilterUI -bool WGuiFilters::Finish(bool emptyset){ - bFinished = true; - string src; - if(source){ - src = getCode(); - source->clearFilters(); - if(src.size()){ - WCFilterFactory * wc = WCFilterFactory::GetInstance(); - WCardFilter * f = wc->Construct(src); - if(recolorTo > -1 && recolorTo < Constants::MTG_NB_COLORS){ - f = NEW WCFilterAND(f,NEW WCFilterColor(recolorTo)); - } - source->addFilter(f); - }else { - if(recolorTo > -1 && recolorTo < Constants::MTG_NB_COLORS){ - WCardFilter * f = NEW WCFilterColor(recolorTo); - source->addFilter(f); - } - } - if((!source->Size() && !emptyset)){ - source->clearFilters(); //TODO: Pop a "No results found" warning - } - } - return true; -} -void WGuiFilters::ButtonPressed(int controllerId, int controlId){ - if(controllerId == -102){ - if(controlId == -10){ - WGuiListRow * wgl= NEW WGuiListRow(""); - wgl->Add(NEW WGuiFilterItem(this)); - list->Add(wgl); - }else if(controlId == -11){ - Finish(); - } - else{ - if(source) +bool WGuiFilters::Finish(bool emptyset) +{ + bFinished = true; + string src; + if (source) + { + src = getCode(); source->clearFilters(); - SAFE_DELETE(list); - buildList(); - } - return; - }else{ - if(list != NULL) - list->ButtonPressed(controllerId,controlId); - } -} -void WGuiFilters::buildList(){ - list = NEW WGuiList(""); - WGuiButton * l = NEW WGuiButton(NEW WGuiItem("Add Filter"),-102,-10,this); - WGuiButton * r = NEW WGuiButton(NEW WGuiItem("Done"),-102,-11,this); - WGuiButton * mid = NEW WGuiButton(NEW WGuiItem("Clear"),-102,-66,this); - WGuiSplit * sub = NEW WGuiSplit(mid,r); - WGuiSplit * wgs = NEW WGuiSplit(l,sub); - subMenu = NULL; - list->Add(NEW WGuiHeader(displayValue)); - list->Add(wgs); - list->Entering(JGE_BTN_NONE); -} -WGuiFilters::WGuiFilters(string header, WSrcCards * src) : WGuiItem(header) { - bFinished = false; - source = src; - recolorTo = -1; - buildList(); -} -void WGuiFilters::recolorFilter(int color){ - recolorTo = color; -} -string WGuiFilters::getCode(){ - if(!list) - return ""; - string res; - vector::iterator row, col; - for(row=list->items.begin();row!=list->items.end();row++){ - WGuiList * wgl = dynamic_cast(*row); - if(wgl){ - if(res.size()) - res += "|("; - else - res += "("; - for(col=wgl->items.begin();col!=wgl->items.end();col++){ - WGuiFilterItem * fi = dynamic_cast(*col); - if(fi){ - string gc = fi->getCode(); - if(res.size() && gc.size() && res[res.size()-1] != '(') - res += "&"; - res += gc; + if (src.size()) + { + WCFilterFactory * wc = WCFilterFactory::GetInstance(); + WCardFilter * f = wc->Construct(src); + if (recolorTo > -1 && recolorTo < Constants::MTG_NB_COLORS) + { + f = NEW WCFilterAND(f, NEW WCFilterColor(recolorTo)); + } + source->addFilter(f); + } + else + { + if (recolorTo > -1 && recolorTo < Constants::MTG_NB_COLORS) + { + WCardFilter * f = NEW WCFilterColor(recolorTo); + source->addFilter(f); + } + } + if ((!source->Size() && !emptyset)) + { + source->clearFilters(); //TODO: Pop a "No results found" warning } - } - res += ")"; - } - } - return res; -} -void WGuiFilters::setSrc(WSrcCards * wsc){ - source = wsc; -} -void WGuiFilters::Update(float dt){ - if(subMenu && !subMenu->closed) - subMenu->Update(dt); - if(list){ - list->Update(dt); - WGuiList * wgl = dynamic_cast(list->Current()); - if(!wgl) - return; - vector::iterator it; - bool bDeleted=false; - for(it=wgl->items.begin();it!=wgl->items.end();it++){ - WGuiFilterItem * wgfi = dynamic_cast(*it); - if(!wgfi || wgfi->mState != WGuiFilterItem::STATE_REMOVE) continue; - SAFE_DELETE(*it); - it = wgl->items.erase(it); - bDeleted = true; - } - if(bDeleted) - wgl->Entering(JGE_BTN_NONE); - } -} -void WGuiFilters::Entering(JButton key){ - bFinished = false; - WGuiItem::Entering(key); -} -void WGuiFilters::Render(){ - if(!list) return; //Hurrah for paranoia. - JRenderer * r = JRenderer::GetInstance(); - float tX, tY; - tX = getX(); - tY = getY(); - r->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(128,0,0,0)); - list->setX(tX); list->setY(tY); - list->Render(); - - if(subMenu && !subMenu->closed) - subMenu->Render(); -} -bool WGuiFilters::CheckUserInput(JButton key){ - if(subMenu && !subMenu->closed && subMenu->CheckUserInput(key)) - return true; - if(key == JGE_BTN_SEC){//|| key == JGE_BTN_MENU){ - //TODO Pop up a "Are you sure?" dialog. - return true; - } - if(list){ - return list->CheckUserInput(key); - } - return WGuiItem::CheckUserInput(key); -} -WGuiFilters::~WGuiFilters(){ - SAFE_DELETE(list); - SAFE_DELETE(subMenu); -} -void WGuiFilters::addColumn(){ - if(!list) - return; - WGuiList * wgl = dynamic_cast(list->Current()); - if(wgl){ - wgl->currentItem = wgl->items.size()-1; - wgl->Add(NEW WGuiFilterItem(this)); - } -} -bool WGuiFilters::isAvailableCode(string code){ -if(!list) return false; - WGuiList * wgl = dynamic_cast(list->Current()); - if(wgl){ - vector::iterator it; - for(it=wgl->items.begin();it!=wgl->items.end();it++){ - WGuiFilterItem * wgfi = dynamic_cast(*it); - if(!wgfi || wgfi->mState != WGuiFilterItem::STATE_FINISHED) continue; - if(!wgfi->mCode.size()) continue; - if(wgfi->mCode == code) - return false; } return true; - } - return false; //For some reason, we don't have any rows? } -bool WGuiFilters::isAvailable(int type){ - if(!list) return false; - int colors = 0, ma = 0; - WGuiList * wgl = dynamic_cast(list->Current()); - if(wgl){ - vector::iterator it; - for(it=wgl->items.begin();it!=wgl->items.end();it++){ - WGuiFilterItem * wgfi = dynamic_cast(*it); - if(!wgfi || wgfi->mState != WGuiFilterItem::STATE_FINISHED) continue; - switch(type){ - case WGuiFilterItem::FILTER_SUBTYPE: - case WGuiFilterItem::FILTER_BASIC: - return true; - case WGuiFilterItem::FILTER_PRODUCE: - if(wgfi->filterType == type) - ma++; - break; - case WGuiFilterItem::FILTER_COLOR: - if(wgfi->filterType == type) - colors++; - break; - default: - if(wgfi->filterType == type) - return false; - } +void WGuiFilters::ButtonPressed(int controllerId, int controlId) +{ + if (controllerId == -102) + { + if (controlId == -10) + { + WGuiListRow * wgl = NEW WGuiListRow(""); + wgl->Add(NEW WGuiFilterItem(this)); + list->Add(wgl); + } + else if (controlId == -11) + { + Finish(); + } + else + { + if (source) source->clearFilters(); + SAFE_DELETE(list); + buildList(); + } + return; + } + else + { + if (list != NULL) list->ButtonPressed(controllerId, controlId); } - if(colors >= 5) - return false; - if(ma >= 5) - return false; - return true; - } - return false; //For some reason, we don't have any rows? } -void WGuiFilters::clearArgs(){ - tempArgs.clear(); +void WGuiFilters::buildList() +{ + list = NEW WGuiList(""); + WGuiButton * l = NEW WGuiButton(NEW WGuiItem("Add Filter"), -102, -10, this); + WGuiButton * r = NEW WGuiButton(NEW WGuiItem("Done"), -102, -11, this); + WGuiButton * mid = NEW WGuiButton(NEW WGuiItem("Clear"), -102, -66, this); + WGuiSplit * sub = NEW WGuiSplit(mid, r); + WGuiSplit * wgs = NEW WGuiSplit(l, sub); + subMenu = NULL; + list->Add(NEW WGuiHeader(displayValue)); + list->Add(wgs); + list->Entering(JGE_BTN_NONE); } -void WGuiFilters::addArg(string display, string code){ - if(!subMenu || !isAvailableCode(code)) - return; - subMenu->Add((int)tempArgs.size(),display.c_str()); - tempArgs.push_back(pair(display,code)); +WGuiFilters::WGuiFilters(string header, WSrcCards * src) : + WGuiItem(header) +{ + bFinished = false; + source = src; + recolorTo = -1; + buildList(); +} +void WGuiFilters::recolorFilter(int color) +{ + recolorTo = color; +} +string WGuiFilters::getCode() +{ + if (!list) return ""; + string res; + vector::iterator row, col; + for (row = list->items.begin(); row != list->items.end(); row++) + { + WGuiList * wgl = dynamic_cast (*row); + if (wgl) + { + if (res.size()) + res += "|("; + else + res += "("; + for (col = wgl->items.begin(); col != wgl->items.end(); col++) + { + WGuiFilterItem * fi = dynamic_cast (*col); + if (fi) + { + string gc = fi->getCode(); + if (res.size() && gc.size() && res[res.size() - 1] != '(') res += "&"; + res += gc; + } + } + res += ")"; + } + } + return res; +} +void WGuiFilters::setSrc(WSrcCards * wsc) +{ + source = wsc; +} +void WGuiFilters::Update(float dt) +{ + if (subMenu && !subMenu->closed) subMenu->Update(dt); + if (list) + { + list->Update(dt); + WGuiList * wgl = dynamic_cast (list->Current()); + if (!wgl) return; + vector::iterator it; + bool bDeleted = false; + for (it = wgl->items.begin(); it != wgl->items.end(); it++) + { + WGuiFilterItem * wgfi = dynamic_cast (*it); + if (!wgfi || wgfi->mState != WGuiFilterItem::STATE_REMOVE) continue; + SAFE_DELETE(*it); + it = wgl->items.erase(it); + bDeleted = true; + } + if (bDeleted) wgl->Entering(JGE_BTN_NONE); + } +} +void WGuiFilters::Entering(JButton key) +{ + bFinished = false; + WGuiItem::Entering(key); +} +void WGuiFilters::Render() +{ + if (!list) return; //Hurrah for paranoia. + JRenderer * r = JRenderer::GetInstance(); + float tX, tY; + tX = getX(); + tY = getY(); + r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(128,0,0,0)); + list->setX(tX); + list->setY(tY); + list->Render(); + + if (subMenu && !subMenu->closed) subMenu->Render(); +} +bool WGuiFilters::CheckUserInput(JButton key) +{ + if (subMenu && !subMenu->closed && subMenu->CheckUserInput(key)) return true; + if (key == JGE_BTN_SEC) + {//|| key == JGE_BTN_MENU){ + //TODO Pop up a "Are you sure?" dialog. + return true; + } + if (list) + { + return list->CheckUserInput(key); + } + return WGuiItem::CheckUserInput(key); +} +WGuiFilters::~WGuiFilters() +{ + SAFE_DELETE(list); + SAFE_DELETE(subMenu); +} +void WGuiFilters::addColumn() +{ + if (!list) return; + WGuiList * wgl = dynamic_cast (list->Current()); + if (wgl) + { + wgl->currentItem = wgl->items.size() - 1; + wgl->Add(NEW WGuiFilterItem(this)); + } +} +bool WGuiFilters::isAvailableCode(string code) +{ + if (!list) return false; + WGuiList * wgl = dynamic_cast (list->Current()); + if (wgl) + { + vector::iterator it; + for (it = wgl->items.begin(); it != wgl->items.end(); it++) + { + WGuiFilterItem * wgfi = dynamic_cast (*it); + if (!wgfi || wgfi->mState != WGuiFilterItem::STATE_FINISHED) continue; + if (!wgfi->mCode.size()) continue; + if (wgfi->mCode == code) return false; + } + return true; + } + return false; //For some reason, we don't have any rows? +} +bool WGuiFilters::isAvailable(int type) +{ + if (!list) return false; + int colors = 0, ma = 0; + WGuiList * wgl = dynamic_cast (list->Current()); + if (wgl) + { + vector::iterator it; + for (it = wgl->items.begin(); it != wgl->items.end(); it++) + { + WGuiFilterItem * wgfi = dynamic_cast (*it); + if (!wgfi || wgfi->mState != WGuiFilterItem::STATE_FINISHED) continue; + switch (type) + { + case WGuiFilterItem::FILTER_SUBTYPE: + case WGuiFilterItem::FILTER_BASIC: + return true; + case WGuiFilterItem::FILTER_PRODUCE: + if (wgfi->filterType == type) ma++; + break; + case WGuiFilterItem::FILTER_COLOR: + if (wgfi->filterType == type) colors++; + break; + default: + if (wgfi->filterType == type) return false; + } + } + if (colors >= 5) return false; + if (ma >= 5) return false; + return true; + } + return false; //For some reason, we don't have any rows? +} +void WGuiFilters::clearArgs() +{ + tempArgs.clear(); +} +void WGuiFilters::addArg(string display, string code) +{ + if (!subMenu || !isAvailableCode(code)) return; + subMenu->Add((int) tempArgs.size(), display.c_str()); + tempArgs.push_back(pair (display, code)); } //WGuiFilterItem -WGuiFilterItem::WGuiFilterItem(WGuiFilters * parent): WGuiItem("Cards..."){ - filterType = -1; filterVal = -1; mState = 0; - mParent = parent; mNew = true; -}; -void WGuiFilterItem::updateValue(){ - bool delMenu = true; - char buf_name[512]; - char buf_code[512]; - if(!mParent) - return; - switch(mState){ +WGuiFilterItem::WGuiFilterItem(WGuiFilters * parent) : + WGuiItem("Cards...") +{ + filterType = -1; + filterVal = -1; + mState = 0; + mParent = parent; + mNew = true; +} +; +void WGuiFilterItem::updateValue() +{ + bool delMenu = true; + char buf_name[512]; + char buf_code[512]; + if (!mParent) return; + switch (mState) + { case STATE_CANCEL: - mState = STATE_UNSET; - break; + mState = STATE_UNSET; + break; case STATE_FINISHED: case STATE_UNSET: - SAFE_DELETE(mParent->subMenu); - mState = STATE_CHOOSE_TYPE; - SAFE_DELETE(mParent->subMenu); - mParent->subMenu = NEW SimpleMenu(-1234,this,Fonts::MENU_FONT,20,20,"Filter By...",10); - if(mParent->isAvailable(FILTER_SET)){ - mParent->subMenu->Add(FILTER_SET,"Set"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_COLOR)){ - mParent->subMenu->Add(FILTER_COLOR,"Color"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_TYPE)){ - mParent->subMenu->Add(FILTER_TYPE,"Type"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_SUBTYPE)){ - mParent->subMenu->Add(FILTER_SUBTYPE,"Subtype"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_RARITY)){ - mParent->subMenu->Add(FILTER_RARITY,"Rarity"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_CMC)){ - mParent->subMenu->Add(FILTER_CMC,"Mana Cost"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_BASIC)){ - mParent->subMenu->Add(FILTER_BASIC,"Basic Ability"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_PRODUCE)){ - mParent->subMenu->Add(FILTER_PRODUCE,"Mana Ability"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_POWER)){ - mParent->subMenu->Add(FILTER_POWER,"Power"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_TOUGH)){ - mParent->subMenu->Add(FILTER_TOUGH,"Toughness"); - delMenu = false; - } - if(mParent->isAvailable(FILTER_ALPHA)){ - mParent->subMenu->Add(FILTER_ALPHA,"First Letter"); - delMenu = false; - } - if(!mNew) - mParent->subMenu->Add(-2,"Remove"); - mParent->subMenu->Add(kCancelMenuID,"Cancel"); - if(delMenu){ SAFE_DELETE(mParent->subMenu); + mState = STATE_CHOOSE_TYPE; + SAFE_DELETE(mParent->subMenu); + mParent->subMenu = NEW SimpleMenu(-1234, this, Fonts::MENU_FONT, 20, 20, "Filter By...", 10); + if (mParent->isAvailable(FILTER_SET)) + { + mParent->subMenu->Add(FILTER_SET, "Set"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_COLOR)) + { + mParent->subMenu->Add(FILTER_COLOR, "Color"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_TYPE)) + { + mParent->subMenu->Add(FILTER_TYPE, "Type"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_SUBTYPE)) + { + mParent->subMenu->Add(FILTER_SUBTYPE, "Subtype"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_RARITY)) + { + mParent->subMenu->Add(FILTER_RARITY, "Rarity"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_CMC)) + { + mParent->subMenu->Add(FILTER_CMC, "Mana Cost"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_BASIC)) + { + mParent->subMenu->Add(FILTER_BASIC, "Basic Ability"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_PRODUCE)) + { + mParent->subMenu->Add(FILTER_PRODUCE, "Mana Ability"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_POWER)) + { + mParent->subMenu->Add(FILTER_POWER, "Power"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_TOUGH)) + { + mParent->subMenu->Add(FILTER_TOUGH, "Toughness"); + delMenu = false; + } + if (mParent->isAvailable(FILTER_ALPHA)) + { + mParent->subMenu->Add(FILTER_ALPHA, "First Letter"); + delMenu = false; + } + if (!mNew) mParent->subMenu->Add(-2, "Remove"); + mParent->subMenu->Add(kCancelMenuID, "Cancel"); + if (delMenu) + { + SAFE_DELETE(mParent->subMenu); + mState = STATE_FINISHED; + } + break; + case STATE_CHOOSE_TYPE: + SAFE_DELETE(mParent->subMenu); + mParent->clearArgs(); + mState = STATE_CHOOSE_VAL; + mParent->subMenu = NEW SimpleMenu(-1234, this, Fonts::MENU_FONT, 20, 20, "Filter:"); + if (filterType == FILTER_TYPE) + { + mParent->addArg("Artifact", "t:Artifact;"); + mParent->addArg("Artifact Creature", "t:Artifact;&t:Creature;"); + mParent->addArg("Creature", "t:Creature;"); + mParent->addArg("Enchantment", "t:Enchantment;"); + mParent->addArg("Instant", "t:Instant;"); + mParent->addArg("Land", "t:Land;"); + mParent->addArg("Legendary", "t:Legendary;"); + mParent->addArg("Sorcery", "t:Sorcery;"); + } + else if (filterType == FILTER_SUBTYPE) + { + vector stlist; + for (int i = Subtypes::LAST_TYPE + 1;; i++) + { + string s = Subtypes::subtypesList->find(i); + if (s == "") break; + if (s.find(" ") != string::npos) continue; + if (s == "Nothing") + {//dont add "nothing" to the search filters. + } + else + { + stlist.push_back(s); + } + } + std::sort(stlist.begin(), stlist.end()); + for (size_t t = 0; t < stlist.size(); t++) + { + string s = stlist[t]; + char buf[1024]; + sprintf(buf, "t:%s;", s.c_str()); + mParent->addArg(s, buf); + } + } + else if (filterType == FILTER_RARITY) + { + mParent->addArg("Mythic", "r:m;"); + mParent->addArg("Rare", "r:r;"); + mParent->addArg("Uncommon", "r:u;"); + mParent->addArg("Common", "r:c;"); + mParent->addArg("Special Rarity", "{r:m;|r:t;|r:r;|r:u;|r:c;}"); + } + else if (filterType == FILTER_CMC) + { + for (int i = 0; i < 20; i++) + { + sprintf(buf_code, "cmc:%i;", i); + sprintf(buf_name, "%i Mana", i); + mParent->addArg(buf_name, buf_code); + } + } + else if (filterType == FILTER_POWER) + { + for (int i = 0; i < 14; i++) + { + sprintf(buf_code, "pow:%i;", i); + sprintf(buf_name, "%i power", i); + mParent->addArg(buf_name, buf_code); + } + } + else if (filterType == FILTER_TOUGH) + { + for (int i = 0; i < 14; i++) + { + sprintf(buf_code, "tgh:%i;", i); + sprintf(buf_name, "%i toughness", i); + mParent->addArg(buf_name, buf_code); + } + } + else if (filterType == FILTER_COLOR) + { + mParent->addArg("White", "c:w;"); + mParent->addArg("Blue", "c:u;"); + mParent->addArg("Black", "c:b;"); + mParent->addArg("Red", "c:r;"); + mParent->addArg("Green", "c:g;"); + mParent->addArg("Exclusively White", "xc:w;"); + mParent->addArg("Exclusively Blue", "xc:u;"); + mParent->addArg("Exclusively Black", "xc:b;"); + mParent->addArg("Exclusively Red", "xc:r;"); + mParent->addArg("Exclusively Green", "xc:g;"); + } + else if (filterType == FILTER_PRODUCE) + { + mParent->addArg("White mana abiltity", "ma:w;"); + mParent->addArg("Blue mana abiltity", "ma:u;"); + mParent->addArg("Black mana abiltity", "ma:b;"); + mParent->addArg("Red mana abiltity", "ma:r;"); + mParent->addArg("Green mana abiltity", "ma:g;"); + mParent->addArg("Colorless mana abiltity", "ma:x;"); + } + else if (filterType == FILTER_BASIC) + { + char buf[512]; + for (int i = 0; i < Constants::NB_BASIC_ABILITIES; i++) + { + string s = Constants::MTGBasicAbilities[i]; + sprintf(buf, "a:%s;", s.c_str()); + s[0] = toupper(s[0]); + mParent->addArg(s, buf); + } + } + else if (filterType == FILTER_SET) + { + char buf[512]; + for (int i = 0; i < setlist.size(); i++) + { + if (options[Options::optionSet(i)].number == 0) continue; + sprintf(buf, "s:%s;", setlist[i].c_str()); + mParent->addArg((setlist.getInfo(i))->getName(), buf); + } + } + else if (filterType == FILTER_ALPHA) + { + char buf[24], pretty[16]; + for (char c = 'a'; c <= 'z'; c++) + { + sprintf(buf, "alpha:%c;", c); + sprintf(pretty, "Letter %c", toupper(c)); + mParent->addArg(pretty, buf); + } + mParent->addArg("Digit", "alpha:#;"); + } + mParent->subMenu->Add(kCancelMenuID, "Cancel"); + break; + case STATE_CHOOSE_VAL: mState = STATE_FINISHED; - } - break; - case STATE_CHOOSE_TYPE: - SAFE_DELETE(mParent->subMenu); - mParent->clearArgs(); - mState = STATE_CHOOSE_VAL; - mParent->subMenu = NEW SimpleMenu(-1234,this,Fonts::MENU_FONT,20,20,"Filter:"); - if(filterType == FILTER_TYPE){ - mParent->addArg("Artifact","t:Artifact;"); - mParent->addArg("Artifact Creature","t:Artifact;&t:Creature;"); - mParent->addArg("Creature","t:Creature;"); - mParent->addArg("Enchantment","t:Enchantment;"); - mParent->addArg("Instant","t:Instant;"); - mParent->addArg("Land","t:Land;"); - mParent->addArg("Legendary","t:Legendary;"); - mParent->addArg("Sorcery","t:Sorcery;"); - }else if(filterType == FILTER_SUBTYPE){ - vector stlist; - for(int i=Subtypes::LAST_TYPE+1;;i++){ - string s = Subtypes::subtypesList->find(i); - if(s == "") break; - if(s.find(" ") != string::npos) continue; - if(s == "Nothing") - {//dont add "nothing" to the search filters. - }else{ - stlist.push_back(s); - } + if (mNew && mParent) mParent->addColumn(); + mNew = false; + if (filterVal > -1 && filterVal < (int) mParent->tempArgs.size()) + { + displayValue = mParent->tempArgs[filterVal].first; + mCode = mParent->tempArgs[filterVal].second; } - std::sort(stlist.begin(),stlist.end()); - for(size_t t=0;taddArg(s,buf); - } - }else if(filterType == FILTER_RARITY){ - mParent->addArg("Mythic","r:m;"); - mParent->addArg("Rare","r:r;"); - mParent->addArg("Uncommon","r:u;"); - mParent->addArg("Common","r:c;"); - mParent->addArg("Special Rarity","{r:m;|r:t;|r:r;|r:u;|r:c;}"); - }else if(filterType == FILTER_CMC){ - for(int i=0;i<20;i++){ - sprintf(buf_code,"cmc:%i;",i); - sprintf(buf_name,"%i Mana",i); - mParent->addArg(buf_name,buf_code); - } - }else if(filterType == FILTER_POWER){ - for(int i=0;i<14;i++){ - sprintf(buf_code,"pow:%i;",i); - sprintf(buf_name,"%i power",i); - mParent->addArg(buf_name,buf_code); - } - }else if(filterType == FILTER_TOUGH){ - for(int i=0;i<14;i++){ - sprintf(buf_code,"tgh:%i;",i); - sprintf(buf_name,"%i toughness",i); - mParent->addArg(buf_name,buf_code); - } - }else if(filterType == FILTER_COLOR){ - mParent->addArg("White","c:w;"); - mParent->addArg("Blue","c:u;"); - mParent->addArg("Black","c:b;"); - mParent->addArg("Red","c:r;"); - mParent->addArg("Green","c:g;"); - mParent->addArg("Exclusively White","xc:w;"); - mParent->addArg("Exclusively Blue","xc:u;"); - mParent->addArg("Exclusively Black","xc:b;"); - mParent->addArg("Exclusively Red","xc:r;"); - mParent->addArg("Exclusively Green","xc:g;"); - }else if(filterType == FILTER_PRODUCE){ - mParent->addArg("White mana abiltity","ma:w;"); - mParent->addArg("Blue mana abiltity","ma:u;"); - mParent->addArg("Black mana abiltity","ma:b;"); - mParent->addArg("Red mana abiltity","ma:r;"); - mParent->addArg("Green mana abiltity","ma:g;"); - mParent->addArg("Colorless mana abiltity","ma:x;"); - }else if(filterType == FILTER_BASIC){ - char buf[512]; - for(int i=0;iaddArg(s,buf); - } - }else if(filterType == FILTER_SET){ - char buf[512]; - for(int i=0;iaddArg((setlist.getInfo(i))->getName(),buf); - } - }else if(filterType == FILTER_ALPHA){ - char buf[24], pretty[16]; - for(char c='a';c<='z';c++){ - sprintf(buf,"alpha:%c;",c); - sprintf(pretty,"Letter %c",toupper(c)); - mParent->addArg(pretty,buf); - } - mParent->addArg("Digit","alpha:#;"); - } - mParent->subMenu->Add(kCancelMenuID,"Cancel"); - break; - case STATE_CHOOSE_VAL: - mState = STATE_FINISHED; - if(mNew && mParent) - mParent->addColumn(); - mNew = false; - if(filterVal > -1 && filterVal < (int) mParent->tempArgs.size()){ - displayValue = mParent->tempArgs[filterVal].first; - mCode = mParent->tempArgs[filterVal].second; - } - SAFE_DELETE(mParent->subMenu); - break; - } + SAFE_DELETE(mParent->subMenu); + break; + } } -void WGuiFilterItem::ButtonPressed(int controllerId, int controlId){ - if(!mParent) return; +void WGuiFilterItem::ButtonPressed(int controllerId, int controlId) +{ + if (!mParent) return; - switch(mState){ + switch (mState) + { case STATE_CHOOSE_TYPE: - if(controlId == -1){ - mParent->subMenu->Close(); - mState = STATE_CANCEL; return; - }else if(controlId == -2){ - mParent->subMenu->Close(); - mState = STATE_REMOVE; return; - } - filterType = controlId; - break; + if (controlId == -1) + { + mParent->subMenu->Close(); + mState = STATE_CANCEL; + return; + } + else if (controlId == -2) + { + mParent->subMenu->Close(); + mState = STATE_REMOVE; + return; + } + filterType = controlId; + break; case STATE_CHOOSE_VAL: - if(controlId == -1){ - mParent->subMenu->Close(); - mState = STATE_UNSET; return; - }else if(controlId == -2){ - mParent->subMenu->Close(); - mState = STATE_REMOVE; return; - } - filterVal = controlId; - break; - } - updateValue(); + if (controlId == -1) + { + mParent->subMenu->Close(); + mState = STATE_UNSET; + return; + } + else if (controlId == -2) + { + mParent->subMenu->Close(); + mState = STATE_REMOVE; + return; + } + filterVal = controlId; + break; + } + updateValue(); } -bool WGuiFilterItem::isModal(){ - switch(mState){ +bool WGuiFilterItem::isModal() +{ + switch (mState) + { case STATE_UNSET: case STATE_REMOVE: case STATE_CANCEL: case STATE_FINISHED: - return false; - } - return true; -} - -string WGuiFilterItem::getCode(){ - if(mState != STATE_FINISHED || !mCode.size()) - return ""; - return mCode; -} - -WGuiKeyBinder::WGuiKeyBinder(string name, GameStateOptions* parent) : WGuiList(name), parent(parent), confirmMenu(NULL), modal(false), confirmed(CONFIRM_NEED), confirmingKey(LOCAL_KEY_NONE), confirmingButton(JGE_BTN_NONE), confirmationString("") { - JGE* j = JGE::GetInstance(); - JGE::keybindings_it start = j->KeyBindings_begin(), end = j->KeyBindings_end(); - - Add(NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE)); - for (JGE::keybindings_it it = start; it != end; ++it) - Add(NEW OptionKey(parent, it->first, it->second)); -} -void WGuiKeyBinder::Update(float dt) { - OptionKey* o = dynamic_cast(items[0]); - if (!o) return; - if (LOCAL_KEY_NONE != o->from) { - items.insert(items.begin(), NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE)); - if (0 == currentItem) ++currentItem; + return false; } - for (vector::iterator it = items.begin(); it != items.end(); ++it) (*it)->Update(dt); - if (confirmMenu) confirmMenu->Update(dt); -} -bool WGuiKeyBinder::isModal() { - for (vector::iterator it = items.begin(); it != items.end(); ++it) - if ((*it)->isModal()) return true; - return modal; -} -bool WGuiKeyBinder::CheckUserInput(JButton key) { - if (confirmMenu) - return confirmMenu->CheckUserInput(key); - if (!items[currentItem]->CheckUserInput(key)) - return WGuiList::CheckUserInput(key); - if (!items[currentItem]->Selectable()) - nextItem(); - return true; -} -void WGuiKeyBinder::setData() { - JGE* j = JGE::GetInstance(); - j->ClearBindings(); - for (vector::iterator it = items.begin(); it != items.end(); ++it) { - OptionKey* o = static_cast(*it); - if (o && LOCAL_KEY_NONE != o->from && JGE_BTN_NONE != o->to) - j->BindKey(o->from, o->to); - } - j->ResetInput(); + return true; } -static const JButton btnToCheck[] = {JGE_BTN_MENU, JGE_BTN_CTRL, JGE_BTN_RIGHT, - JGE_BTN_LEFT, JGE_BTN_UP, JGE_BTN_DOWN, - JGE_BTN_OK, JGE_BTN_CANCEL, JGE_BTN_PRI, - JGE_BTN_SEC, JGE_BTN_PREV, JGE_BTN_NEXT }; +string WGuiFilterItem::getCode() +{ + if (mState != STATE_FINISHED || !mCode.size()) return ""; + return mCode; +} + +WGuiKeyBinder::WGuiKeyBinder(string name, GameStateOptions* parent) : + WGuiList(name), parent(parent), confirmMenu(NULL), modal(false), confirmed(CONFIRM_NEED), confirmingKey(LOCAL_KEY_NONE), + confirmingButton(JGE_BTN_NONE), confirmationString("") +{ + JGE* j = JGE::GetInstance(); + JGE::keybindings_it start = j->KeyBindings_begin(), end = j->KeyBindings_end(); + + Add(NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE)); + for (JGE::keybindings_it it = start; it != end; ++it) + Add(NEW OptionKey(parent, it->first, it->second)); +} +void WGuiKeyBinder::Update(float dt) +{ + OptionKey* o = dynamic_cast (items[0]); + if (!o) return; + if (LOCAL_KEY_NONE != o->from) + { + items.insert(items.begin(), NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE)); + if (0 == currentItem) ++currentItem; + } + for (vector::iterator it = items.begin(); it != items.end(); ++it) + (*it)->Update(dt); + if (confirmMenu) confirmMenu->Update(dt); +} +bool WGuiKeyBinder::isModal() +{ + for (vector::iterator it = items.begin(); it != items.end(); ++it) + if ((*it)->isModal()) return true; + return modal; +} +bool WGuiKeyBinder::CheckUserInput(JButton key) +{ + if (confirmMenu) return confirmMenu->CheckUserInput(key); + if (!items[currentItem]->CheckUserInput(key)) return WGuiList::CheckUserInput(key); + if (!items[currentItem]->Selectable()) nextItem(); + return true; +} +void WGuiKeyBinder::setData() +{ + JGE* j = JGE::GetInstance(); + j->ClearBindings(); + for (vector::iterator it = items.begin(); it != items.end(); ++it) + { + OptionKey* o = static_cast (*it); + if (o && LOCAL_KEY_NONE != o->from && JGE_BTN_NONE != o->to) j->BindKey(o->from, o->to); + } + j->ResetInput(); +} + +static const JButton btnToCheck[] = { JGE_BTN_MENU, JGE_BTN_CTRL, JGE_BTN_RIGHT, JGE_BTN_LEFT, JGE_BTN_UP, JGE_BTN_DOWN, + JGE_BTN_OK, JGE_BTN_CANCEL, JGE_BTN_PRI, JGE_BTN_SEC, JGE_BTN_PREV, JGE_BTN_NEXT }; #define C(o) (static_cast(o)) -WGuiBase::CONFIRM_TYPE WGuiKeyBinder::needsConfirm() { - if (CONFIRM_CANCEL == confirmed) { confirmedKeys.clear(); confirmedButtons.clear(); confirmed = CONFIRM_NEED; return CONFIRM_CANCEL; } - if (confirmMenu) return CONFIRM_NEED; +WGuiBase::CONFIRM_TYPE WGuiKeyBinder::needsConfirm() +{ + if (CONFIRM_CANCEL == confirmed) + { + confirmedKeys.clear(); + confirmedButtons.clear(); + confirmed = CONFIRM_NEED; + return CONFIRM_CANCEL; + } + if (confirmMenu) return CONFIRM_NEED; - // Check whether any key is bound to two functions. - confirmingKey = LOCAL_KEY_NONE; - for (vector::iterator it = items.begin(); it != items.end(); ++it) { - if (!(*it)->Visible()) continue; + // Check whether any key is bound to two functions. + confirmingKey = LOCAL_KEY_NONE; + for (vector::iterator it = items.begin(); it != items.end(); ++it) + { + if (!(*it)->Visible()) continue; - vector boundFunctionsList; - for (vector::iterator jt = it + 1; jt != items.end(); ++jt) { - if (!(*jt)->Visible()) continue; - if (C(*it)->from == C(*jt)->from) - if (confirmedKeys.end() == find(confirmedKeys.begin(), confirmedKeys.end(), C(*it)->from)) { + vector boundFunctionsList; + for (vector::iterator jt = it + 1; jt != items.end(); ++jt) + { + if (!(*jt)->Visible()) continue; + if (C(*it)->from == C(*jt)->from) if (confirmedKeys.end() == find(confirmedKeys.begin(), confirmedKeys.end(), + C(*it)->from)) + { confirmingKey = C(*it)->from; if (boundFunctionsList.empty()) boundFunctionsList.push_back(C(*it)->to); boundFunctionsList.push_back(C(*jt)->to); } } - if (LOCAL_KEY_NONE != confirmingKey) { - // There is a conflict. Generate the error message... - char s[1024]; - snprintf(s, 1024, _("Warning : the %s key is bound to\n%i different functions:").c_str(), translateKey(confirmingKey).first.c_str(), boundFunctionsList.size()); - stringstream ss; - ss << s << "\n"; - vector::iterator jt = boundFunctionsList.begin(); - ss << translateKey(*jt).first.c_str(); - for (++jt; jt != boundFunctionsList.end(); ++jt) ss << ", " << translateKey(*jt).first.c_str(); - confirmationString = ss.str(); + if (LOCAL_KEY_NONE != confirmingKey) + { + // There is a conflict. Generate the error message... + char s[1024]; + snprintf(s, 1024, _("Warning : the %s key is bound to\n%i different functions:").c_str(), + translateKey(confirmingKey).first.c_str(), boundFunctionsList.size()); + stringstream ss; + ss << s << "\n"; + vector::iterator jt = boundFunctionsList.begin(); + ss << translateKey(*jt).first.c_str(); + for (++jt; jt != boundFunctionsList.end(); ++jt) + ss << ", " << translateKey(*jt).first.c_str(); + confirmationString = ss.str(); - // Then create the menu. - confirmMenu = NEW SimpleMenu(0, this, Fonts::MENU_FONT, 40, 130, "Conflict"); + // Then create the menu. + confirmMenu = NEW SimpleMenu(0, this, Fonts::MENU_FONT, 40, 130, "Conflict"); + confirmMenu->Add(1, _("Cancel and return to the options menu").c_str()); + confirmMenu->Add(2, _("This is okay, validate and save").c_str()); + return CONFIRM_NEED; + } + } + + // Check whether any button has no key associated to it. + confirmingButton = JGE_BTN_NONE; + for (signed int i = (sizeof(btnToCheck) / sizeof(btnToCheck[0])) - 1; i >= 0; --i) + { + if (confirmedButtons.end() != find(confirmedButtons.begin(), confirmedButtons.end(), btnToCheck[i])) continue; + bool found = false; + for (vector::iterator it = items.begin(); it != items.end(); ++it) + if (btnToCheck[i] == C(*it)->to) + { + found = true; + break; + } + if (found) continue; + + char s[1024]; + snprintf(s, 1024, _("Warning : no key is associated to\nthe %s function.\nThis may make the game unusable.").c_str(), + translateKey(btnToCheck[i]).first.c_str()); + confirmationString = s; + + confirmingButton = btnToCheck[i]; + confirmMenu = NEW SimpleMenu(1, this, Fonts::MENU_FONT, 40, 130, "Binding missing"); confirmMenu->Add(1, _("Cancel and return to the options menu").c_str()); confirmMenu->Add(2, _("This is okay, validate and save").c_str()); return CONFIRM_NEED; - } } - // Check whether any button has no key associated to it. - confirmingButton = JGE_BTN_NONE; - for (signed int i = (sizeof(btnToCheck) / sizeof(btnToCheck[0])) - 1; i >= 0; --i) { - if (confirmedButtons.end() != find(confirmedButtons.begin(), confirmedButtons.end(), btnToCheck[i])) continue; - bool found = false; - for (vector::iterator it = items.begin(); it != items.end(); ++it) - if (btnToCheck[i] == C(*it)->to) { found = true; break; } - if (found) continue; - - char s[1024]; - snprintf(s, 1024, _("Warning : no key is associated to\nthe %s function.\nThis may make the game unusable.").c_str(), translateKey(btnToCheck[i]).first.c_str()); - confirmationString = s; - - confirmingButton = btnToCheck[i]; - confirmMenu = NEW SimpleMenu(1, this, Fonts::MENU_FONT, 40, 130, "Binding missing"); - confirmMenu->Add(1, _("Cancel and return to the options menu").c_str()); - confirmMenu->Add(2, _("This is okay, validate and save").c_str()); - return CONFIRM_NEED; - } - - return CONFIRM_OK; + return CONFIRM_OK; } -void WGuiKeyBinder::ButtonPressed(int controllerId, int controlId) { - if (2 == controlId) - switch(controllerId) { - case 0: confirmedKeys.insert(confirmingKey); break; - case 1: confirmedButtons.insert(confirmingButton); break; +void WGuiKeyBinder::ButtonPressed(int controllerId, int controlId) +{ + if (2 == controlId) + switch (controllerId) + { + case 0: + confirmedKeys.insert(confirmingKey); + break; + case 1: + confirmedButtons.insert(confirmingButton); + break; + } + else + confirmed = CONFIRM_CANCEL; + SAFE_DELETE(confirmMenu); + confirmMenu = NULL; +} +void WGuiKeyBinder::Render() +{ + WGuiList::Render(); + if (confirmMenu) + { + JRenderer * renderer = JRenderer::GetInstance(); + WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); + mFont->SetColor(ARGB(255, 255, 0, 0)); + renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(230, 255, 240, 240)); + + size_t pos = 0; + float y = 20; + do + { + size_t t = confirmationString.find_first_of("\n", pos); + string s = confirmationString.substr(pos, t - pos); + pos = (string::npos == t) ? t : t + 1; + mFont->DrawString(s, SCREEN_WIDTH / 2, y, JGETEXT_CENTER); + y += 20; + } while (pos != string::npos); + confirmMenu->Render(); } - else - confirmed = CONFIRM_CANCEL; - SAFE_DELETE(confirmMenu); - confirmMenu = NULL; } -void WGuiKeyBinder::Render() { - WGuiList::Render(); - if (confirmMenu) { - JRenderer * renderer = JRenderer::GetInstance(); - WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT); - mFont->SetColor(ARGB(255, 255, 0, 0)); - renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(230, 255, 240, 240)); - - size_t pos = 0; - float y = 20; - do { - size_t t = confirmationString.find_first_of("\n", pos); - string s = confirmationString.substr(pos, t - pos); - pos = (string::npos == t) ? t : t + 1; - mFont->DrawString(s, SCREEN_WIDTH / 2, y, JGETEXT_CENTER); - y += 20; - } while (pos != string::npos); - confirmMenu->Render(); - } -} -bool WGuiKeyBinder::yieldFocus() { - return true; +bool WGuiKeyBinder::yieldFocus() +{ + return true; } diff --git a/projects/mtg/src/WResourceManager.cpp b/projects/mtg/src/WResourceManager.cpp index 4c937b2b0..4b49bef19 100644 --- a/projects/mtg/src/WResourceManager.cpp +++ b/projects/mtg/src/WResourceManager.cpp @@ -22,1444 +22,1518 @@ WResourceManager resources; namespace { - const std::string kExtension_png(".png"); - const std::string kExtension_gbk(".gbk"); - const std::string kExtension_font(".font"); + const std::string kExtension_png(".png"); + const std::string kExtension_gbk(".gbk"); + const std::string kExtension_font(".font"); } -int WResourceManager::RetrieveError(){ - return lastError; +int WResourceManager::RetrieveError() +{ + return lastError; } -bool WResourceManager::RemoveOldest(){ - if(sampleWCache.RemoveOldest()) - return true; - if(textureWCache.RemoveOldest()) - return true; - if(psiWCache.RemoveOldest()) - return true; +bool WResourceManager::RemoveOldest() +{ + if (sampleWCache.RemoveOldest()) return true; + if (textureWCache.RemoveOldest()) return true; + if (psiWCache.RemoveOldest()) return true; - return false; + return false; } //WResourceManager -void WResourceManager::DebugRender(){ - JRenderer* renderer = JRenderer::GetInstance(); - WFont * font = resources.GetWFont(Fonts::MAIN_FONT); - font->SetColor(ARGB(255,255,255,255)); - - if(!font || !renderer) - return; - - font->SetScale(DEFAULT_MAIN_FONT_SCALE); - renderer->FillRect(0,0,SCREEN_WIDTH,40,ARGB(128,155,0,0)); +void WResourceManager::DebugRender() +{ + JRenderer* renderer = JRenderer::GetInstance(); + WFont * font = resources.GetWFont(Fonts::MAIN_FONT); + font->SetColor(ARGB(255,255,255,255)); - renderer->FillRect(0,SCREEN_HEIGHT-20,SCREEN_WIDTH,40,ARGB(128,155,0,0)); - char buf[512]; + if (!font || !renderer) return; - - unsigned long man = 0; - unsigned int misses = 0; + font->SetScale(DEFAULT_MAIN_FONT_SCALE); + renderer->FillRect(0, 0, SCREEN_WIDTH, 40, ARGB(128,155,0,0)); - if(textureWCache.cacheItems < textureWCache.cache.size()) - misses = textureWCache.cache.size()-textureWCache.cacheItems; + renderer->FillRect(0, SCREEN_HEIGHT - 20, SCREEN_WIDTH, 40, ARGB(128,155,0,0)); + char buf[512]; - if(textureWCache.totalSize > textureWCache.cacheSize) - man = textureWCache.totalSize - textureWCache.cacheSize; + unsigned long man = 0; + unsigned int misses = 0; - sprintf(buf,"Textures %u+%llu (of %u) items (%u misses), Pixels: %lu (of %lu) + %lu", - textureWCache.cacheItems, (long long unsigned int)textureWCache.managed.size(),textureWCache.maxCached, - misses,textureWCache.cacheSize,textureWCache.maxCacheSize,man); - font->DrawString(buf, 10,5); + if (textureWCache.cacheItems < textureWCache.cache.size()) misses = textureWCache.cache.size() - textureWCache.cacheItems; + if (textureWCache.totalSize > textureWCache.cacheSize) man = textureWCache.totalSize - textureWCache.cacheSize; + + sprintf(buf, "Textures %u+%llu (of %u) items (%u misses), Pixels: %lu (of %lu) + %lu", textureWCache.cacheItems, + (long long unsigned int) textureWCache.managed.size(), textureWCache.maxCached, misses, + textureWCache.cacheSize, textureWCache.maxCacheSize, man); + font->DrawString(buf, 10, 5); #if defined (WIN32) || defined (LINUX) #else - int maxLinear = ramAvailableLineareMax(); - int ram = ramAvailable(); - sprintf(buf, "Ram : linear max: %i - total : %i\n",maxLinear, ram); - font->DrawString(buf,10, 20); + int maxLinear = ramAvailableLineareMax(); + int ram = ramAvailable(); + sprintf(buf, "Ram : linear max: %i - total : %i\n", maxLinear, ram); + font->DrawString(buf, 10, 20); #endif - - sprintf(buf,"Time: %u. Total Size: %lu (%lu cached, %lu managed). ",lastTime,Size(),SizeCached(),SizeManaged()); - font->DrawString(buf, SCREEN_WIDTH-10,SCREEN_HEIGHT-15,JGETEXT_RIGHT); + sprintf(buf, "Time: %u. Total Size: %lu (%lu cached, %lu managed). ", lastTime, Size(), SizeCached(), SizeManaged()); + font->DrawString(buf, SCREEN_WIDTH - 10, SCREEN_HEIGHT - 15, JGETEXT_RIGHT); #ifdef DEBUG_CACHE - if(debugMessage.size()) + if(debugMessage.size()) font->DrawString(debugMessage.c_str(), SCREEN_WIDTH-10,SCREEN_HEIGHT-25,JGETEXT_RIGHT); #endif } -unsigned long WResourceManager::Size(){ - unsigned long res = 0; - res += textureWCache.totalSize; - res += sampleWCache.totalSize; - res += psiWCache.totalSize; - return res; +unsigned long WResourceManager::Size() +{ + unsigned long res = 0; + res += textureWCache.totalSize; + res += sampleWCache.totalSize; + res += psiWCache.totalSize; + return res; } -unsigned long WResourceManager::SizeCached(){ - unsigned long res = 0; - res += textureWCache.cacheSize; - res += sampleWCache.cacheSize; - res += psiWCache.cacheSize; - return res; +unsigned long WResourceManager::SizeCached() +{ + unsigned long res = 0; + res += textureWCache.cacheSize; + res += sampleWCache.cacheSize; + res += psiWCache.cacheSize; + return res; } -unsigned long WResourceManager::SizeManaged(){ - unsigned long res = 0; - if(textureWCache.totalSize > textureWCache.cacheSize) - res += textureWCache.totalSize - textureWCache.cacheSize; +unsigned long WResourceManager::SizeManaged() +{ + unsigned long res = 0; + if (textureWCache.totalSize > textureWCache.cacheSize) res += textureWCache.totalSize - textureWCache.cacheSize; - if(sampleWCache.totalSize > sampleWCache.cacheSize) - res += sampleWCache.totalSize - sampleWCache.cacheSize; + if (sampleWCache.totalSize > sampleWCache.cacheSize) res += sampleWCache.totalSize - sampleWCache.cacheSize; - if(psiWCache.totalSize > psiWCache.cacheSize) - res += psiWCache.totalSize - psiWCache.cacheSize; + if (psiWCache.totalSize > psiWCache.cacheSize) res += psiWCache.totalSize - psiWCache.cacheSize; - return res; + return res; } -unsigned int WResourceManager::Count(){ - unsigned int count = 0; - count += textureWCache.cacheItems; - count += textureWCache.managed.size(); - count += sampleWCache.cacheItems; - count += sampleWCache.managed.size(); - count += psiWCache.cacheItems; - count += psiWCache.managed.size(); - return count; +unsigned int WResourceManager::Count() +{ + unsigned int count = 0; + count += textureWCache.cacheItems; + count += textureWCache.managed.size(); + count += sampleWCache.cacheItems; + count += sampleWCache.managed.size(); + count += psiWCache.cacheItems; + count += psiWCache.managed.size(); + return count; } -unsigned int WResourceManager::CountCached(){ - unsigned int count = 0; - count += textureWCache.cacheItems; - count += sampleWCache.cacheItems; - count += psiWCache.cacheItems; - return count; +unsigned int WResourceManager::CountCached() +{ + unsigned int count = 0; + count += textureWCache.cacheItems; + count += sampleWCache.cacheItems; + count += psiWCache.cacheItems; + return count; } -unsigned int WResourceManager::CountManaged(){ - unsigned int count = 0; - count += textureWCache.managed.size(); - count += sampleWCache.managed.size(); - count += psiWCache.managed.size(); - return count; +unsigned int WResourceManager::CountManaged() +{ + unsigned int count = 0; + count += textureWCache.managed.size(); + count += sampleWCache.managed.size(); + count += psiWCache.managed.size(); + return count; } -unsigned int WResourceManager::nowTime(){ - if(lastTime > MAX_CACHE_TIME) - FlattenTimes(); - - return ++lastTime; +unsigned int WResourceManager::nowTime() +{ + if (lastTime > MAX_CACHE_TIME) FlattenTimes(); + + return ++lastTime; } -void WResourceManager::FlattenTimes(){ - unsigned int t; - lastTime = sampleWCache.Flatten(); +void WResourceManager::FlattenTimes() +{ + unsigned int t; + lastTime = sampleWCache.Flatten(); - t = textureWCache.Flatten(); - if(t > lastTime) - lastTime = t; + t = textureWCache.Flatten(); + if (t > lastTime) lastTime = t; - t = psiWCache.Flatten(); - if(t > lastTime) - lastTime = t; + t = psiWCache.Flatten(); + if (t > lastTime) lastTime = t; } -WResourceManager::WResourceManager(){ - DebugTrace("Init WResourceManager : " << this); +WResourceManager::WResourceManager() +{ + DebugTrace("Init WResourceManager : " << this); #ifdef DEBUG_CACHE - menuCached = 0; + menuCached = 0; #endif - mTextureList.clear(); - mTextureList.reserve(0); - mTextureMap.clear(); + mTextureList.clear(); + mTextureList.reserve(0); + mTextureMap.clear(); - mQuadList.clear(); - mQuadList.reserve(0); - mQuadMap.clear(); + mQuadList.clear(); + mQuadList.reserve(0); + mQuadMap.clear(); - psiWCache.Resize(PSI_CACHE_SIZE,20); - sampleWCache.Resize(SAMPLES_CACHE_SIZE,MAX_CACHED_SAMPLES); - textureWCache.Resize(TEXTURES_CACHE_MINSIZE,MAX_CACHE_OBJECTS); - lastTime = 0; - lastError = CACHE_ERROR_NONE; + psiWCache.Resize(PSI_CACHE_SIZE, 20); + sampleWCache.Resize(SAMPLES_CACHE_SIZE, MAX_CACHED_SAMPLES); + textureWCache.Resize(TEXTURES_CACHE_MINSIZE, MAX_CACHE_OBJECTS); + lastTime = 0; + lastError = CACHE_ERROR_NONE; - bThemedCards = false; + bThemedCards = false; } -WResourceManager::~WResourceManager(){ - LOG("==Destroying WResourceManager=="); - RemoveAll(); - RemoveWFonts(); +WResourceManager::~WResourceManager() +{ + LOG("==Destroying WResourceManager=="); + RemoveAll(); + RemoveWFonts(); - LOG("==Successfully Destroyed WResourceManager=="); + LOG("==Successfully Destroyed WResourceManager=="); } -JQuad * WResourceManager::RetrieveCard(MTGCard * card, int style, int submode){ - //Cards are never, ever resource managed, so just check cache. - if(!card || options[Options::DISABLECARDS].number) - return NULL; +JQuad * WResourceManager::RetrieveCard(MTGCard * card, int style, int submode) +{ + //Cards are never, ever resource managed, so just check cache. + if (!card || options[Options::DISABLECARDS].number) return NULL; - submode = submode | TEXTURE_SUB_CARD; + submode = submode | TEXTURE_SUB_CARD; - string filename = setlist[card->setId]; - filename += "/"; - string filename1 = filename + card->getImageName(); - int id = card->getMTGId(); + string filename = setlist[card->setId]; + filename += "/"; + string filename1 = filename + card->getImageName(); + int id = card->getMTGId(); - //Aliases. - if(style == RETRIEVE_THUMB){ - submode = submode | TEXTURE_SUB_THUMB; - style = RETRIEVE_NORMAL; - } + //Aliases. + if (style == RETRIEVE_THUMB) + { + submode = submode | TEXTURE_SUB_THUMB; + style = RETRIEVE_NORMAL; + } - //Hack to allow either ID or card name as a filename for a given card. - // When missing the first attempt (for example [id].jpg), the cache assigns a "404" to the card's image cache, - // Preventing us to try a second time with [name].jpg. - //To bypass this, we first check if the card was ever marked as "null". If not, it means it's the first time we're looking for it - // In that case, we "unmiss" it after trying the [id].jpg, in order to give a chance to the [name.jpg] - bool canUnmiss = false; - { - JQuad * tempQuad = RetrieveQuad(filename1,0,0,0,0, "",RETRIEVE_EXISTING,submode|TEXTURE_SUB_5551,id); + //Hack to allow either ID or card name as a filename for a given card. + // When missing the first attempt (for example [id].jpg), the cache assigns a "404" to the card's image cache, + // Preventing us to try a second time with [name].jpg. + //To bypass this, we first check if the card was ever marked as "null". If not, it means it's the first time we're looking for it + // In that case, we "unmiss" it after trying the [id].jpg, in order to give a chance to the [name.jpg] + bool canUnmiss = false; + { + JQuad * tempQuad = RetrieveQuad(filename1, 0, 0, 0, 0, "", RETRIEVE_EXISTING, submode | TEXTURE_SUB_5551, id); + lastError = textureWCache.mError; + if (!tempQuad && lastError != CACHE_ERROR_404) + { + canUnmiss = true; + } + } + JQuad * jq = RetrieveQuad(filename1, 0, 0, 0, 0, "", style, submode | TEXTURE_SUB_5551, id); + if (!jq) + { + if (canUnmiss) + { + int mId = id; + //To differentiate between cached thumbnails and the real thing. + if (submode & TEXTURE_SUB_THUMB) + { + if (mId < 0) + mId -= THUMBNAILS_OFFSET; + else + mId += THUMBNAILS_OFFSET; + } + textureWCache.RemoveMiss(mId); + } + filename1 = filename + card->data->getName() + ".jpg"; + jq = RetrieveQuad(filename1, 0, 0, 0, 0, "", style, submode | TEXTURE_SUB_5551, id); + int i = 0; //TODO remove debug test; + } lastError = textureWCache.mError; - if (!tempQuad && lastError != CACHE_ERROR_404){ - canUnmiss = true; + if (jq) + { + jq->SetHotSpot(static_cast (jq->mTex->mWidth / 2), static_cast (jq->mTex->mHeight / 2)); + return jq; } - } - JQuad * jq = RetrieveQuad(filename1,0,0,0,0, "",style,submode|TEXTURE_SUB_5551,id); - if (!jq) { - if (canUnmiss) { - int mId = id; - //To differentiate between cached thumbnails and the real thing. - if(submode & TEXTURE_SUB_THUMB){ - if (mId < 0) - mId-=THUMBNAILS_OFFSET; - else - mId+=THUMBNAILS_OFFSET; - } - textureWCache.RemoveMiss(mId); - } - filename1 = filename + card->data->getName() + ".jpg"; - jq = RetrieveQuad(filename1,0,0,0,0, "",style,submode|TEXTURE_SUB_5551,id); - int i = 0; //TODO remove debug test; - } - lastError = textureWCache.mError; - if(jq){ - jq->SetHotSpot(static_cast(jq->mTex->mWidth / 2), static_cast(jq->mTex->mHeight / 2)); - return jq; - } - - return NULL; + + return NULL; } int WResourceManager::AddQuadToManaged(const WManagedQuad& inQuad) { - int id = mIDLookupMap.size(); - mIDLookupMap.insert(make_pair(id, inQuad.resname)); - mManagedQuads.insert(make_pair(inQuad.resname, inQuad)); + int id = mIDLookupMap.size(); + mIDLookupMap.insert(make_pair(id, inQuad.resname)); + mManagedQuads.insert(make_pair(inQuad.resname, inQuad)); - return id; -} - -int WResourceManager::CreateQuad(const string &quadName, const string &textureName, float x, float y, float width, float height){ - if(!quadName.size() || !textureName.size()) - return INVALID_ID; - - if (GetQuad(quadName) != NULL) - { - assert(false); - return ALREADY_EXISTS; - } - - WCachedTexture * jtex = textureWCache.Retrieve(0,textureName,RETRIEVE_MANAGE); - lastError = textureWCache.mError; - int id = INVALID_ID; - //Somehow, jtex wasn't promoted. - if(RETRIEVE_MANAGE && jtex && !jtex->isPermanent()) return id; - - if(jtex){ - WTrackedQuad * tq = jtex->GetTrackedQuad(x,y,width,height,quadName); - - if(tq){ - tq->deadbolt(); - - WManagedQuad mq; - mq.resname = quadName; - mq.texture = jtex; - id = AddQuadToManaged(mq); - } - } - - assert(id != INVALID_ID); - return id; } -JQuad* WResourceManager::GetQuad(const string &quadName){ +int WResourceManager::CreateQuad(const string &quadName, const string &textureName, float x, float y, float width, float height) +{ + if (!quadName.size() || !textureName.size()) return INVALID_ID; - JQuad* result = NULL; - ManagedQuadMap::const_iterator found = mManagedQuads.find(quadName); - if (found != mManagedQuads.end()) - { - result = found->second.texture->GetQuad(quadName); - } - - return result; -} - -JQuad * WResourceManager::GetQuad(int id){ - - JQuad* result = NULL; - if(id < 0 || id >= (int) mManagedQuads.size()) - return result; - - IDLookupMap::const_iterator key = mIDLookupMap.find(id); - if (key != mIDLookupMap.end()) - { - WCachedTexture * jtex = mManagedQuads[key->second].texture; - if(jtex) + if (GetQuad(quadName) != NULL) { - result = jtex->GetQuad(key->second); - } - } - - return result; -} - -JQuad * WResourceManager::RetrieveTempQuad(string filename,int submode){ - return RetrieveQuad(filename,0,0,0,0,"temporary",RETRIEVE_NORMAL,submode); -} - -JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY, float width, float height, string resname, int style, int submode, int id){ - JQuad * jq = NULL; - - //Lookup managed resources, but only with a real resname. - if(resname.size() && (style == RETRIEVE_MANAGE || style == RETRIEVE_RESOURCE)){ - jq = GetQuad(resname); - if(jq || style == RETRIEVE_RESOURCE) - return jq; - } - - //Aliases. - if(style == RETRIEVE_THUMB){ - submode = submode | TEXTURE_SUB_THUMB; - style = RETRIEVE_NORMAL; - } - - //Resname defaults to filename. - if(!resname.size()) - resname = filename; - - //No quad, but we have a managed texture for this! - WCachedTexture * jtex = NULL; - if(style == RETRIEVE_MANAGE || style == RETRIEVE_EXISTING) - jtex = textureWCache.Retrieve(id,filename,style,submode); - else - jtex = textureWCache.Retrieve(id, filename,RETRIEVE_NORMAL,submode); - - lastError = textureWCache.mError; - - //Somehow, jtex wasn't promoted. - if(style == RETRIEVE_MANAGE && jtex && !jtex->isPermanent()) - return NULL; - - //Make this quad, overwriting any similarly resname'd quads. - if(jtex){ - WTrackedQuad * tq = jtex->GetTrackedQuad(offX,offY,width,height,resname); - - if(!tq) return NULL; - - if(style == RETRIEVE_MANAGE && resname != ""){ - WManagedQuad mq; - mq.resname = resname; - mq.texture = jtex; - AddQuadToManaged(mq); + assert(false); + return ALREADY_EXISTS; } - if(style == RETRIEVE_LOCK) - tq->lock(); - else if(style == RETRIEVE_UNLOCK) - tq->unlock(); - else if(style == RETRIEVE_MANAGE) - tq->deadbolt(); + WCachedTexture * jtex = textureWCache.Retrieve(0, textureName, RETRIEVE_MANAGE); + lastError = textureWCache.mError; + int id = INVALID_ID; + //Somehow, jtex wasn't promoted. + if (RETRIEVE_MANAGE && jtex && !jtex->isPermanent()) return id; - return tq->quad; - } + if (jtex) + { + WTrackedQuad * tq = jtex->GetTrackedQuad(x, y, width, height, quadName); - //Texture doesn't exist, so no quad. - return NULL; -} -void WResourceManager::Release(JTexture * tex){ - if(!tex) - return; + if (tq) + { + tq->deadbolt(); - //Copied direct from WCache::Release(). This is quick and dirty. - map::iterator it; - for(it=textureWCache.cache.begin();it!=textureWCache.cache.end();it++){ - if(it->second && it->second->compare(tex)) - break; - } + WManagedQuad mq; + mq.resname = quadName; + mq.texture = jtex; + id = AddQuadToManaged(mq); + } + } - if(it == textureWCache.cache.end()) - return; //Not here, can't release. - - if(it->second){ - it->second->unlock(); //Release one lock. - if(it->second->locks != WRES_UNLOCKED) //Normally we'd call isLocked, but this way ignores quads. - return; //Locked - } - - textureWCache.Delete(it->second); - textureWCache.cache.erase(it); - return; //Released! + assert(id != INVALID_ID); + return id; } -void WResourceManager::Unmiss(string filename){ - map::iterator it; - int id = textureWCache.makeID(0,filename,CACHE_NORMAL); - textureWCache.RemoveMiss(id); +JQuad* WResourceManager::GetQuad(const string &quadName) +{ + + JQuad* result = NULL; + ManagedQuadMap::const_iterator found = mManagedQuads.find(quadName); + if (found != mManagedQuads.end()) + { + result = found->second.texture->GetQuad(quadName); + } + + return result; } -void WResourceManager::ClearUnlocked(){ - textureWCache.ClearUnlocked(); - sampleWCache.ClearUnlocked(); - psiWCache.ClearUnlocked(); -} -bool WResourceManager::Cleanup(){ - int check = 0; +JQuad * WResourceManager::GetQuad(int id) +{ - if(textureWCache.Cleanup()) - check++; - if(sampleWCache.Cleanup()) - check++; - if(psiWCache.Cleanup()) - check++; + JQuad* result = NULL; + if (id < 0 || id >= (int) mManagedQuads.size()) return result; - return (check > 0); -} -void WResourceManager::Release(JSample * sample){ - if(!sample) - return; + IDLookupMap::const_iterator key = mIDLookupMap.find(id); + if (key != mIDLookupMap.end()) + { + WCachedTexture * jtex = mManagedQuads[key->second].texture; + if (jtex) + { + result = jtex->GetQuad(key->second); + } + } - sampleWCache.Release(sample); + return result; } -JTexture * WResourceManager::RetrieveTexture(string filename, int style, int submode){ - WCachedTexture * res = NULL; +JQuad * WResourceManager::RetrieveTempQuad(string filename, int submode) +{ + return RetrieveQuad(filename, 0, 0, 0, 0, "temporary", RETRIEVE_NORMAL, submode); +} - //Aliases. - if(style == RETRIEVE_THUMB){ - submode = submode | TEXTURE_SUB_THUMB; - style = RETRIEVE_NORMAL; - } +JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY, float width, float height, string resname, + int style, int submode, int id) +{ + JQuad * jq = NULL; - res = textureWCache.Retrieve(0,filename,style,submode); - lastError = textureWCache.mError; + //Lookup managed resources, but only with a real resname. + if (resname.size() && (style == RETRIEVE_MANAGE || style == RETRIEVE_RESOURCE)) + { + jq = GetQuad(resname); + if (jq || style == RETRIEVE_RESOURCE) return jq; + } - if(res){ //a non-null result will always be good. - JTexture * t = res->Actual(); - return t; - } + //Aliases. + if (style == RETRIEVE_THUMB) + { + submode = submode | TEXTURE_SUB_THUMB; + style = RETRIEVE_NORMAL; + } + + //Resname defaults to filename. + if (!resname.size()) resname = filename; + + //No quad, but we have a managed texture for this! + WCachedTexture * jtex = NULL; + if (style == RETRIEVE_MANAGE || style == RETRIEVE_EXISTING) + jtex = textureWCache.Retrieve(id, filename, style, submode); + else + jtex = textureWCache.Retrieve(id, filename, RETRIEVE_NORMAL, submode); + + lastError = textureWCache.mError; + + //Somehow, jtex wasn't promoted. + if (style == RETRIEVE_MANAGE && jtex && !jtex->isPermanent()) return NULL; + + //Make this quad, overwriting any similarly resname'd quads. + if (jtex) + { + WTrackedQuad * tq = jtex->GetTrackedQuad(offX, offY, width, height, resname); + + if (!tq) return NULL; + + if (style == RETRIEVE_MANAGE && resname != "") + { + WManagedQuad mq; + mq.resname = resname; + mq.texture = jtex; + AddQuadToManaged(mq); + } + + if (style == RETRIEVE_LOCK) + tq->lock(); + else if (style == RETRIEVE_UNLOCK) + tq->unlock(); + else if (style == RETRIEVE_MANAGE) tq->deadbolt(); + + return tq->quad; + } + + //Texture doesn't exist, so no quad. + return NULL; +} +void WResourceManager::Release(JTexture * tex) +{ + if (!tex) return; + + //Copied direct from WCache::Release(). This is quick and dirty. + map::iterator it; + for (it = textureWCache.cache.begin(); it != textureWCache.cache.end(); it++) + { + if (it->second && it->second->compare(tex)) break; + } + + if (it == textureWCache.cache.end()) return; //Not here, can't release. + + if (it->second) + { + it->second->unlock(); //Release one lock. + if (it->second->locks != WRES_UNLOCKED) //Normally we'd call isLocked, but this way ignores quads. + return; //Locked + } + + textureWCache.Delete(it->second); + textureWCache.cache.erase(it); + return; //Released! +} + +void WResourceManager::Unmiss(string filename) +{ + map::iterator it; + int id = textureWCache.makeID(0, filename, CACHE_NORMAL); + textureWCache.RemoveMiss(id); +} + +void WResourceManager::ClearUnlocked() +{ + textureWCache.ClearUnlocked(); + sampleWCache.ClearUnlocked(); + psiWCache.ClearUnlocked(); +} +bool WResourceManager::Cleanup() +{ + int check = 0; + + if (textureWCache.Cleanup()) check++; + if (sampleWCache.Cleanup()) check++; + if (psiWCache.Cleanup()) check++; + + return (check > 0); +} +void WResourceManager::Release(JSample * sample) +{ + if (!sample) return; + + sampleWCache.Release(sample); +} + +JTexture * WResourceManager::RetrieveTexture(string filename, int style, int submode) +{ + WCachedTexture * res = NULL; + + //Aliases. + if (style == RETRIEVE_THUMB) + { + submode = submode | TEXTURE_SUB_THUMB; + style = RETRIEVE_NORMAL; + } + + res = textureWCache.Retrieve(0, filename, style, submode); + lastError = textureWCache.mError; + + if (res) + { //a non-null result will always be good. + JTexture * t = res->Actual(); + return t; + } #ifdef DEBUG_CACHE - else{ - switch(textureWCache.mError){ - case CACHE_ERROR_NONE: - debugMessage = "Not in cache: "; - break; - case CACHE_ERROR_404: - debugMessage = "File not found: "; - break; - case CACHE_ERROR_BAD_ALLOC: - debugMessage = "Out of memory: "; - break; - case CACHE_ERROR_BAD: - debugMessage = "Cache bad: "; - break; - case CACHE_ERROR_NOT_MANAGED: - debugMessage = "Resource not managed: "; - break; - case CACHE_ERROR_LOST: - debugMessage = "Resource went bad, potential memory leak: "; - break; - default: - debugMessage = "Unspecified error: "; + else + { + switch(textureWCache.mError) + { + case CACHE_ERROR_NONE: + debugMessage = "Not in cache: "; + break; + case CACHE_ERROR_404: + debugMessage = "File not found: "; + break; + case CACHE_ERROR_BAD_ALLOC: + debugMessage = "Out of memory: "; + break; + case CACHE_ERROR_BAD: + debugMessage = "Cache bad: "; + break; + case CACHE_ERROR_NOT_MANAGED: + debugMessage = "Resource not managed: "; + break; + case CACHE_ERROR_LOST: + debugMessage = "Resource went bad, potential memory leak: "; + break; + default: + debugMessage = "Unspecified error: "; + } + debugMessage += filename; } - debugMessage += filename; - } #endif - return NULL; -} - -int WResourceManager::CreateTexture(const string &textureName) { - JTexture * jtex = RetrieveTexture(textureName,RETRIEVE_MANAGE); - - if(jtex) - return (int) jtex->mTexId; //Because it's unsigned on windows/linux. - - return INVALID_ID; -} - -JTexture* WResourceManager::GetTexture(const string &textureName){ - JTexture * jtex = RetrieveTexture(textureName,RETRIEVE_RESOURCE); - return jtex; -} - -JTexture* WResourceManager::GetTexture(int id){ - map::iterator it; - JTexture *jtex = NULL; - - if(id == INVALID_ID) return NULL; +} - for(it = textureWCache.managed.begin();it!= textureWCache.managed.end(); it++){ - if(it->second){ - jtex = it->second->Actual(); - if(id == (int) jtex->mTexId) - return jtex; +int WResourceManager::CreateTexture(const string &textureName) +{ + JTexture * jtex = RetrieveTexture(textureName, RETRIEVE_MANAGE); + + if (jtex) return (int) jtex->mTexId; //Because it's unsigned on windows/linux. + + return INVALID_ID; +} + +JTexture* WResourceManager::GetTexture(const string &textureName) +{ + JTexture * jtex = RetrieveTexture(textureName, RETRIEVE_RESOURCE); + return jtex; +} + +JTexture* WResourceManager::GetTexture(int id) +{ + map::iterator it; + JTexture *jtex = NULL; + + if (id == INVALID_ID) return NULL; + + for (it = textureWCache.managed.begin(); it != textureWCache.managed.end(); it++) + { + if (it->second) + { + jtex = it->second->Actual(); + if (id == (int) jtex->mTexId) return jtex; + } } - } - return jtex; + return jtex; } -hgeParticleSystemInfo * WResourceManager::RetrievePSI(string filename, JQuad * texture, int style, int submode){ - - if(!texture) +hgeParticleSystemInfo * WResourceManager::RetrievePSI(string filename, JQuad * texture, int style, int submode) +{ + + if (!texture) return NULL; + + WCachedParticles * res = psiWCache.Retrieve(0, filename, style, submode); + lastError = psiWCache.mError; + + if (res) //A non-null result will always be good. + { + hgeParticleSystemInfo * i = res->Actual(); + i->sprite = texture; + return i; + } + return NULL; - - WCachedParticles * res = psiWCache.Retrieve(0,filename,style,submode); - lastError = psiWCache.mError; - - if(res) //A non-null result will always be good. - { - hgeParticleSystemInfo * i = res->Actual(); - i->sprite = texture; - return i; - } - - return NULL; } -JSample * WResourceManager::RetrieveSample(string filename, int style, int submode){ - WCachedSample * tc = NULL; - tc = sampleWCache.Retrieve(0,filename,style,submode); - lastError = sampleWCache.mError; +JSample * WResourceManager::RetrieveSample(string filename, int style, int submode) +{ + WCachedSample * tc = NULL; + tc = sampleWCache.Retrieve(0, filename, style, submode); + lastError = sampleWCache.mError; - //Sample exists! Get it. - if(tc && tc->isGood()){ - JSample * js = tc->Actual(); - return js; - } + //Sample exists! Get it. + if (tc && tc->isGood()) + { + JSample * js = tc->Actual(); + return js; + } - return NULL; + return NULL; } -string WResourceManager::graphicsFile(const string filename){ +string WResourceManager::graphicsFile(const string filename) +{ char buf[512]; - + //Check the theme folder. string theme = options[Options::ACTIVE_THEME].str; //Check for a theme style renaming: - if(filename != "style.txt"){ - WStyle * ws = options.getStyle(); - if(ws){ - sprintf(buf,"themes/%s/%s",theme.c_str(),ws->stylized(filename).c_str()); - if(fileOK(buf,true)) - return buf; - } + if (filename != "style.txt") + { + WStyle * ws = options.getStyle(); + if (ws) + { + sprintf(buf, "themes/%s/%s", theme.c_str(), ws->stylized(filename).c_str()); + if (fileOK(buf, true)) return buf; + } } - if(theme != "" && theme != "Default"){ - sprintf(buf,"themes/%s/%s",theme.c_str(),filename.c_str()); + if (theme != "" && theme != "Default") + { + sprintf(buf, "themes/%s/%s", theme.c_str(), filename.c_str()); + if (fileOK(buf, true)) return buf; + } + /* + //FIXME Put back when we're using modes. + //Failure. Check mode graphics + string mode = options[Options::ACTIVE_MODE].str; + + if(mode != "" && mode != "Default"){ + sprintf(buf,"modes/%s/graphics/%s",mode.c_str(),filename.c_str()); if(fileOK(buf,true)) - return buf; - } -/* - //FIXME Put back when we're using modes. - //Failure. Check mode graphics - string mode = options[Options::ACTIVE_MODE].str; + return buf; + } + */ + //Failure. Check graphics + char graphdir[512]; + sprintf(graphdir, "graphics/%s", filename.c_str()); + if (fileOK(graphdir, true)) return graphdir; - if(mode != "" && mode != "Default"){ - sprintf(buf,"modes/%s/graphics/%s",mode.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; - } -*/ - //Failure. Check graphics - char graphdir[512]; - sprintf(graphdir,"graphics/%s",filename.c_str()); - if(fileOK(graphdir,true)) - return graphdir; - - //Failure. Check sets. - sprintf(buf,"sets/%s",filename.c_str()); - if(fileOK(buf,true)) - return buf; + //Failure. Check sets. + sprintf(buf, "sets/%s", filename.c_str()); + if (fileOK(buf, true)) return buf; - //Failure. Check raw faile. - sprintf(buf,"%s",filename.c_str()); - if(fileOK(buf,true)) - return buf; + //Failure. Check raw faile. + sprintf(buf, "%s", filename.c_str()); + if (fileOK(buf, true)) return buf; - //Complete abject failure. Probably a crash... - return graphdir; + //Complete abject failure. Probably a crash... + return graphdir; } - -string WResourceManager::avatarFile(const string filename){ +string WResourceManager::avatarFile(const string filename) +{ char buf[512]; - + //Check the profile folder. string profile = options[Options::ACTIVE_PROFILE].str; - if(profile != "" && profile != "Default"){ - sprintf(buf,"profiles/%s/%s",profile.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; - }else{ - sprintf(buf,"player/%s",filename.c_str()); - if(fileOK(buf,true)) - return buf; + if (profile != "" && profile != "Default") + { + sprintf(buf, "profiles/%s/%s", profile.c_str(), filename.c_str()); + if (fileOK(buf, true)) return buf; + } + else + { + sprintf(buf, "player/%s", filename.c_str()); + if (fileOK(buf, true)) return buf; } //Check the theme folder. string theme = options[Options::ACTIVE_THEME].str; - if(theme != "" && theme != "Default"){ - sprintf(buf,"themes/%s/%s",theme.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; + if (theme != "" && theme != "Default") + { + sprintf(buf, "themes/%s/%s", theme.c_str(), filename.c_str()); + if (fileOK(buf, true)) return buf; } -/* - //FIXME Put back when we're using modes. - //Failure. Check mode graphics - string mode = options[Options::ACTIVE_MODE].str; + /* + //FIXME Put back when we're using modes. + //Failure. Check mode graphics + string mode = options[Options::ACTIVE_MODE].str; - if(mode != "" && mode != "Default"){ - sprintf(buf,"modes/%s/graphics/%s",mode.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; - } -*/ + if(mode != "" && mode != "Default"){ + sprintf(buf,"modes/%s/graphics/%s",mode.c_str(),filename.c_str()); + if(fileOK(buf,true)) + return buf; + } + */ //Failure. Check Baka - sprintf(buf,"ai/baka/avatars/%s",filename.c_str()); - if(fileOK(buf,true)) - return buf; - - //Failure. Check graphics - sprintf(buf,"graphics/%s",filename.c_str()); - if(fileOK(buf,true)) - return buf; + sprintf(buf, "ai/baka/avatars/%s", filename.c_str()); + if (fileOK(buf, true)) return buf; - //Failure. Check raw faile. - sprintf(buf,"%s",filename.c_str()); - if(fileOK(buf,true)) - return buf; + //Failure. Check graphics + sprintf(buf, "graphics/%s", filename.c_str()); + if (fileOK(buf, true)) return buf; - //Complete abject failure. Probably a crash... - return ""; + //Failure. Check raw faile. + sprintf(buf, "%s", filename.c_str()); + if (fileOK(buf, true)) return buf; + + //Complete abject failure. Probably a crash... + return ""; } -string WResourceManager::cardFile(const string filename){ +string WResourceManager::cardFile(const string filename) +{ char buf[512]; string::size_type i = 0; string set; JFileSystem* fs = JFileSystem::GetInstance(); - + //Check the theme folder. string theme = options[Options::ACTIVE_THEME].str; - if(theme != "" && theme != "Default"){ - //Does this theme use custom cards? - if(bThemedCards){ - //Check zipped first. Discover set name. - for(i = 0;i < filename.size();i++){ - if(filename[i] == '\\' || filename[i] == '/') - break; - } - - if(i != filename.size()) - set = filename.substr(0,i); - - if(set.size()){ - char zipname[512]; - sprintf(zipname, JGE_GET_RES("themes/%s/sets/%s/%s.zip").c_str(), theme.c_str(), set.c_str(),set.c_str()); - if (fs->AttachZipFile(zipname)) - return filename.substr(i+1); + if (theme != "" && theme != "Default") + { + //Does this theme use custom cards? + if (bThemedCards) + { + //Check zipped first. Discover set name. + for (i = 0; i < filename.size(); i++) + { + if (filename[i] == '\\' || filename[i] == '/') break; } - sprintf(buf,"themes/%s/sets/%s",theme.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; //Themed, unzipped. - } - } - -//FIXME Put back when we're using modes. -/* - //Failure. Check mode - string mode = options[Options::ACTIVE_MODE].str; + if (i != filename.size()) set = filename.substr(0, i); - if(mode != "" && mode != "Default"){ - sprintf(buf,"modes/%s/sets/%s",mode.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; - } -*/ - //Failure. Assume it's in a zip file? - if(!set.size()){ //Didn't fill "set" string, so do it now. - for(i = 0;i < filename.size();i++){ - if(filename[i] == '\\' || filename[i] == '/') - break; - } + if (set.size()) + { + char zipname[512]; + sprintf(zipname, JGE_GET_RES("themes/%s/sets/%s/%s.zip").c_str(), theme.c_str(), set.c_str(), set.c_str()); + if (fs->AttachZipFile(zipname)) return filename.substr(i + 1); + } - if(i != filename.size()) - set = filename.substr(0,i); + sprintf(buf, "themes/%s/sets/%s", theme.c_str(), filename.c_str()); + if (fileOK(buf, true)) return buf; //Themed, unzipped. + } + } + + //FIXME Put back when we're using modes. + /* + //Failure. Check mode + string mode = options[Options::ACTIVE_MODE].str; + + if(mode != "" && mode != "Default"){ + sprintf(buf,"modes/%s/sets/%s",mode.c_str(),filename.c_str()); + if(fileOK(buf,true)) + return buf; } + */ + //Failure. Assume it's in a zip file? + if (!set.size()) + { //Didn't fill "set" string, so do it now. + for (i = 0; i < filename.size(); i++) + { + if (filename[i] == '\\' || filename[i] == '/') break; + } - if(set.size()){ + if (i != filename.size()) set = filename.substr(0, i); + } + + if (set.size()) + { char zipname[512]; - sprintf(zipname, JGE_GET_RES("sets/%s/%s.zip").c_str(), set.c_str(),set.c_str()); - if (fs->AttachZipFile(zipname)) - return filename.substr(i+1); - } + sprintf(zipname, JGE_GET_RES("sets/%s/%s.zip").c_str(), set.c_str(), set.c_str()); + if (fs->AttachZipFile(zipname)) return filename.substr(i + 1); + } - //Failure. Check for unzipped file in sets - char defdir[512]; - sprintf(defdir,"sets/%s",filename.c_str()); - if(fileOK(defdir,true)) - return defdir; + //Failure. Check for unzipped file in sets + char defdir[512]; + sprintf(defdir, "sets/%s", filename.c_str()); + if (fileOK(defdir, true)) return defdir; - //Complete failure. - return ""; + //Complete failure. + return ""; } -string WResourceManager::musicFile(const string filename){ +string WResourceManager::musicFile(const string filename) +{ char buf[512]; //Check the theme folder. string theme = options[Options::ACTIVE_THEME].str; - if(theme != "" && theme != "Default"){ - sprintf(buf,"themes/%s/sound/%s",theme.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; + if (theme != "" && theme != "Default") + { + sprintf(buf, "themes/%s/sound/%s", theme.c_str(), filename.c_str()); + if (fileOK(buf, true)) return buf; } /* - //FIXME Put back when we're using modes. - //Failure. Check mode - string mode = options[Options::ACTIVE_MODE].str; + //FIXME Put back when we're using modes. + //Failure. Check mode + string mode = options[Options::ACTIVE_MODE].str; - if(mode != "" && mode != "Default"){ - sprintf(buf,"modes/%s/sound/%s",mode.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; - }*/ - - //Failure. Check sound - char defdir[512]; - sprintf(defdir,"sound/%s",filename.c_str()); - if(fileOK(defdir,true)) - return defdir; + if(mode != "" && mode != "Default"){ + sprintf(buf,"modes/%s/sound/%s",mode.c_str(),filename.c_str()); + if(fileOK(buf,true)) + return buf; + }*/ - //Failure. Check raw faile. - sprintf(defdir,"%s",filename.c_str()); - if(fileOK(defdir,true)) - return defdir; + //Failure. Check sound + char defdir[512]; + sprintf(defdir, "sound/%s", filename.c_str()); + if (fileOK(defdir, true)) return defdir; + //Failure. Check raw faile. + sprintf(defdir, "%s", filename.c_str()); + if (fileOK(defdir, true)) return defdir; - //Complete abject failure. Probably a crash... - return ""; + //Complete abject failure. Probably a crash... + return ""; } -string WResourceManager::sfxFile(const string filename){ +string WResourceManager::sfxFile(const string filename) +{ char buf[512]; //Check the theme folder. string theme = options[Options::ACTIVE_THEME].str; - if(theme != "" && theme != "Default"){ - sprintf(buf,"themes/%s/sound/sfx/%s",theme.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; + if (theme != "" && theme != "Default") + { + sprintf(buf, "themes/%s/sound/sfx/%s", theme.c_str(), filename.c_str()); + if (fileOK(buf, true)) return buf; } -/* - //FIXME: Put back when we're using modes. - //Failure. Check mode - string mode = options[Options::ACTIVE_MODE].str; - if(mode != "" && mode != "Default"){ - sprintf(buf,"modes/%s/sound/sfx/%s",mode.c_str(),filename.c_str()); - if(fileOK(buf,true)) - return buf; - } -*/ - //Failure. Check sound - char defdir[512]; - sprintf(defdir,"sound/sfx/%s",filename.c_str()); - if(fileOK(defdir,true)) - return defdir; - - //Complete abject failure. Probably a crash... - return ""; + /* + //FIXME: Put back when we're using modes. + //Failure. Check mode + string mode = options[Options::ACTIVE_MODE].str; + if(mode != "" && mode != "Default"){ + sprintf(buf,"modes/%s/sound/sfx/%s",mode.c_str(),filename.c_str()); + if(fileOK(buf,true)) + return buf; + } + */ + //Failure. Check sound + char defdir[512]; + sprintf(defdir, "sound/sfx/%s", filename.c_str()); + if (fileOK(defdir, true)) return defdir; + + //Complete abject failure. Probably a crash... + return ""; } -int WResourceManager::dirOK(string dirname){ -char fname[512]; +int WResourceManager::dirOK(string dirname) +{ + char fname[512]; #if defined (WIN32) - sprintf(fname,JGE_GET_RES(dirname).c_str()); + sprintf(fname,JGE_GET_RES(dirname).c_str()); - struct _stat statBuffer; - return (_stat(fname, &statBuffer) >= 0 && // make sure it exists - statBuffer.st_mode & S_IFDIR); // and it's not a file + struct _stat statBuffer; + return (_stat(fname, &statBuffer) >= 0 && // make sure it exists + statBuffer.st_mode & S_IFDIR); // and it's not a file #else - sprintf(fname,JGE_GET_RES(dirname).c_str()); - struct stat st; - if(stat(fname,&st) == 0) - return 1; + sprintf(fname, JGE_GET_RES(dirname).c_str()); + struct stat st; + if (stat(fname, &st) == 0) return 1; #endif - return 0; + return 0; } +int WResourceManager::fileOK(string filename, bool relative) +{ + std::ifstream * fp = NULL; + if (relative) + { + fp = NEW std::ifstream(JGE_GET_RES(filename).c_str()); + } + else + fp = NEW std::ifstream(filename.c_str()); -int WResourceManager::fileOK(string filename, bool relative){ - std::ifstream * fp = NULL; - if(relative){ - fp = NEW std::ifstream(JGE_GET_RES(filename).c_str()); - } - else - fp = NEW std::ifstream(filename.c_str()); + int result = 0; + if (fp) + { + if (*fp) result = 1; + fp->close(); + delete fp; + } - int result = 0; - if(fp){ - if(*fp) result = 1; - fp->close(); - delete fp; - } - - return result; + return result; } void WResourceManager::InitFonts(const std::string& inLang) { - unsigned int idOffset = 0; + unsigned int idOffset = 0; - if (inLang.compare("cn") == 0) - { - mFontFileExtension = kExtension_gbk; - LoadWFont("simon", 12, Fonts::MAIN_FONT); - LoadWFont("f3", 16, Fonts::MENU_FONT); - LoadWFont("magic", 16, Fonts::MAGIC_FONT); - LoadWFont("smallface", 12, Fonts::SMALLFACE_FONT); + if (inLang.compare("cn") == 0) + { + mFontFileExtension = kExtension_gbk; + LoadWFont("simon", 12, Fonts::MAIN_FONT); + LoadWFont("f3", 16, Fonts::MENU_FONT); + LoadWFont("magic", 16, Fonts::MAGIC_FONT); + LoadWFont("smallface", 12, Fonts::SMALLFACE_FONT); - idOffset = Fonts::kSingleByteFontOffset; - } + idOffset = Fonts::kSingleByteFontOffset; + } - if (inLang.compare("jp") == 0) - { - mFontFileExtension = kExtension_font; - LoadWFont("simon", 12, Fonts::MAIN_FONT); - LoadWFont("f3", 16, Fonts::MENU_FONT); - LoadWFont("magic", 16, Fonts::MAGIC_FONT); - LoadWFont("smallface", 12, Fonts::SMALLFACE_FONT); + if (inLang.compare("jp") == 0) + { + mFontFileExtension = kExtension_font; + LoadWFont("simon", 12, Fonts::MAIN_FONT); + LoadWFont("f3", 16, Fonts::MENU_FONT); + LoadWFont("magic", 16, Fonts::MAGIC_FONT); + LoadWFont("smallface", 12, Fonts::SMALLFACE_FONT); - idOffset = Fonts::kSingleByteFontOffset; - } + idOffset = Fonts::kSingleByteFontOffset; + } - mFontFileExtension = kExtension_png; - LoadWFont("simon", 11, Fonts::MAIN_FONT + idOffset); - GetWFont(Fonts::MAIN_FONT)->SetTracking(-1); - LoadWFont("f3", 16, Fonts::MENU_FONT + idOffset); - LoadWFont("magic", 16, Fonts::MAGIC_FONT + idOffset); - LoadWFont("smallface", 7, Fonts::SMALLFACE_FONT + idOffset); + mFontFileExtension = kExtension_png; + LoadWFont("simon", 11, Fonts::MAIN_FONT + idOffset); + GetWFont(Fonts::MAIN_FONT)->SetTracking(-1); + LoadWFont("f3", 16, Fonts::MENU_FONT + idOffset); + LoadWFont("magic", 16, Fonts::MAGIC_FONT + idOffset); + LoadWFont("smallface", 7, Fonts::SMALLFACE_FONT + idOffset); } -int WResourceManager::ReloadWFonts(){ - RemoveWFonts(); +int WResourceManager::ReloadWFonts() +{ + RemoveWFonts(); - string lang = options[Options::LANG].str; - std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower); + string lang = options[Options::LANG].str; + std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower); - InitFonts(lang); + InitFonts(lang); - return 1; + return 1; } WFont* WResourceManager::LoadWFont(const string& inFontname, int inFontHeight, int inFontID) { - WFont* font = GetWFont(inFontID); - if (font) - { + WFont* font = GetWFont(inFontID); + if (font) + { + return font; + } + + string mFontName = inFontname + mFontFileExtension; + string path = graphicsFile(mFontName); + + if (mFontFileExtension == kExtension_font) + font = NEW WUFont(inFontID, path.c_str(), inFontHeight, true); + else if (mFontFileExtension == kExtension_gbk) + font = NEW WGBKFont(inFontID, path.c_str(), inFontHeight, true); + else + font = NEW WLBFont(inFontID, path.c_str(), inFontHeight, true); + mWFontMap[inFontID] = font; + return font; - } - - string mFontName = inFontname + mFontFileExtension; - string path = graphicsFile(mFontName); - - if (mFontFileExtension == kExtension_font) - font = NEW WUFont(inFontID, path.c_str(), inFontHeight, true); - else if (mFontFileExtension == kExtension_gbk) - font = NEW WGBKFont(inFontID, path.c_str(), inFontHeight, true); - else - font = NEW WLBFont(inFontID, path.c_str(), inFontHeight, true); - mWFontMap[inFontID] = font; - - return font; } WFont* WResourceManager::GetWFont(int id) { - WFont* font = NULL; - FontMap::iterator iter = mWFontMap.find(id); - if (iter != mWFontMap.end()) - { - font = iter->second; - } - return font; + WFont* font = NULL; + FontMap::iterator iter = mWFontMap.find(id); + if (iter != mWFontMap.end()) + { + font = iter->second; + } + return font; } -void WResourceManager::RemoveWFonts() { - for (FontMap::iterator font = mWFontMap.begin(); font != mWFontMap.end(); ++font) - { - delete font->second; - } - mWFontMap.clear(); +void WResourceManager::RemoveWFonts() +{ + for (FontMap::iterator font = mWFontMap.begin(); font != mWFontMap.end(); ++font) + { + delete font->second; + } + mWFontMap.clear(); } -void WResourceManager::ResetCacheLimits(){ +void WResourceManager::ResetCacheLimits() +{ #if defined WIN32 || defined LINUX - #ifdef FORCE_LOW_CACHE_MEMORY - textureWCache.Resize(kConstrainedCacheLimit, MAX_CACHE_OBJECTS); - #else +#ifdef FORCE_LOW_CACHE_MEMORY + textureWCache.Resize(kConstrainedCacheLimit, MAX_CACHE_OBJECTS); +#else textureWCache.Resize(HUGE_CACHE_LIMIT,MAX_CACHE_OBJECTS); - #endif +#endif #else unsigned int ram = ramAvailable(); unsigned int myNewSize = ram - OPERATIONAL_SIZE + textureWCache.totalSize; - if (myNewSize < TEXTURES_CACHE_MINSIZE){ - fprintf(stderr, "Error, Not enough RAM for Cache: %i - total Ram: %i\n", myNewSize, ram); + if (myNewSize < TEXTURES_CACHE_MINSIZE) + { + fprintf(stderr, "Error, Not enough RAM for Cache: %i - total Ram: %i\n", myNewSize, ram); } - textureWCache.Resize(myNewSize,MAX_CACHE_OBJECTS); + textureWCache.Resize(myNewSize, MAX_CACHE_OBJECTS); #endif return; } -JMusic * WResourceManager::ssLoadMusic(const char *fileName){ - string file = musicFile(fileName); - if (!file.size()) return NULL; - return JSoundSystem::GetInstance()->LoadMusic(file.c_str()); +JMusic * WResourceManager::ssLoadMusic(const char *fileName) +{ + string file = musicFile(fileName); + if (!file.size()) return NULL; + return JSoundSystem::GetInstance()->LoadMusic(file.c_str()); } +void WResourceManager::Refresh() +{ + //Really easy cache relinking. + ReloadWFonts(); + sampleWCache.Refresh(); + textureWCache.Refresh(); + psiWCache.Refresh(); -void WResourceManager::Refresh(){ - //Really easy cache relinking. - ReloadWFonts(); - sampleWCache.Refresh(); - textureWCache.Refresh(); - psiWCache.Refresh(); + map::iterator it; + vector::iterator q; - map::iterator it; - vector::iterator q; + //Now do some juggling so that managed resources also reload. + map oldTextures; + map newNames; + map::iterator oldIt; + vector::iterator jtex; + map::iterator mapping; + JTexture * newtex; + JTexture * oldtex = NULL; - //Now do some juggling so that managed resources also reload. - map oldTextures; - map newNames; - map::iterator oldIt; - vector::iterator jtex; - map::iterator mapping; - JTexture * newtex; - JTexture * oldtex = NULL; + //Store old mappings. + for (mapping = mTextureMap.begin(); mapping != mTextureMap.end(); mapping++) + { + if (oldTextures[mTextureList[mapping->second]] == NULL) + { + newtex = JRenderer::GetInstance()->LoadTexture(graphicsFile(mapping->first).c_str(), 0, TEXTURE_FORMAT); + oldtex = mTextureList[mapping->second]; + if (!newtex) + newNames[oldtex] = mapping->first; + else + { + newNames[newtex] = mapping->first; + } - //Store old mappings. - for(mapping = mTextureMap.begin();mapping != mTextureMap.end();mapping++){ - if(oldTextures[mTextureList[mapping->second]] == NULL){ - newtex = JRenderer::GetInstance()->LoadTexture(graphicsFile(mapping->first).c_str(),0,TEXTURE_FORMAT); - oldtex = mTextureList[mapping->second]; - if(!newtex) - newNames[oldtex] = mapping->first; - else{ - newNames[newtex] = mapping->first; - } - - oldTextures[oldtex] = newtex; + oldTextures[oldtex] = newtex; + } } - } - //Remap quads. - for(q = mQuadList.begin();q!=mQuadList.end();q++){ - newtex = oldTextures[(*q)->mTex]; - if(newtex != NULL) - (*q)->mTex = newtex; - } + //Remap quads. + for (q = mQuadList.begin(); q != mQuadList.end(); q++) + { + newtex = oldTextures[(*q)->mTex]; + if (newtex != NULL) (*q)->mTex = newtex; + } - //Rebuild mTextureList and mapping. - mTextureList.clear(); - mTextureMap.clear(); - int x = 0; - for(oldIt = oldTextures.begin();oldIt!=oldTextures.end();oldIt++){ - - if(oldIt->second) - newtex = oldIt->second; - else - newtex = oldIt->first; - - mTextureList.push_back(newtex); - mTextureMap[newNames[newtex]] = x; - x++; - } - - //Rebuild mapping. - for(mapping = mTextureMap.begin();mapping != mTextureMap.end();mapping++){ - if(oldTextures[mTextureList[mapping->second]] == NULL) - continue; - } + //Rebuild mTextureList and mapping. + mTextureList.clear(); + mTextureMap.clear(); + int x = 0; + for (oldIt = oldTextures.begin(); oldIt != oldTextures.end(); oldIt++) + { - //Delete unused textures. - for(oldIt = oldTextures.begin();oldIt!=oldTextures.end();oldIt++){ - if(!oldIt->second || !oldIt->first ) - continue; + if (oldIt->second) + newtex = oldIt->second; + else + newtex = oldIt->first; - SAFE_DELETE(oldtex); - } + mTextureList.push_back(newtex); + mTextureMap[newNames[newtex]] = x; + x++; + } - //Check for card images in theme. - bThemedCards = false; - if(!options[Options::ACTIVE_THEME].isDefault()){ - char buf[512]; - sprintf(buf,"themes/%s/sets",options[Options::ACTIVE_THEME].str.c_str()); - - if(dirOK(buf)) - bThemedCards = true; - } + //Rebuild mapping. + for (mapping = mTextureMap.begin(); mapping != mTextureMap.end(); mapping++) + { + if (oldTextures[mTextureList[mapping->second]] == NULL) continue; + } + + //Delete unused textures. + for (oldIt = oldTextures.begin(); oldIt != oldTextures.end(); oldIt++) + { + if (!oldIt->second || !oldIt->first) continue; + + SAFE_DELETE(oldtex); + } + + //Check for card images in theme. + bThemedCards = false; + if (!options[Options::ACTIVE_THEME].isDefault()) + { + char buf[512]; + sprintf(buf, "themes/%s/sets", options[Options::ACTIVE_THEME].str.c_str()); + + if (dirOK(buf)) bThemedCards = true; + } } //WCache -template -bool WCache::RemoveOldest(){ - typename map ::iterator oldest = cache.end(); +template +bool WCache::RemoveOldest() +{ + typename map::iterator oldest = cache.end(); - for(typename map::iterator it = cache.begin();it!=cache.end();it++){ - if(it->second && !it->second->isLocked() - && (oldest == cache.end() || it->second->lastTime < oldest->second->lastTime)) - oldest = it; - } + for (typename map::iterator it = cache.begin(); it != cache.end(); it++) + { + if (it->second && !it->second->isLocked() && (oldest == cache.end() || it->second->lastTime < oldest->second->lastTime)) oldest + = it; + } - if(oldest != cache.end() && oldest->second && !oldest->second->isLocked()){ - Delete(oldest->second); - cache.erase(oldest); - return true; - } + if (oldest != cache.end() && oldest->second && !oldest->second->isLocked()) + { + Delete(oldest->second); + cache.erase(oldest); + return true; + } - return false; + return false; } -template -void WCache::ClearUnlocked(){ - typename map::iterator it, next; +template +void WCache::ClearUnlocked() +{ + typename map::iterator it, next; - for(it = cache.begin(); it != cache.end();it=next){ - next = it; - next++; + for (it = cache.begin(); it != cache.end(); it = next) + { + next = it; + next++; - if(it->second && !it->second->isLocked()){ - Delete(it->second); - cache.erase(it); - } - else if(!it->second){ - cache.erase(it); - } - } + if (it->second && !it->second->isLocked()) + { + Delete(it->second); + cache.erase(it); + } + else if (!it->second) + { + cache.erase(it); + } + } } -template -void WCache::Resize(unsigned long size, int items){ +template +void WCache::Resize(unsigned long size, int items) +{ maxCacheSize = size; - if(items > MAX_CACHE_OBJECTS || items < 1) - maxCached = MAX_CACHE_OBJECTS; - else - maxCached = items; -} - - -template -cacheItem* WCache::AttemptNew(string filename, int submode){ - if(submode & CACHE_EXISTING){ //Should never get this far. - mError = CACHE_ERROR_NOT_CACHED; - return NULL; - } - - cacheItem* item = NEW cacheItem; - if(!item) { - mError = CACHE_ERROR_BAD_ALLOC; - return NULL; - } - - mError = CACHE_ERROR_NONE; - - if(!item->Attempt(filename,submode,mError) || !item->isGood()) { - //No such file. Fail - if(mError == CACHE_ERROR_404){ - SAFE_DELETE(item); - return NULL; - } - //Probably not enough memory: cleanup and try again - Cleanup(); - mError = CACHE_ERROR_NONE; - if(!item->Attempt(filename,submode,mError) || !item->isGood()) { - SAFE_DELETE(item); - mError = CACHE_ERROR_BAD; - return NULL; - } - } - - //Success! Enforce cache limits, then return. - mError = CACHE_ERROR_NONE; - item->lock(); - Cleanup(); - item->unlock(); - return item; -} - -template -cacheItem * WCache::Retrieve(int id, string filename, int style, int submode){ - //Check cache. - cacheItem * tc = NULL; - mError = CACHE_ERROR_NONE; //Reset error status. - - if(style == RETRIEVE_EXISTING || style == RETRIEVE_RESOURCE) - tc = Get(id,filename,style,submode|CACHE_EXISTING); - else - tc = Get(id, filename,style,submode); - - //Retrieve resource only works on permanent items. - if(style == RETRIEVE_RESOURCE && tc && !tc->isPermanent()){ - mError = CACHE_ERROR_NOT_MANAGED; - return NULL; - } - - //Perform lock or unlock on entry. - if(tc){ - switch(style){ - case RETRIEVE_LOCK: tc->lock(); break; - case RETRIEVE_UNLOCK: tc->unlock(); break; - case RETRIEVE_MANAGE: - if (!tc->isPermanent()) { - //Unlink the managed resource from the cache. - UnlinkCache(tc); - - //Post it in managed resources. - managed[makeID(id,filename,submode)] = tc; - tc->deadbolt(); - } - break; - } - } - - //Resource exists! - if(tc){ - if(tc->isGood()){ - tc->hit(); - return tc; //Everything fine. - } - //Something went wrong. - RemoveItem(tc); - mError = CACHE_ERROR_BAD; - } - - //Record managed failure. Cache failure is recorded in Get(). - if((style == RETRIEVE_MANAGE || style == RETRIEVE_RESOURCE) && mError == CACHE_ERROR_404) - managed[makeID(id,filename,submode)] = NULL; - - return NULL; -} -template -int WCache::makeID(int id, string filename, int submode){ - int mId = id; - if (!mId) { - mId = ids[filename]; - if (!mId){ - mId = idCounter++; - ids[filename] = mId; - } - } - - //To differentiate between cached thumbnails and the real thing. - if(submode & TEXTURE_SUB_THUMB){ - if (mId < 0) - mId-=THUMBNAILS_OFFSET; + if (items > MAX_CACHE_OBJECTS || items < 1) + maxCached = MAX_CACHE_OBJECTS; else - mId+=THUMBNAILS_OFFSET; - } - return mId; + maxCached = items; } -template -cacheItem * WCache::Get(int id, string filename, int style, int submode){ - typename map::iterator it; - int lookup = makeID(id,filename, submode); +template +cacheItem* WCache::AttemptNew(string filename, int submode) +{ + if (submode & CACHE_EXISTING) + { //Should never get this far. + mError = CACHE_ERROR_NOT_CACHED; + return NULL; + } - //Check for managed resources first. Always - it = managed.find(lookup); + cacheItem* item = NEW cacheItem; + if (!item) + { + mError = CACHE_ERROR_BAD_ALLOC; + return NULL; + } - //Something is managed. - if(it != managed.end()) { - return it->second; //A hit. - } + mError = CACHE_ERROR_NONE; + + if (!item->Attempt(filename, submode, mError) || !item->isGood()) + { + //No such file. Fail + if (mError == CACHE_ERROR_404) + { + SAFE_DELETE(item); + return NULL; + } + //Probably not enough memory: cleanup and try again + Cleanup(); + mError = CACHE_ERROR_NONE; + if (!item->Attempt(filename, submode, mError) || !item->isGood()) + { + SAFE_DELETE(item); + mError = CACHE_ERROR_BAD; + return NULL; + } + } + + //Success! Enforce cache limits, then return. + mError = CACHE_ERROR_NONE; + item->lock(); + Cleanup(); + item->unlock(); + return item; +} + +template +cacheItem * WCache::Retrieve(int id, string filename, int style, int submode) +{ + //Check cache. + cacheItem * tc = NULL; + mError = CACHE_ERROR_NONE; //Reset error status. + + if (style == RETRIEVE_EXISTING || style == RETRIEVE_RESOURCE) + tc = Get(id, filename, style, submode | CACHE_EXISTING); + else + tc = Get(id, filename, style, submode); + + //Retrieve resource only works on permanent items. + if (style == RETRIEVE_RESOURCE && tc && !tc->isPermanent()) + { + mError = CACHE_ERROR_NOT_MANAGED; + return NULL; + } + + //Perform lock or unlock on entry. + if (tc) + { + switch (style) + { + case RETRIEVE_LOCK: + tc->lock(); + break; + case RETRIEVE_UNLOCK: + tc->unlock(); + break; + case RETRIEVE_MANAGE: + if (!tc->isPermanent()) + { + //Unlink the managed resource from the cache. + UnlinkCache(tc); + + //Post it in managed resources. + managed[makeID(id, filename, submode)] = tc; + tc->deadbolt(); + } + break; + } + } + + //Resource exists! + if (tc) + { + if (tc->isGood()) + { + tc->hit(); + return tc; //Everything fine. + } + //Something went wrong. + RemoveItem(tc); + mError = CACHE_ERROR_BAD; + } + + //Record managed failure. Cache failure is recorded in Get(). + if ((style == RETRIEVE_MANAGE || style == RETRIEVE_RESOURCE) && mError == CACHE_ERROR_404) managed[makeID(id, filename, submode)] + = NULL; - //Failed to find managed resource and won't create one. Record a miss. - if(style == RETRIEVE_RESOURCE){ - managed[lookup] = NULL; return NULL; - } - - //Not managed, so look in cache. - if(style != RETRIEVE_MANAGE){ - it = cache.find(lookup); - //Well, we've found something... - if(it != cache.end()){ - if(!it->second) - mError = CACHE_ERROR_404; - return it->second; //A hit, or maybe a miss. +} +template +int WCache::makeID(int id, string filename, int submode) +{ + int mId = id; + if (!mId) + { + mId = ids[filename]; + if (!mId) + { + mId = idCounter++; + ids[filename] = mId; + } } - } - //Didn't exist in cache. - if(submode & CACHE_EXISTING ){ - mError = CACHE_ERROR_NOT_CACHED; - return NULL; - } - - //Space in cache, make new texture - cacheItem * item = AttemptNew(filename,submode); - - if(style == RETRIEVE_MANAGE){ - if(mError == CACHE_ERROR_404 || item) - managed[lookup] = item; //Record a hit or miss. - if(item){ - item->deadbolt(); //Make permanent. + //To differentiate between cached thumbnails and the real thing. + if (submode & TEXTURE_SUB_THUMB) + { + if (mId < 0) + mId -= THUMBNAILS_OFFSET; + else + mId += THUMBNAILS_OFFSET; } - } - else { - if(mError == CACHE_ERROR_404 || item) - cache[lookup] = item; - } - - if (!item) return NULL; //Failure - - //Succeeded in making a new item. - unsigned long isize = item->size(); - totalSize += isize; - - mError = CACHE_ERROR_NONE; - if(style != RETRIEVE_MANAGE){ - cacheItems++; - cacheSize += isize; - } - - return item; + return mId; } -template -void WCache::Refresh(){ - typename map::iterator it; - ClearUnlocked(); +template +cacheItem * WCache::Get(int id, string filename, int style, int submode) +{ + typename map::iterator it; + int lookup = makeID(id, filename, submode); - for(it = cache.begin();it!=cache.end();it++){ - if(it->second){ - it->second->Refresh(); + //Check for managed resources first. Always + it = managed.find(lookup); + + //Something is managed. + if (it != managed.end()) + { + return it->second; //A hit. } - } - for(it = managed.begin();it!=managed.end();it++){ - if(it->second){ - it->second->Refresh(); + + //Failed to find managed resource and won't create one. Record a miss. + if (style == RETRIEVE_RESOURCE) + { + managed[lookup] = NULL; + return NULL; } - } + + //Not managed, so look in cache. + if (style != RETRIEVE_MANAGE) + { + it = cache.find(lookup); + //Well, we've found something... + if (it != cache.end()) + { + if (!it->second) mError = CACHE_ERROR_404; + return it->second; //A hit, or maybe a miss. + } + } + + //Didn't exist in cache. + if (submode & CACHE_EXISTING) + { + mError = CACHE_ERROR_NOT_CACHED; + return NULL; + } + + //Space in cache, make new texture + cacheItem * item = AttemptNew(filename, submode); + + if (style == RETRIEVE_MANAGE) + { + if (mError == CACHE_ERROR_404 || item) managed[lookup] = item; //Record a hit or miss. + if (item) + { + item->deadbolt(); //Make permanent. + } + } + else + { + if (mError == CACHE_ERROR_404 || item) cache[lookup] = item; + } + + if (!item) return NULL; //Failure + + //Succeeded in making a new item. + unsigned long isize = item->size(); + totalSize += isize; + + mError = CACHE_ERROR_NONE; + if (style != RETRIEVE_MANAGE) + { + cacheItems++; + cacheSize += isize; + } + + return item; } -template -WCache::WCache(){ - cacheSize = 0; - totalSize = 0; +template +void WCache::Refresh() +{ + typename map::iterator it; + ClearUnlocked(); - maxCacheSize = TEXTURES_CACHE_MINSIZE; - - maxCached = MAX_CACHE_OBJECTS; - cacheItems = 0; - mError = CACHE_ERROR_NONE; + for (it = cache.begin(); it != cache.end(); it++) + { + if (it->second) + { + it->second->Refresh(); + } + } + for (it = managed.begin(); it != managed.end(); it++) + { + if (it->second) + { + it->second->Refresh(); + } + } } -template -WCache::~WCache(){ - typename map::iterator it; +template +WCache::WCache() +{ + cacheSize = 0; + totalSize = 0; - //Delete from cache & managed - for(it=cache.begin();it!=cache.end();it++){ - SAFE_DELETE(it->second); - } + maxCacheSize = TEXTURES_CACHE_MINSIZE; - for(it=managed.begin();it!=managed.end();it++){ - SAFE_DELETE(it->second); - } + maxCached = MAX_CACHE_OBJECTS; + cacheItems = 0; + mError = CACHE_ERROR_NONE; } +template +WCache::~WCache() +{ + typename map::iterator it; -template -bool WCache::Cleanup(){ - while(cacheItems < cache.size() && cache.size() - cacheItems > MAX_CACHE_MISSES){ - RemoveMiss(); - } + //Delete from cache & managed + for (it = cache.begin(); it != cache.end(); it++) + { + SAFE_DELETE(it->second); + } - while (cacheItems > MAX_CACHE_OBJECTS || cacheItems > maxCached || cacheSize > maxCacheSize + for (it = managed.begin(); it != managed.end(); it++) + { + SAFE_DELETE(it->second); + } +} + +template +bool WCache::Cleanup() +{ + while (cacheItems < cache.size() && cache.size() - cacheItems > MAX_CACHE_MISSES) + { + RemoveMiss(); + } + + while (cacheItems > MAX_CACHE_OBJECTS || cacheItems > maxCached || cacheSize > maxCacheSize #if defined WIN32 || defined LINUX #else - || ramAvailableLineareMax() < MIN_LINEAR_RAM + || ramAvailableLineareMax() < MIN_LINEAR_RAM #endif - ){ - if (!RemoveOldest()) { - return false; - } - } - return true; -} - -bool WCacheSort::operator()(const WResource * l, const WResource * r){ - if(!l || !r) - return false; - return (l->lastTime < r->lastTime); -} - -template -unsigned int WCache::Flatten(){ - vector items; - unsigned int oldest = 0; - unsigned int lastSet = 0; - - if(!cache.size()) - return 0; - - for (typename map::iterator it = cache.begin(); it != cache.end(); ++it){ - if(!it->second) continue; - items.push_back(it->second); - } - - sort(items.begin(), items.end(), WCacheSort()); - - for (typename vector::iterator it = items.begin(); it != items.end(); ++it){ - assert((*it) && (*it)->lastTime > lastSet); - lastSet = (*it)->lastTime; - (*it)->lastTime = ++oldest; - } - - return oldest + 1; -} - -template -bool WCache::RemoveMiss(int id){ - typename map::iterator it = cache.end(); - - for(it = cache.begin();it!=cache.end();it++){ - if((id == 0 || it->first == id) && it->second == NULL) - break; - } - - if(it != cache.end()) - { - cache.erase(it); - return true; - } - - return false; -} - -template -bool WCache::RemoveItem(cacheItem * item, bool force){ - typename map::iterator it; - - if(item == NULL) - return false; //Use RemoveMiss to remove cache misses, not this. - - for(it = cache.begin();it!=cache.end();it++){ - if(it->second == item) - break; - } - if(it != cache.end() && it->second && (force || !it->second->isLocked())){ - Delete(it->second); - cache.erase(it); + ) + { + if (!RemoveOldest()) + { + return false; + } + } return true; - } - - return false; } -template -bool WCache::UnlinkCache(cacheItem * item){ - typename map::iterator it = cache.end(); +bool WCacheSort::operator()(const WResource * l, const WResource * r) +{ + if (!l || !r) return false; + return (l->lastTime < r->lastTime); +} - if(item == NULL) - return false; //Use RemoveMiss to remove cache misses, not this. +template +unsigned int WCache::Flatten() +{ + vector items; + unsigned int oldest = 0; + unsigned int lastSet = 0; + + if (!cache.size()) return 0; + + for (typename map::iterator it = cache.begin(); it != cache.end(); ++it) + { + if (!it->second) continue; + items.push_back(it->second); + } + + sort(items.begin(), items.end(), WCacheSort()); + + for (typename vector::iterator it = items.begin(); it != items.end(); ++it) + { + assert((*it) && (*it)->lastTime > lastSet); + lastSet = (*it)->lastTime; + (*it)->lastTime = ++oldest; + } + + return oldest + 1; +} + +template +bool WCache::RemoveMiss(int id) +{ + typename map::iterator it = cache.end(); + + for (it = cache.begin(); it != cache.end(); it++) + { + if ((id == 0 || it->first == id) && it->second == NULL) break; + } + + if (it != cache.end()) + { + cache.erase(it); + return true; + } + + return false; +} + +template +bool WCache::RemoveItem(cacheItem * item, bool force) +{ + typename map::iterator it; + + if (item == NULL) return false; //Use RemoveMiss to remove cache misses, not this. + + for (it = cache.begin(); it != cache.end(); it++) + { + if (it->second == item) break; + } + if (it != cache.end() && it->second && (force || !it->second->isLocked())) + { + Delete(it->second); + cache.erase(it); + return true; + } + + return false; +} + +template +bool WCache::UnlinkCache(cacheItem * item) +{ + typename map::iterator it = cache.end(); + + if (item == NULL) return false; //Use RemoveMiss to remove cache misses, not this. + + for (it = cache.begin(); it != cache.end(); it++) + { + if (it->second == item) break; + } + if (it != cache.end() && it->second) + { + it->second = NULL; + unsigned long isize = item->size(); + + cacheSize -= isize; + cacheItems--; + cache.erase(it); + return true; + } + + return false; +} + +template +bool WCache::Delete(cacheItem * item) +{ + if (!item) return false; - for(it = cache.begin();it!=cache.end();it++){ - if(it->second == item) - break; - } - if(it != cache.end() && it->second){ - it->second = NULL; unsigned long isize = item->size(); - - cacheSize -= isize; - cacheItems--; - cache.erase(it); - return true; - } - - return false; -} - -template -bool WCache::Delete(cacheItem * item){ - if(!item) - return false; - - unsigned long isize = item->size(); - totalSize -= isize; - cacheSize -= isize; + totalSize -= isize; + cacheSize -= isize; #ifdef DEBUG_CACHE - if(cacheItems == 0) + if(cacheItems == 0) DebugTrace("cacheItems out of sync."); #endif - cacheItems--; + cacheItems--; - SAFE_DELETE(item); - return true; + SAFE_DELETE(item); + return true; } -template -bool WCache::Release(cacheActual* actual){ - if(!actual) - return false; +template +bool WCache::Release(cacheActual* actual) +{ + if (!actual) return false; - typename map::iterator it; - for(it=cache.begin();it!=cache.end();it++){ - if(it->second && it->second->compare(actual)) - break; - } - - if(it == cache.end()) - return false; //Not here, can't release. + typename map::iterator it; + for (it = cache.begin(); it != cache.end(); it++) + { + if (it->second && it->second->compare(actual)) break; + } - if(it->second){ - it->second->unlock(); //Release one lock. - if(it->second->isLocked()) - return true; //Still locked, won't delete, not technically a failure. - } + if (it == cache.end()) return false; //Not here, can't release. - //Released! - Delete(it->second); - cache.erase(it); - return true; + if (it->second) + { + it->second->unlock(); //Release one lock. + if (it->second->isLocked()) return true; //Still locked, won't delete, not technically a failure. + } + + //Released! + Delete(it->second); + cache.erase(it); + return true; } diff --git a/projects/mtg/src/testfeatures.c b/projects/mtg/src/testfeatures.c index e7d8f7414..4ef62d83b 100644 --- a/projects/mtg/src/testfeatures.c +++ b/projects/mtg/src/testfeatures.c @@ -1,4 +1,8 @@ -extern "C" { -void FSOUND_Close(); +extern "C" +{ + void FSOUND_Close(); +} +int main() +{ + FSOUND_Close(); } -int main() { FSOUND_Close(); } diff --git a/projects/mtg/src/utils.cpp b/projects/mtg/src/utils.cpp index 628ee744a..c7ae978fd 100644 --- a/projects/mtg/src/utils.cpp +++ b/projects/mtg/src/utils.cpp @@ -5,220 +5,225 @@ using std::vector; int randValuesCursor = -1; -vectorrandValues; +vector randValues; -int loadRandValues(string s){ - randValues.clear(); - randValuesCursor = -1; - while (s.size()){ - unsigned int value; - size_t limiter = s.find(","); - if (limiter != string::npos){ - value = atoi(s.substr(0,limiter).c_str()); - s = s.substr(limiter+1); - }else{ - value = atoi(s.c_str()); - s = ""; - } - if (value) randValues.push_back(value); +int loadRandValues(string s) +{ + randValues.clear(); + randValuesCursor = -1; + while (s.size()) + { + unsigned int value; + size_t limiter = s.find(","); + if (limiter != string::npos) + { + value = atoi(s.substr(0, limiter).c_str()); + s = s.substr(limiter + 1); + } + else + { + value = atoi(s.c_str()); + s = ""; + } + if (value) randValues.push_back(value); } if (randValues.size()) randValuesCursor = 0; return 1; } -int WRand(){ - if (randValuesCursor == -1) return rand(); - int result = randValues[randValuesCursor]; - randValuesCursor++; - if ((size_t)randValuesCursor >= randValues.size()) randValuesCursor = 0; - return result; +int WRand() +{ + if (randValuesCursor == -1) return rand(); + int result = randValues[randValuesCursor]; + randValuesCursor++; + if ((size_t) randValuesCursor >= randValues.size()) randValuesCursor = 0; + return result; } -int filesize(const char * filename){ - int file_size = 0; +int filesize(const char * filename) +{ + int file_size = 0; #if defined (WIN32) || defined (LINUX) - FILE * file = fopen(filename, "rb"); - if (file != NULL) + FILE * file = fopen(filename, "rb"); + if (file != NULL) { - fseek(file, 0, SEEK_END); - file_size = ftell(file); - fclose(file); + fseek(file, 0, SEEK_END); + file_size = ftell(file); + fclose(file); } #else - int file = sceIoOpen(filename,PSP_O_RDONLY, 0777); - if (file > 0){ - file_size = sceIoLseek(file, 0, PSP_SEEK_END); - sceIoClose(file); - } + int file = sceIoOpen(filename, PSP_O_RDONLY, 0777); + if (file > 0) + { + file_size = sceIoLseek(file, 0, PSP_SEEK_END); + sceIoClose(file); + } #endif - return file_size; + return file_size; } +int fileExists(const char * filename) +{ + std::ifstream fichier(filename); + if (fichier) + { + fichier.close(); + return 1; + } -int fileExists(const char * filename){ - std::ifstream fichier(filename); -if(fichier){ - fichier.close(); - return 1; + std::ifstream fichier2(JGE_GET_RES(filename).c_str()); + if (fichier2) + { + fichier2.close(); + return 1; + } + return 0; } -std::ifstream fichier2(JGE_GET_RES(filename).c_str()); -if(fichier2){ - fichier2.close(); - return 1; -} -return 0; -} - - /* -#ifdef LINUX + #ifdef LINUX -#include -void dumpStack() -{ - void* buffer[50]; - int s = backtrace(buffer, 50); - char** tab = backtrace_symbols(buffer, s); - for (int i = 1; i < s; ++i) printf("%s\n", tab[i]); - printf("\n"); - free(tab); -} - -#endif -*/ + #include + void dumpStack() + { + void* buffer[50]; + int s = backtrace(buffer, 50); + char** tab = backtrace_symbols(buffer, s); + for (int i = 1; i < s; ++i) printf("%s\n", tab[i]); + printf("\n"); + free(tab); + } + #endif + */ /* RAM simple check functions source */ - // *** FUNCTIONS *** -u32 ramAvailableLineareMax (void) +u32 ramAvailableLineareMax(void) { - u32 size, sizeblock; - u8 *ram; + u32 size, sizeblock; + u8 *ram; + // Init variables + size = 0; + sizeblock = RAM_BLOCK; - // Init variables - size = 0; - sizeblock = RAM_BLOCK; + // Check loop + while (sizeblock) + { + // Increment size + size += sizeblock; - // Check loop - while (sizeblock) - { - // Increment size - size += sizeblock; + // Allocate ram + ram = (u8 *) malloc(size); - // Allocate ram - ram = (u8 *) malloc(size); + // Check allocate + if (!(ram)) + { + // Restore old size + size -= sizeblock; - // Check allocate - if (!(ram)) - { - // Restore old size - size -= sizeblock; + // Size block / 2 + sizeblock >>= 1; + } + else + free(ram); + } - // Size block / 2 - sizeblock >>= 1; - } - else - free(ram); - } - - return size; + return size; } -u32 ramAvailable (void) +u32 ramAvailable(void) { - u8 **ram, **temp; - u32 size, count, x; + u8 **ram, **temp; + u32 size, count, x; + // Init variables + ram = NULL; + size = 0; + count = 0; - // Init variables - ram = NULL; - size = 0; - count = 0; + // Check loop + for (;;) + { + // Check size entries + if (!(count % 10)) + { + // Allocate more entries if needed + temp = (u8**) realloc(ram, sizeof(u8 *) * (count + 10)); + if (!(temp)) break; - // Check loop - for (;;) - { - // Check size entries - if (!(count % 10)) - { - // Allocate more entries if needed - temp = (u8**) realloc(ram,sizeof(u8 *) * (count + 10)); - if (!(temp)) break; - - // Update entries and size (size contains also size of entries) - ram = temp; - size += (sizeof(u8 *) * 10); - } + // Update entries and size (size contains also size of entries) + ram = temp; + size += (sizeof(u8 *) * 10); + } - // Find max lineare size available - x = ramAvailableLineareMax(); - if (!(x)) break; + // Find max lineare size available + x = ramAvailableLineareMax(); + if (!(x)) break; - // Allocate ram - ram[count] = (u8 *) malloc(x); - if (!(ram[count])) break; + // Allocate ram + ram[count] = (u8 *) malloc(x); + if (!(ram[count])) break; - // Update variables - size += x; - count++; - } + // Update variables + size += x; + count++; + } - // Free ram - if (ram) - { - for (x=0;x &split(const std::string &s, char delim, std::vector &elems) { +std::vector &split(const std::string &s, char delim, std::vector &elems) +{ std::stringstream ss(s); std::string item; - while(std::getline(ss, item, delim)) { + while (std::getline(ss, item, delim)) + { elems.push_back(item); } return elems; } - -std::vector split(const std::string &s, char delim) { +std::vector split(const std::string &s, char delim) +{ std::vector elems; return split(s, delim, elems); } - std::string wordWrap(std::string sentence, int width) -{ +{ std::string::iterator it = sentence.begin(); //remember how long next word is @@ -229,28 +234,28 @@ std::string wordWrap(std::string sentence, int width) { while (*it != ' ') { - nextWordLength++; - distanceFromWidth--; + nextWordLength++; + distanceFromWidth--; - ++it; + ++it; - // check if done - if (it == sentence.end()) - { - return sentence; - } + // check if done + if (it == sentence.end()) + { + return sentence; + } } if (nextWordLength > distanceFromWidth) { - *it = '\n'; - distanceFromWidth = width; - nextWordLength = 0; + *it = '\n'; + distanceFromWidth = width; + nextWordLength = 0; } //skip the space ++it; } - return sentence; -} \ No newline at end of file + return sentence; +}