diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 26e2ca91d..a46d058cb 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -91,6 +91,7 @@ hannas_custody.txt howl_of_the_night_pack.txt hymn_of_rebirth.txt icatian_priest.txt +jump.txt keldon_warlord.txt keldon_warlord2.txt kird_ape.txt diff --git a/projects/mtg/bin/Res/test/jump.txt b/projects/mtg/bin/Res/test/jump.txt new file mode 100644 index 000000000..d5f29cb7a --- /dev/null +++ b/projects/mtg/bin/Res/test/jump.txt @@ -0,0 +1,22 @@ +#Bug: Ability until end of turn + creature killed = crash ? +[INIT] +FIRSTMAIN +[PLAYER1] +hand:jump,terror +inplay:grizzly bears +manapool:{B}{U}{1} +[PLAYER2] +[DO] +jump +grizzly bears +terror +grizzly bears +eot +next +[ASSERT] +UPKEEP +[PLAYER1] +graveyard:jump,terror,grizzly bears +manapool:{0} +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 1589f5ac1..412b4ce8a 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -661,7 +661,8 @@ class AInstantBasicAbilityModifierUntilEOT: public InstantAbility{ } int destroy(){ - ((MTGCardInstance *)target)->basicAbilities[ability] = stateBeforeActivation; + MTGCardInstance * _target = (MTGCardInstance *)target; + if (_target) _target->basicAbilities[ability] = stateBeforeActivation; return 1; } virtual ostream& toString(ostream& out) const diff --git a/projects/mtg/include/Credits.h b/projects/mtg/include/Credits.h index 7a002cf14..075f6029f 100644 --- a/projects/mtg/include/Credits.h +++ b/projects/mtg/include/Credits.h @@ -25,6 +25,7 @@ private: int isDifficultyUnlocked(); int isMomirUnlocked(); int isEvilTwinUnlocked(); + int isRandomDeckUnlocked(); public: int value; Player * p1, *p2; diff --git a/projects/mtg/include/GameApp.h b/projects/mtg/include/GameApp.h index b1670fd98..8485b8585 100644 --- a/projects/mtg/include/GameApp.h +++ b/projects/mtg/include/GameApp.h @@ -45,6 +45,8 @@ #define GAME_TYPE_CLASSIC 0 #define GAME_TYPE_MOMIR 1 +#define GAME_TYPE_RANDOM1 2 +#define GAME_TYPE_RANDOM2 3 class MTGAllCards; class TexturesCache; diff --git a/projects/mtg/include/GameStateDuel.h b/projects/mtg/include/GameStateDuel.h index 04bb93bc5..4a818f366 100644 --- a/projects/mtg/include/GameStateDuel.h +++ b/projects/mtg/include/GameStateDuel.h @@ -34,6 +34,7 @@ class GameStateDuel: public GameState, public JGuiListener void loadPlayer(int playerId, int decknb = 0, int isAI = 0); void loadPlayerMomir(int playerId, int isAI); + void loadPlayerRandom(int playerId, int isAI, int mode); public: GameStateDuel(GameApp* parent); diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index 88006b95f..4523bfb32 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -60,7 +60,7 @@ class MTGAbility: public ActionElement{ virtual int receiveEvent(WEvent * event){return 0;}; virtual void Update(float dt){}; virtual int fireAbility(); - virtual int stillInUse(MTGCardInstance * card){if (card==source) return 1; return 0;}; + virtual int stillInUse(MTGCardInstance * card); virtual int resolve(){return 0;}; virtual MTGAbility* clone() const = 0; virtual ostream& toString(ostream& out) const; diff --git a/projects/mtg/include/MTGDeck.h b/projects/mtg/include/MTGDeck.h index 2b98bfa57..cb6eb1f09 100644 --- a/projects/mtg/include/MTGDeck.h +++ b/projects/mtg/include/MTGDeck.h @@ -94,7 +94,7 @@ class MTGDeck{ int totalCards(); MTGDeck(TexturesCache * cache, MTGAllCards * _allcards); MTGDeck(const char * config_file, TexturesCache * cache, MTGAllCards * _allcards, int meta_only = 0); - int addRandomCards(int howmany, int setId = -1, int rarity = -1, const char * subtype = NULL); + int addRandomCards(int howmany, int setId = -1, int rarity = -1, const char * subtype = NULL, int * colors = NULL, int nbcolors = 0); int add(int cardid); int add(MTGDeck * deck); // adds the contents of "deck" into myself int remove(int cardid); diff --git a/projects/mtg/src/Credits.cpp b/projects/mtg/src/Credits.cpp index 244f07726..8d1e518ac 100644 --- a/projects/mtg/src/Credits.cpp +++ b/projects/mtg/src/Credits.cpp @@ -43,7 +43,7 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app){ if (!p1->isAI() && p2->isAI() && p1!= g->gameOver){ GameOptions * go = GameOptions::GetInstance(); value = 400; - if (app->gameType == GAME_TYPE_MOMIR) value = 200; + if (app->gameType != GAME_TYPE_CLASSIC) value = 200; int difficulty = go->values[OPTIONS_DIFFICULTY].getIntValue(); if (go->values[OPTIONS_DIFFICULTY_MODE_UNLOCKED].getIntValue() && difficulty) { CreditBonus * b = NEW CreditBonus(100*difficulty, _("Difficulty Bonus")); @@ -88,6 +88,11 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app){ unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96); GameOptions::GetInstance()->values[OPTIONS_EVILTWIN_MODE_UNLOCKED] = GameOption(1); GameOptions::GetInstance()->save(); + }else if(unlocked = isRandomDeckUnlocked()) { + unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/randomdeck_unlocked.png", TEX_TYPE_USE_VRAM); + unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96); + GameOptions::GetInstance()->values[OPTIONS_RANDOMDECK_MODE_UNLOCKED] = GameOption(1); + GameOptions::GetInstance()->save(); } if (unlocked){ JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/bonus.wav"); @@ -203,3 +208,10 @@ int Credits::isEvilTwinUnlocked(){ if (p1->game->inPlay->nb_cards && (p1->game->inPlay->nb_cards == p2->game->inPlay->nb_cards)) return 1; return 0; } + +int Credits::isRandomDeckUnlocked(){ + if (GameOptions::GetInstance()->values[OPTIONS_DIFFICULTY].getIntValue() == 0 ) return 0; + if (GameOptions::GetInstance()->values[OPTIONS_RANDOMDECK_MODE_UNLOCKED].getIntValue()) return 0; + if (p1->life >= 20 ) return 1; + return 0; +} diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 3e66ea644..760720e58 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -96,12 +96,6 @@ void GameObserver::nextGamePhase(){ phaseRing->forward(); Phase * cPhase = phaseRing->getCurrentPhase(); - - //Warn the layers about the phase Change - WEvent * e = NEW WEventPhaseChange(cPhaseOld, cPhase); - receiveEvent(e); - delete e; - currentGamePhase = cPhase->id; if (currentPlayer != cPhase->player) nextPlayer(); diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 2ff2fc3c9..e30be19b3 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -107,6 +107,40 @@ void GameStateDuel::Start() //mGamePhase = DUEL_STATE_ERROR_NO_DECK; } +void GameStateDuel::loadPlayerRandom(int playerId, int isAI, int mode){ + int color1 = 1 + rand() % 5; + int color2 = 1 + rand() % 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(NULL, mParent->collection); + tempDeck->addRandomCards(9,-1,-1,lands[color1].c_str()); + tempDeck->addRandomCards(9,-1,-1,lands[color2].c_str()); + tempDeck->addRandomCards(1,-1,'U',"land",colors,nbcolors); + tempDeck->addRandomCards(1,-1,'R',"land",colors,nbcolors); + tempDeck->addRandomCards(12,-1,-1,"creature",colors,nbcolors); + tempDeck->addRandomCards(2,-1,-1,"sorcery",colors,nbcolors); + tempDeck->addRandomCards(2,-1,-1,"enchantment",colors,nbcolors); + tempDeck->addRandomCards(2,-1,-1,"instant",colors,nbcolors); + tempDeck->addRandomCards(2,-1,-1,"artifact",colors,nbcolors); + + char * deckFile = "random"; + string deckFileSmall = "random"; + + deck[playerId] = NEW MTGPlayerCards(mParent->collection,tempDeck); + if (!isAI){ //Human Player + mPlayers[playerId] = NEW HumanPlayer(deck[playerId],deckFile, deckFileSmall); + }else{ + mPlayers[playerId] = NEW AIPlayerBaka(deck[playerId],deckFile, "random", ""); + } + delete tempDeck; +} + void GameStateDuel::loadPlayerMomir(int playerId, int isAI){ char deckFile[] = RESPATH"/player/momir.txt"; @@ -226,6 +260,13 @@ void GameStateDuel::Update(float dt) loadPlayerMomir(i, isAI); } mGamePhase = DUEL_STATE_PLAY; + } else if (mParent->gameType == GAME_TYPE_RANDOM1 || mParent->gameType == GAME_TYPE_RANDOM2){ + for (int i = 0; i < 2; i++){ + int isAI = 1; + if (mParent->players[i] == PLAYER_TYPE_HUMAN) isAI = 0; + loadPlayerRandom(i, isAI, mParent->gameType); + } + mGamePhase = DUEL_STATE_PLAY; }else if (mParent->players[0] == PLAYER_TYPE_HUMAN) deckmenu->Update(dt); #ifdef TESTSUITE @@ -373,10 +414,14 @@ void GameStateDuel::Render() case DUEL_STATE_CHOOSE_DECK1_TO_2: case DUEL_STATE_CHOOSE_DECK2: case DUEL_STATE_CHOOSE_DECK2_TO_PLAY: - 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; case DUEL_STATE_ERROR_NO_DECK: diff --git a/projects/mtg/src/GameStateMenu.cpp b/projects/mtg/src/GameStateMenu.cpp index 9a51632e6..ea4c441c8 100644 --- a/projects/mtg/src/GameStateMenu.cpp +++ b/projects/mtg/src/GameStateMenu.cpp @@ -56,6 +56,8 @@ enum SUBMENUITEM_TESTSUITE, SUBMENUITEM_MOMIR, SUBMENUITEM_CLASSIC, + SUBMENUITEM_RANDOM1, + SUBMENUITEM_RANDOM2, }; @@ -167,6 +169,7 @@ void GameStateMenu::Start(){ hasChosenGameType = 1; if (GameOptions::GetInstance()->values[OPTIONS_MOMIR_MODE_UNLOCKED].getIntValue()) hasChosenGameType =0; + if (GameOptions::GetInstance()->values[OPTIONS_RANDOMDECK_MODE_UNLOCKED].getIntValue()) hasChosenGameType =0; @@ -338,7 +341,13 @@ void GameStateMenu::Update(float dt) subMenuController = NEW SimpleMenu(102, this, mFont, 150,60); if (subMenuController){ subMenuController->Add(SUBMENUITEM_CLASSIC,"Classic"); - subMenuController->Add(SUBMENUITEM_MOMIR, "Momir Basic"); + if (GameOptions::GetInstance()->values[OPTIONS_MOMIR_MODE_UNLOCKED].getIntValue()){ + subMenuController->Add(SUBMENUITEM_MOMIR, "Momir Basic"); + } + if (GameOptions::GetInstance()->values[OPTIONS_RANDOMDECK_MODE_UNLOCKED].getIntValue()){ + subMenuController->Add(SUBMENUITEM_RANDOM1, "Random 1 Color"); + subMenuController->Add(SUBMENUITEM_RANDOM2, "Random 2 Colors"); + } subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel"); } }else{ @@ -575,6 +584,20 @@ JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT); 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; #ifdef TESTSUITE case SUBMENUITEM_TESTSUITE: mParent->players[0] = PLAYER_TYPE_TESTSUITE; diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 7dc9fe87f..9f9b0abe3 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1976,6 +1976,11 @@ MTGAbility::MTGAbility(int id, MTGCardInstance * _source,Targetable * _target ): oneShot = 0; } +int MTGAbility::stillInUse(MTGCardInstance * card){ + if (card==source || card==target) return 1; + return 0; +} + MTGAbility::~MTGAbility(){ if (!isClone){ SAFE_DELETE(cost); diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index a406be9a7..ea025bbbb 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -351,6 +351,8 @@ MTGDeck::MTGDeck(TexturesCache * cache, MTGAllCards * _allcards){ mCache = cache; total_cards = 0; database = _allcards; + filename =""; + meta_name = ""; } MTGDeck::MTGDeck(const char * config_file, TexturesCache * cache, MTGAllCards * _allcards, int meta_only){ @@ -418,10 +420,20 @@ MTGCard * MTGDeck::getCardById(int mtgId){ return database->getCardById(mtgId); } -int MTGDeck::addRandomCards(int howmany, int setId, int rarity, const char * _subtype){ + +int MTGDeck::addRandomCards(int howmany, int setId, int rarity, const char * _subtype, int * colors, int nbcolors){ + 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; - if (setId == -1 && rarity == -1 && !_subtype){ + if (setId == -1 && rarity == -1 && !_subtype && !nbcolors){ for (int i = 0; i < howmany; i++){ add(database->randomCardId()); } @@ -440,8 +452,17 @@ int MTGDeck::addRandomCards(int howmany, int setId, int rarity, const char * _su (rarity == -1 || card->getRarity()==rarity) && (!_subtype || card->hasSubtype(subtype)) ){ - subcollection.push_back(card->getId()); - subtotal++; + int ok = 1; + for (int j=0; j < Constants::MTG_NB_COLORS; ++j){ + if (unallowedColors[j] && card->hasColor(j)){ + ok = 0; + break; + } + } + if (ok){ + subcollection.push_back(card->getId()); + subtotal++; + } } } if (subtotal == 0) return 0; diff --git a/projects/mtg/src/PhaseRing.cpp b/projects/mtg/src/PhaseRing.cpp index beab11f1f..dc2d60d5b 100644 --- a/projects/mtg/src/PhaseRing.cpp +++ b/projects/mtg/src/PhaseRing.cpp @@ -2,7 +2,7 @@ #include "../include/MTGDefinitions.h" #include "../include/Player.h" #include "../include/config.h" - +#include "../include/WEvent.h" /* Creates a new phase ring with the default rules */ @@ -32,8 +32,15 @@ Phase * PhaseRing::getCurrentPhase(){ } Phase * PhaseRing::forward(){ + Phase * cPhaseOld = *current; if (current != ring.end()) current++; if (current == ring.end()) current = ring.begin(); + + //Warn the layers about the phase Change + WEvent * e = NEW WEventPhaseChange(cPhaseOld, *current); + GameObserver::GetInstance()->receiveEvent(e); + delete e; + return *current; }