Added HTR18, HT19, AFR and AFC sets, added/fixed old primitives, improved Android dowloader, fixed it lang file, fixed IMA rarities, fixed order index of some old sets, added all features from D&D such as Dungeon Cards and Dice (d20,d10, adn so on).
This commit is contained in:
@@ -605,9 +605,14 @@ int PutInGraveyard::resolve()
|
||||
}
|
||||
if (card->basicAbilities[(int)Constants::INPLAYDEATH] || card->basicAbilities[(int)Constants::INPLAYTAPDEATH])
|
||||
{
|
||||
card->controller()->game->putInZone(card, zone, card->owner->game->battlefield);
|
||||
if(card->basicAbilities[(int)Constants::INPLAYTAPDEATH])
|
||||
bool toTap = card->basicAbilities[(int)Constants::INPLAYTAPDEATH];
|
||||
bool addCounter = card->basicAbilities[(int)Constants::COUNTERDEATH];
|
||||
card = card->controller()->game->putInZone(card, zone, card->owner->game->graveyard);
|
||||
card = card->controller()->game->putInZone(card, card->owner->game->graveyard, card->owner->game->battlefield);
|
||||
if(toTap)
|
||||
card->tap(true);
|
||||
if(addCounter)
|
||||
card->counters->addCounter(1, 1, false);
|
||||
return 1;
|
||||
}
|
||||
if (zone == observer->players[0]->game->inPlay || zone == observer->players[1]->game->inPlay)
|
||||
|
||||
@@ -1240,6 +1240,48 @@ AAAlterDevotionOffset::~AAAlterDevotionOffset()
|
||||
{
|
||||
}
|
||||
|
||||
//AA Dungeon Completed
|
||||
AAAlterDungeonCompleted::AAAlterDungeonCompleted(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int dungeoncounter, ManaCost * _cost,
|
||||
int who) :
|
||||
ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), dungeoncounter(dungeoncounter)
|
||||
{
|
||||
}
|
||||
|
||||
int AAAlterDungeonCompleted::resolve()
|
||||
{
|
||||
Damageable * _target = (Damageable *) getTarget();
|
||||
if (_target)
|
||||
{
|
||||
Player * pTarget = (Player*)_target;
|
||||
if(pTarget)
|
||||
{
|
||||
source = pTarget->game->putInSideboard(source);
|
||||
source->basicAbilities[Constants::DUNGEONCOMPLETED] = 1;
|
||||
pTarget->dungeonCompleted += dungeoncounter;
|
||||
if(pTarget->dungeonCompleted < 0)
|
||||
pTarget->dungeonCompleted = 0;
|
||||
WEvent * e = NEW WEventCardDungeonCompleted(source, pTarget->dungeonCompleted, source->controller()->getDisplayName());
|
||||
game->receiveEvent(e);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const string AAAlterDungeonCompleted::getMenuText()
|
||||
{
|
||||
WParsedInt parsedNum(dungeoncounter);
|
||||
return _(parsedNum.getStringValue() + " Dungeon Completed Counter ").c_str();
|
||||
}
|
||||
|
||||
AAAlterDungeonCompleted * AAAlterDungeonCompleted::clone() const
|
||||
{
|
||||
return NEW AAAlterDungeonCompleted(*this);
|
||||
}
|
||||
|
||||
AAAlterDungeonCompleted::~AAAlterDungeonCompleted()
|
||||
{
|
||||
}
|
||||
|
||||
//AA Yidaro Count
|
||||
AAAlterYidaroCount::AAAlterYidaroCount(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int yidarocount, ManaCost * _cost,
|
||||
int who) :
|
||||
@@ -3188,9 +3230,9 @@ AASetCoin::~AASetCoin()
|
||||
}
|
||||
|
||||
//
|
||||
//rolling a 6 side die
|
||||
GenericRollDie::GenericRollDie(GameObserver* observer, int id, MTGCardInstance * source, Targetable *, string _toAdd, ManaCost * cost, int userchoice) :
|
||||
ActivatedAbility(observer, id, source, cost, 0), baseAbility(_toAdd), userchoice(userchoice)
|
||||
//rolling a generic die
|
||||
GenericRollDie::GenericRollDie(GameObserver* observer, int id, MTGCardInstance * source, Targetable *, string _toAdd, ManaCost * cost, int userchoice, int diefaces) :
|
||||
ActivatedAbility(observer, id, source, cost, 0), baseAbility(_toAdd), userchoice(userchoice), diefaces(diefaces)
|
||||
{
|
||||
this->GetId();
|
||||
setDie = NULL;
|
||||
@@ -3201,17 +3243,17 @@ int GenericRollDie::resolve()
|
||||
if (!target)
|
||||
return 0;
|
||||
vector<MTGAbility*>selection;
|
||||
if(userchoice > 0 && userchoice < 7){
|
||||
setDie = NEW AASetDie(game, game->mLayers->actionLayer()->getMaxId(), source,(MTGCardInstance*)target, userchoice, baseAbility);
|
||||
if(userchoice > 0 && userchoice <= diefaces){
|
||||
setDie = NEW AASetDie(game, game->mLayers->actionLayer()->getMaxId(), source,(MTGCardInstance*)target, userchoice, diefaces, baseAbility);
|
||||
MTGAbility * set = setDie->clone();
|
||||
set->oneShot = true;
|
||||
game->mLayers->actionLayer()->currentActionCard = (MTGCardInstance *)target;
|
||||
set->resolve();
|
||||
SAFE_DELETE(setDie);
|
||||
} else{
|
||||
for (int i = 1; i < 7; ++i)
|
||||
for (int i = 1; i <= diefaces; ++i)
|
||||
{
|
||||
setDie = NEW AASetDie(game, game->mLayers->actionLayer()->getMaxId(), source,(MTGCardInstance*)target, i, baseAbility);
|
||||
setDie = NEW AASetDie(game, game->mLayers->actionLayer()->getMaxId(), source,(MTGCardInstance*)target, i, diefaces, baseAbility);
|
||||
MTGAbility * set = setDie->clone();
|
||||
set->oneShot = true;
|
||||
selection.push_back(set);
|
||||
@@ -3230,7 +3272,9 @@ int GenericRollDie::resolve()
|
||||
|
||||
const string GenericRollDie::getMenuText()
|
||||
{
|
||||
return "Roll a Die";
|
||||
std::stringstream msg;
|
||||
msg << "Roll a " << diefaces << " faced Die";
|
||||
return msg.str();
|
||||
}
|
||||
|
||||
GenericRollDie * GenericRollDie::clone() const
|
||||
@@ -3243,9 +3287,9 @@ GenericRollDie::~GenericRollDie()
|
||||
{
|
||||
}
|
||||
|
||||
//set color choosen
|
||||
AASetDie::AASetDie(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target, int _side, string toAlter):
|
||||
InstantAbility(observer, id, source),side(_side), abilityToAlter(toAlter)
|
||||
//set die result
|
||||
AASetDie::AASetDie(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * _target, int _side, int _diefaces, string toAlter):
|
||||
InstantAbility(observer, id, source),side(_side), diefaces(_diefaces), abilityToAlter(toAlter)
|
||||
{
|
||||
this->target = _target;
|
||||
abilityAltered = NULL;
|
||||
@@ -3256,8 +3300,9 @@ int AASetDie::resolve()
|
||||
MTGCardInstance * _target = (MTGCardInstance *)target;
|
||||
_target->dieSide = side;
|
||||
|
||||
int roll = 1 + game->getRandomGenerator()->random() % 6;
|
||||
int roll = 1 + game->getRandomGenerator()->random() % diefaces;
|
||||
_target->lastRollResult = roll;
|
||||
_target->dieNumFaces = diefaces;
|
||||
WEvent * e = NEW WEventCardRollDie(_target, source->controller()->getDisplayName());
|
||||
game->receiveEvent(e);
|
||||
vector<string>Win = parseBetween(abilityToAlter,"winability "," winabilityend");
|
||||
@@ -4473,6 +4518,8 @@ int AAFlip::resolve()
|
||||
MTGCardInstance * myParent = NULL;
|
||||
if(_target->target)
|
||||
myParent = _target->target;
|
||||
if(_target->nameOrig == "")
|
||||
_target->nameOrig = _target->name; // Saves the orignal card name before to flip the card.
|
||||
_target->name = myFlip->name;
|
||||
_target->setName(myFlip->name);
|
||||
if(!isflipcard)//transform card
|
||||
|
||||
@@ -39,6 +39,7 @@ GameStateDeckViewer::GameStateDeckViewer(GameApp* parent) :
|
||||
myDeck = NULL;
|
||||
mySideboard = NULL;
|
||||
myCommandZone = NULL;
|
||||
myDungeonZone = NULL;
|
||||
filterMenu = NULL;
|
||||
source = NULL;
|
||||
hudAlpha = 0;
|
||||
@@ -50,7 +51,7 @@ GameStateDeckViewer::GameStateDeckViewer(GameApp* parent) :
|
||||
statsPrevButton = NEW InteractiveButton(NULL, kPrevStatsButtonId, Fonts::MAIN_FONT, "Stats", SCREEN_WIDTH_F - 35, SCREEN_HEIGHT_F - 20, JGE_BTN_PREV);
|
||||
toggleDeckButton = NEW InteractiveButton(NULL, kToggleDeckActionId, Fonts::MAIN_FONT, "View Deck", 10, SCREEN_HEIGHT_F - 20, JGE_BTN_PRI);
|
||||
sellCardButton = NEW InteractiveButton(NULL, kSellCardActionId, Fonts::MAIN_FONT, "Sell Card", (SCREEN_WIDTH_F/ 2) - 125, SCREEN_HEIGHT_F - 20, JGE_BTN_SEC);
|
||||
sb_cmd_Button = NEW InteractiveButton(NULL, kSBActionId, Fonts::MAIN_FONT, "View SB/CMD", (SCREEN_WIDTH_F/ 2) - 35, SCREEN_HEIGHT_F - 20, JGE_BTN_SOUND);
|
||||
sb_cmd_dng_Button = NEW InteractiveButton(NULL, kSBActionId, Fonts::MAIN_FONT, "View SB", (SCREEN_WIDTH_F/ 2) - 35, SCREEN_HEIGHT_F - 20, JGE_BTN_SOUND);
|
||||
filterButton = NEW InteractiveButton(NULL, kFilterButtonId, Fonts::MAIN_FONT, "Filter", (SCREEN_WIDTH_F - 116), SCREEN_HEIGHT_F - 20, JGE_BTN_CTRL);
|
||||
//TODO: Check if that button is available:
|
||||
toggleViewButton = NEW InteractiveButton(NULL, kSwitchViewButton, Fonts::MAIN_FONT, "Grid", (SCREEN_WIDTH_F/ 2) + 50, SCREEN_HEIGHT_F - 20, JGE_BTN_MAX);
|
||||
@@ -65,7 +66,7 @@ GameStateDeckViewer::~GameStateDeckViewer()
|
||||
SAFE_DELETE(bgMusic);
|
||||
SAFE_DELETE(toggleDeckButton);
|
||||
SAFE_DELETE(sellCardButton);
|
||||
SAFE_DELETE(sb_cmd_Button);
|
||||
SAFE_DELETE(sb_cmd_dng_Button);
|
||||
SAFE_DELETE(statsPrevButton);
|
||||
SAFE_DELETE(filterButton);
|
||||
SAFE_DELETE(toggleViewButton);
|
||||
@@ -90,6 +91,11 @@ GameStateDeckViewer::~GameStateDeckViewer()
|
||||
SAFE_DELETE(myCommandZone->parent);
|
||||
SAFE_DELETE(myCommandZone);
|
||||
}
|
||||
if (myDungeonZone)
|
||||
{
|
||||
SAFE_DELETE(myDungeonZone->parent);
|
||||
SAFE_DELETE(myDungeonZone);
|
||||
}
|
||||
if (myCollection)
|
||||
{
|
||||
SAFE_DELETE(myCollection->parent);
|
||||
@@ -125,7 +131,7 @@ void GameStateDeckViewer::updateFilters()
|
||||
|
||||
void GameStateDeckViewer::toggleCollection()
|
||||
{
|
||||
if(mView->deck() == mySideboard || mView->deck() == myCommandZone)
|
||||
if(mView->deck() == mySideboard || mView->deck() == myCommandZone || mView->deck() == myDungeonZone)
|
||||
return;
|
||||
|
||||
if (mView->deck() == myCollection)
|
||||
@@ -142,7 +148,7 @@ void GameStateDeckViewer::toggleCollection()
|
||||
updateFilters();
|
||||
}
|
||||
|
||||
void GameStateDeckViewer::toggleSB_CMD()
|
||||
void GameStateDeckViewer::toggleSB_CMD_DNG()
|
||||
{
|
||||
if(mView->deck() == myDeck)
|
||||
return;
|
||||
@@ -150,17 +156,22 @@ void GameStateDeckViewer::toggleSB_CMD()
|
||||
if (mView->deck() == myCollection)
|
||||
{
|
||||
mView->SetDeck(mySideboard);
|
||||
sb_cmd_Button->setText("View CMD");
|
||||
sb_cmd_dng_Button->setText("View CMD");
|
||||
}
|
||||
else if (mView->deck() == mySideboard)
|
||||
{
|
||||
mView->SetDeck(myCommandZone);
|
||||
sb_cmd_Button->setText("View Coll.");
|
||||
sb_cmd_dng_Button->setText("View DNG");
|
||||
}
|
||||
else if (mView->deck() == myCommandZone)
|
||||
{
|
||||
mView->SetDeck(myDungeonZone);
|
||||
sb_cmd_dng_Button->setText("View Coll.");
|
||||
}
|
||||
else
|
||||
{
|
||||
mView->SetDeck(myCollection);
|
||||
sb_cmd_Button->setText("View SB/CMD");
|
||||
sb_cmd_dng_Button->setText("View SB");
|
||||
}
|
||||
//source->swapSrc();
|
||||
//updateFilters();
|
||||
@@ -210,6 +221,7 @@ void GameStateDeckViewer::Start()
|
||||
myDeck = NULL;
|
||||
mySideboard = NULL;
|
||||
myCommandZone = NULL;
|
||||
myDungeonZone = NULL;
|
||||
mStage = STAGE_WELCOME;
|
||||
|
||||
last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1;
|
||||
@@ -282,6 +294,11 @@ void GameStateDeckViewer::End()
|
||||
SAFE_DELETE(myCommandZone->parent);
|
||||
SAFE_DELETE(myCommandZone);
|
||||
}
|
||||
if (myDungeonZone)
|
||||
{
|
||||
SAFE_DELETE(myDungeonZone->parent);
|
||||
SAFE_DELETE(myDungeonZone);
|
||||
}
|
||||
SAFE_DELETE(pricelist);
|
||||
SAFE_DELETE(playerdata);
|
||||
SAFE_DELETE(filterMenu);
|
||||
@@ -354,6 +371,28 @@ void GameStateDeckViewer::CMDaddRemove(MTGCard * card)
|
||||
mView->reloadIndexes();
|
||||
}
|
||||
|
||||
void GameStateDeckViewer::DNGaddRemove(MTGCard * card)
|
||||
{
|
||||
if (!card) return;
|
||||
if ((card->getRarity() != Constants::RARITY_T) || (card->getId() < 1)) return;
|
||||
if (mView->deck()->Remove(card, 1, (mView->deck() == myDungeonZone)))
|
||||
{
|
||||
if (mView->deck() == myCollection)
|
||||
{
|
||||
myDungeonZone->Add(card);
|
||||
myDungeonZone->Sort(WSrcCards::SORT_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
myCollection->Add(card);
|
||||
}
|
||||
}
|
||||
myCollection->validate();
|
||||
myDungeonZone->validate();
|
||||
mStatsWrapper->needUpdate = true;
|
||||
mView->reloadIndexes();
|
||||
}
|
||||
|
||||
void GameStateDeckViewer::choiceAddRemove(MTGCard * card)
|
||||
{
|
||||
if (!card) return;
|
||||
@@ -366,19 +405,37 @@ void GameStateDeckViewer::choiceAddRemove(MTGCard * card)
|
||||
if (mView->deck() == myCollection)
|
||||
{
|
||||
sbMenu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), SBMENU_CHOICE, this, Fonts::MAIN_FONT, menuXOffset, menuYOffset, "Add/Remove Cards");
|
||||
sbMenu->Add(SBMENU_ADD_NORMAL, "Add to Deck");
|
||||
sbMenu->Add(SBMENU_ADD_SB, "Add to Sideboard");
|
||||
if(card->data->hasType("Legendary") && (card->data->hasType("Creature") || card->data->basicAbilities[Constants::CANBECOMMANDER]))
|
||||
sbMenu->Add(SBMENU_ADD_CMD, "Choose as Commander");
|
||||
if(!card->data->hasType("Dungeon")){
|
||||
sbMenu->Add(SBMENU_ADD_NORMAL, "Add to Deck");
|
||||
sbMenu->Add(SBMENU_ADD_SB, "Add to Sideboard");
|
||||
if(card->data->hasType("Legendary") && (card->data->hasType("Creature") || card->data->basicAbilities[Constants::CANBECOMMANDER]))
|
||||
sbMenu->Add(SBMENU_ADD_CMD, "Choose as Commander");
|
||||
} else
|
||||
sbMenu->Add(SBMENU_ADD_DNG, "Add to Dungeons");
|
||||
sbMenu->Add(SBMENU_ADD_CANCEL, "Cancel");
|
||||
}
|
||||
else
|
||||
else if (mView->deck() == myCommandZone)
|
||||
{
|
||||
sbMenu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), SBMENU_CHOICE, this, Fonts::MAIN_FONT, menuXOffset, menuYOffset, "Add/Remove Cards");
|
||||
sbMenu->Add(SBMENU_ADD_CMD, "Remove as Commander");
|
||||
sbMenu->Add(SBMENU_ADD_CANCEL, "Cancel");
|
||||
}
|
||||
else if (mView->deck() == mySideboard)
|
||||
{
|
||||
sbMenu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), SBMENU_CHOICE, this, Fonts::MAIN_FONT, menuXOffset, menuYOffset, "Add/Remove Cards");
|
||||
sbMenu->Add(SBMENU_ADD_SB, "Remove from Sideboard");
|
||||
sbMenu->Add(SBMENU_ADD_CANCEL, "Cancel");
|
||||
}
|
||||
else if (mView->deck() == myDungeonZone)
|
||||
{
|
||||
sbMenu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), SBMENU_CHOICE, this, Fonts::MAIN_FONT, menuXOffset, menuYOffset, "Add/Remove Cards");
|
||||
sbMenu->Add(SBMENU_ADD_DNG, "Remove from Dungeons");
|
||||
sbMenu->Add(SBMENU_ADD_CANCEL, "Cancel");
|
||||
}
|
||||
else if (mView->deck() == myDeck)
|
||||
{
|
||||
sbMenu = NEW SimpleMenu(JGE::GetInstance(), WResourceManager::Instance(), SBMENU_CHOICE, this, Fonts::MAIN_FONT, menuXOffset, menuYOffset, "Add/Remove Cards");
|
||||
sbMenu->Add(SBMENU_ADD_NORMAL, "Remove Card");
|
||||
//sbMenu->Add(SBMENU_ADD_SB, "Add to Sideboard");
|
||||
if(card->data->hasType("Legendary") && (card->data->hasType("Creature") || card->data->basicAbilities[Constants::CANBECOMMANDER]))
|
||||
sbMenu->Add(SBMENU_ADD_CMD, "Choose as Commander");
|
||||
sbMenu->Add(SBMENU_ADD_CANCEL, "Cancel");
|
||||
}
|
||||
}
|
||||
@@ -425,6 +482,26 @@ void GameStateDeckViewer::insertCommandZone()
|
||||
}
|
||||
}
|
||||
|
||||
void GameStateDeckViewer::insertDungeonZone()
|
||||
{
|
||||
if(myDungeonZone->getCount())
|
||||
{
|
||||
vector<string> newDNG;
|
||||
for (int i = 0; i < myDungeonZone->Size(true); i++)
|
||||
{
|
||||
MTGCard * current = myDungeonZone->getCard(i, true);
|
||||
int howmanyinDeck = myDungeonZone->count(current);
|
||||
for (int i = 0; i < howmanyinDeck; i++)
|
||||
{
|
||||
stringstream cid;
|
||||
cid << current->getMTGId();
|
||||
newDNG.push_back(cid.str());
|
||||
}
|
||||
}
|
||||
myDeck->parent->replaceDNG(newDNG);
|
||||
}
|
||||
}
|
||||
|
||||
void GameStateDeckViewer::saveDeck()
|
||||
{
|
||||
//update the corresponding meta data object
|
||||
@@ -436,6 +513,8 @@ void GameStateDeckViewer::saveDeck()
|
||||
insertSideBoard();
|
||||
//insert commanders to mydeck parents
|
||||
insertCommandZone();
|
||||
//insert dungeons to mydeck parents
|
||||
insertDungeonZone();
|
||||
//save deck
|
||||
myDeck->save();
|
||||
playerdata->save();
|
||||
@@ -491,7 +570,7 @@ bool GameStateDeckViewer::userPressedButton()
|
||||
{
|
||||
return ((toggleDeckButton->ButtonPressed())
|
||||
|| (sellCardButton->ButtonPressed())
|
||||
|| (sb_cmd_Button->ButtonPressed())
|
||||
|| (sb_cmd_dng_Button->ButtonPressed())
|
||||
|| (statsPrevButton->ButtonPressed())
|
||||
|| (filterButton->ButtonPressed())
|
||||
|| (toggleViewButton->ButtonPressed())
|
||||
@@ -506,7 +585,7 @@ void GameStateDeckViewer::setButtonState(bool state)
|
||||
{
|
||||
toggleDeckButton->setIsSelectionValid(state);
|
||||
sellCardButton->setIsSelectionValid(state);
|
||||
sb_cmd_Button->setIsSelectionValid(state);
|
||||
sb_cmd_dng_Button->setIsSelectionValid(state);
|
||||
statsPrevButton->setIsSelectionValid(state);
|
||||
filterButton->setIsSelectionValid(state);
|
||||
toggleViewButton->setIsSelectionValid(state);
|
||||
@@ -518,12 +597,12 @@ void GameStateDeckViewer::setButtonState(bool state)
|
||||
|
||||
void GameStateDeckViewer::RenderButtons()
|
||||
{
|
||||
if(mView->deck() != mySideboard && mView->deck() != myCommandZone)
|
||||
if(mView->deck() != mySideboard && mView->deck() != myCommandZone && mView->deck() != myDungeonZone)
|
||||
toggleDeckButton->Render();
|
||||
sellCardButton->Render();
|
||||
if(mView->deck() != myDeck)
|
||||
sb_cmd_Button->Render();
|
||||
if(mView->deck() != mySideboard && mView->deck() != myCommandZone)
|
||||
sb_cmd_dng_Button->Render();
|
||||
if(mView->deck() != mySideboard && mView->deck() != myCommandZone && mView->deck() != myDungeonZone)
|
||||
filterButton->Render();
|
||||
statsPrevButton->Render();
|
||||
toggleViewButton->Render();
|
||||
@@ -631,7 +710,7 @@ void GameStateDeckViewer::Update(float dt)
|
||||
if (last_user_activity > 0.2)
|
||||
{
|
||||
last_user_activity = 0;
|
||||
toggleSB_CMD();
|
||||
toggleSB_CMD_DNG();
|
||||
}
|
||||
break;
|
||||
case JGE_BTN_PRI:
|
||||
@@ -685,9 +764,9 @@ void GameStateDeckViewer::Update(float dt)
|
||||
break;
|
||||
|
||||
case JGE_BTN_MENU:
|
||||
if(mView->deck() == mySideboard || mView->deck() == myCommandZone)
|
||||
if(mView->deck() == mySideboard || mView->deck() == myCommandZone || mView->deck() == myDungeonZone)
|
||||
{
|
||||
toggleSB_CMD();
|
||||
toggleSB_CMD_DNG();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -696,7 +775,7 @@ void GameStateDeckViewer::Update(float dt)
|
||||
}
|
||||
break;
|
||||
case JGE_BTN_CTRL:
|
||||
if (mView->deck() == mySideboard || mView->deck() == myCommandZone)
|
||||
if (mView->deck() == mySideboard || mView->deck() == myCommandZone || mView->deck() == myDungeonZone)
|
||||
break;//SB is for viewing add or remove only
|
||||
else if(!mView->ButtonPressed(JGE_BTN_CTRL))
|
||||
{
|
||||
@@ -985,7 +1064,8 @@ void GameStateDeckViewer::renderOnScreenMenu()
|
||||
int value = myDeck->getCount(WSrcDeck::UNFILTERED_COPIES);
|
||||
int sb_value = mySideboard->getCount(WSrcDeck::UNFILTERED_COPIES);
|
||||
int cmd_value = myCommandZone->getCount(WSrcDeck::UNFILTERED_COPIES);
|
||||
sprintf(buffer, _("Your Deck: %i cards.\nSideboard: %i cards.\nCommanders: %i cards").c_str(), value, sb_value,cmd_value);
|
||||
int dng_value = myDungeonZone->getCount(WSrcDeck::UNFILTERED_COPIES);
|
||||
sprintf(buffer, _("Your Deck: %i cards.\nSideboard: %i cards.\nCommanders: %i cards.\nDungeons: %i cards").c_str(), value, sb_value,cmd_value,dng_value);
|
||||
font->DrawString(buffer, SCREEN_WIDTH - 200 + rightTransition, SCREEN_HEIGHT / 2 + 15);
|
||||
|
||||
for (int j = 0; j < Constants::NB_Colors; j++)
|
||||
@@ -1625,6 +1705,12 @@ int GameStateDeckViewer::loadDeck(int deckid)
|
||||
SAFE_DELETE(myCommandZone->parent);
|
||||
SAFE_DELETE(myCommandZone);
|
||||
}
|
||||
//dng
|
||||
if (myDungeonZone)
|
||||
{
|
||||
SAFE_DELETE(myDungeonZone->parent);
|
||||
SAFE_DELETE(myDungeonZone);
|
||||
}
|
||||
//temp deck for sb?
|
||||
MTGDeck * sbtempDeck = NEW MTGDeck(MTGCollection());
|
||||
if(myDeck->parent)
|
||||
@@ -1707,10 +1793,52 @@ int GameStateDeckViewer::loadDeck(int deckid)
|
||||
myCollection->validate();
|
||||
}
|
||||
//endcmd
|
||||
//temp deck for dng?
|
||||
MTGDeck * dngtempDeck = NEW MTGDeck(MTGCollection());
|
||||
if(myDeck->parent)
|
||||
{//add cards from commanders lists
|
||||
if(myDeck->parent->DungeonZone.size())
|
||||
{
|
||||
for(unsigned int j = 0; j < myDeck->parent->DungeonZone.size(); j++)
|
||||
{
|
||||
string cardID = myDeck->parent->DungeonZone[j];
|
||||
dngtempDeck->add(atoi(cardID.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
myDungeonZone = NEW DeckDataWrapper(dngtempDeck);
|
||||
for (int i = 0; i < myDungeonZone->Size(true); i++)
|
||||
{
|
||||
MTGCard * current = myDungeonZone->getCard(i, true);
|
||||
int howmanyinDeck = myDungeonZone->count(current);
|
||||
for (int i = myCollection->count(current); i < howmanyinDeck; i++)
|
||||
{
|
||||
cPure = false;
|
||||
if (cheatmode)
|
||||
{ //Are we cheating?
|
||||
playerdata->collection->add(current); //Yup, add it to collection permanently.
|
||||
myCollection->Add(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
myDungeonZone->Remove(current,howmanyinDeck-i); //Nope. Remove it from sb.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
myCollection->Remove(current, myDungeonZone->count(current));
|
||||
}
|
||||
if (!cPure)
|
||||
{
|
||||
myDungeonZone->validate();
|
||||
myCollection->validate();
|
||||
}
|
||||
//enddng
|
||||
|
||||
myDeck->Sort(WSrcCards::SORT_ALPHA);
|
||||
mySideboard->Sort(WSrcCards::SORT_ALPHA);
|
||||
myCommandZone->Sort(WSrcCards::SORT_ALPHA);
|
||||
myDungeonZone->Sort(WSrcCards::SORT_ALPHA);
|
||||
SAFE_DELETE(filterMenu);
|
||||
rebuildFilters();
|
||||
mView->reloadIndexes();
|
||||
@@ -1877,6 +2005,14 @@ void GameStateDeckViewer::ButtonPressed(int controllerId, int controlId)
|
||||
sbMenu->Close();
|
||||
break;
|
||||
}
|
||||
case SBMENU_ADD_DNG:
|
||||
{
|
||||
MTGCard * card = mView->getActiveCard();
|
||||
if (card)
|
||||
DNGaddRemove(card);
|
||||
sbMenu->Close();
|
||||
break;
|
||||
}
|
||||
case SBMENU_ADD_CANCEL:
|
||||
sbMenu->Close();
|
||||
break;
|
||||
|
||||
@@ -147,7 +147,7 @@ GameState(parent, "duel")
|
||||
menu = NULL;
|
||||
popupScreen = NULL;
|
||||
mGamePhase = DUEL_STATE_UNSET;
|
||||
taskList = NEW TaskList(options.profileFile(PLAYER_TASKS).c_str());
|
||||
taskList = NEW TaskList();
|
||||
|
||||
#ifdef TESTSUITE
|
||||
testSuite = NULL;
|
||||
@@ -190,6 +190,8 @@ void GameStateDuel::Start()
|
||||
OpponentsDeckid = 0;
|
||||
bool createDeckMenu=true; // create only a deckmenu if not in tournament
|
||||
|
||||
SAFE_DELETE(taskList);
|
||||
taskList = NEW TaskList();
|
||||
|
||||
#ifdef NETWORK_SUPPORT
|
||||
if(!mParent->mpNetwork) {
|
||||
@@ -358,6 +360,7 @@ void GameStateDuel::End()
|
||||
SAFE_DELETE(opponentMenu);
|
||||
SAFE_DELETE(deckmenu);
|
||||
SAFE_DELETE(popupScreen);
|
||||
SAFE_DELETE(taskList);
|
||||
|
||||
//reset player for next match (only if actual match is finished)
|
||||
tournament->End();
|
||||
@@ -1682,7 +1685,6 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
|
||||
// break;
|
||||
case MENUITEM_TASKBOARD:
|
||||
if(taskList->getState() != TaskList::TASKS_ACTIVE){
|
||||
taskList->load(options.profileFile(PLAYER_TASKS).c_str());
|
||||
taskList->Start();
|
||||
} else {
|
||||
taskList->End();
|
||||
|
||||
+170
-20
@@ -1245,12 +1245,33 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "explored", card))
|
||||
return NEW TrCardExplored(observer, id, card, tc, once, limitOnceATurn);
|
||||
|
||||
//Dungeon has been completer from a card
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "dungeoncompleted", card)){
|
||||
int totaldng = 0;
|
||||
vector<string>res = parseBetween(s, "total(",")");
|
||||
if(res.size()){
|
||||
totaldng = atoi(res[1].c_str());
|
||||
}
|
||||
string playerName = "";
|
||||
vector<string>from = parseBetween(s, "from(",")");
|
||||
if(from.size() && from[1] == "opponent"){
|
||||
playerName = card->controller()->opponent()->getDisplayName();
|
||||
} else if(from.size() && from[1] == "controller"){
|
||||
playerName = card->controller()->getDisplayName();
|
||||
}
|
||||
return NEW TrCardDungeonCompleted(observer, id, card, tc, once, limitOnceATurn, totaldng, playerName);
|
||||
}
|
||||
|
||||
//Roll die has been performed from a card
|
||||
if (TargetChooser * tc = parseSimpleTC(s, "dierolled", card)){
|
||||
int rollresult = 0;
|
||||
vector<string>res = parseBetween(s, "result(",")");
|
||||
if(res.size()){
|
||||
rollresult = atoi(res[1].c_str());
|
||||
if(res[1] == "max"){
|
||||
rollresult = -1;
|
||||
} else {
|
||||
rollresult = atoi(res[1].c_str());
|
||||
}
|
||||
}
|
||||
string playerName = "";
|
||||
vector<string>from = parseBetween(s, "from(",")");
|
||||
@@ -1824,6 +1845,10 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
{
|
||||
size_t pos1 = s.find("transforms(("); // Try to handle pay ability inside ability$! or transforms keywords.
|
||||
size_t pos2 = s.find("ability$!");
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("winability"); // Try to handle pay ability inside winability or loseability keywords.
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("loseability");
|
||||
vector<string> splitMayPaystr = parseBetween(s, "pay(", ")", true);
|
||||
if((pos1 == string::npos && pos2 == string::npos) || (pos2 != string::npos && pos1 != string::npos && found < pos1 && found < pos2) ||
|
||||
(pos2 == string::npos && pos1 != string::npos && found < pos1) || (pos1 == string::npos && pos2 != string::npos && found < pos2)){
|
||||
@@ -1844,9 +1869,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
storedAbilityString = splitGrant[1];
|
||||
size_t pos1 = s.find("transforms(("); // Try to handle grant ability inside ability$! or transforms keywords.
|
||||
size_t pos2 = s.find("ability$!");
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("winability"); // Try to handle grant ability inside winability or loseability keywords.
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("loseability");
|
||||
size_t pos3 = s.find(splitGrant[1]);
|
||||
if((pos1 == string::npos && pos2 == string::npos) || (pos2 != string::npos && pos1 != string::npos && pos3 < pos1 && pos3 < pos2) ||
|
||||
(pos2 == string::npos && pos1 != string::npos && pos3 < pos1) || (pos1 == string::npos && pos2 != string::npos && pos3 < pos2)){
|
||||
if((pos1 == string::npos && pos2 == string::npos) || (pos2 != string::npos && pos1 != string::npos && pos3 <= pos1 && pos3 <= pos2) ||
|
||||
(pos2 == string::npos && pos1 != string::npos && pos3 <= pos1) || (pos1 == string::npos && pos2 != string::npos && pos3 <= pos2)){
|
||||
s = splitGrant[0];
|
||||
s.append("grant ");
|
||||
s.append(splitGrant[2]);
|
||||
@@ -1860,9 +1889,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
storedAbilityString = splitRevealx[1];
|
||||
size_t pos1 = s.find("transforms(("); // Try to handle reveal ability inside ability$! or transforms keywords.
|
||||
size_t pos2 = s.find("ability$!");
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("winability"); // Try to handle reveal ability inside winability or loseability keywords.
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("loseability");
|
||||
size_t pos3 = s.find(splitRevealx[1]);
|
||||
if((pos1 == string::npos && pos2 == string::npos) || (pos2 != string::npos && pos1 != string::npos && pos3 < pos1 && pos3 < pos2) ||
|
||||
(pos2 == string::npos && pos1 != string::npos && pos3 < pos1) || (pos1 == string::npos && pos2 != string::npos && pos3 < pos2)){
|
||||
if((pos1 == string::npos && pos2 == string::npos) || (pos2 != string::npos && pos1 != string::npos && pos3 <= pos1 && pos3 <= pos2) ||
|
||||
(pos2 == string::npos && pos1 != string::npos && pos3 <= pos1) || (pos1 == string::npos && pos2 != string::npos && pos3 <= pos2)){
|
||||
s = splitRevealx[0];
|
||||
s.append("reveal: ");
|
||||
s.append(splitRevealx[2]);
|
||||
@@ -1876,9 +1909,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
storedAbilityString = splitScryx[1];
|
||||
size_t pos1 = s.find("transforms(("); // Try to handle scry ability inside ability$! or transforms keywords.
|
||||
size_t pos2 = s.find("ability$!");
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("winability"); // Try to handle scry ability inside winability or loseability keywords.
|
||||
if(pos2 == string::npos)
|
||||
pos2 = s.find("loseability");
|
||||
size_t pos3 = s.find(splitScryx[1]);
|
||||
if((pos1 == string::npos && pos2 == string::npos) || (pos2 != string::npos && pos1 != string::npos && pos3 < pos1 && pos3 < pos2) ||
|
||||
(pos2 == string::npos && pos1 != string::npos && pos3 < pos1) || (pos1 == string::npos && pos2 != string::npos && pos3 < pos2)){
|
||||
if((pos1 == string::npos && pos2 == string::npos) || (pos2 != string::npos && pos1 != string::npos && pos3 <= pos1 && pos3 <= pos2) ||
|
||||
(pos2 == string::npos && pos1 != string::npos && pos3 <= pos1) || (pos1 == string::npos && pos2 != string::npos && pos3 <= pos2)){
|
||||
s = splitScryx[0];
|
||||
s.append("scry: ");
|
||||
s.append(splitScryx[2]);
|
||||
@@ -1890,6 +1927,10 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
if (found != string::npos && storedString.empty())
|
||||
{
|
||||
size_t pos1 = s.find("ability$!"); // Try to handle transforms ability inside ability$! keyword.
|
||||
if(pos1 == string::npos)
|
||||
pos1 = s.find("winability"); // Try to handle transforms ability inside winability or loseability keywords.
|
||||
if(pos1 == string::npos)
|
||||
pos1 = s.find("loseability");
|
||||
if(pos1 == string::npos || found < pos1){
|
||||
size_t real_end = s.find("))", found);
|
||||
size_t stypesStartIndex = found + 12;
|
||||
@@ -2687,13 +2728,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return a;
|
||||
}
|
||||
|
||||
//Phase based actions
|
||||
found = s.find("phaseaction");
|
||||
if (found != string::npos)
|
||||
{
|
||||
return parsePhaseActionAbility(s,card,spell,target,restrictions,id);
|
||||
}
|
||||
|
||||
//flip a coin
|
||||
vector<string> splitFlipCoin = parseBetween(s, "flipacoin ", " flipend");
|
||||
if (splitFlipCoin.size())
|
||||
@@ -2705,22 +2739,124 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return a;
|
||||
}
|
||||
|
||||
//roll a die
|
||||
vector<string> splitRollDie = parseBetween(s, "rolladie ", " rollend");
|
||||
if (splitRollDie.size())
|
||||
//roll a d4 die
|
||||
vector<string> splitRollD4 = parseBetween(s, "rolld4 ", " rolld4end");
|
||||
if (splitRollD4.size())
|
||||
{
|
||||
string a1 = splitRollDie[1];
|
||||
string a1 = splitRollD4[1];
|
||||
int userchoice = 0;
|
||||
if(a1[0] >= 48 && a1[0] <= 57){
|
||||
userchoice = a1[0] - 48;
|
||||
userchoice = (a1[0] - 48);
|
||||
a1 = a1.substr(2);
|
||||
}
|
||||
MTGAbility * a = NEW GenericRollDie(observer, id, card, target, a1, NULL, userchoice);
|
||||
MTGAbility * a = NEW GenericRollDie(observer, id, card, target, a1, NULL, userchoice, 4);
|
||||
a->oneShot = 1;
|
||||
a->canBeInterrupted = false;
|
||||
return a;
|
||||
}
|
||||
|
||||
//roll a d6 die
|
||||
vector<string> splitRollD6 = parseBetween(s, "rolld6 ", " rolld6end");
|
||||
if (splitRollD6.size())
|
||||
{
|
||||
string a1 = splitRollD6[1];
|
||||
int userchoice = 0;
|
||||
if(a1[0] >= 48 && a1[0] <= 57){
|
||||
userchoice = (a1[0] - 48);
|
||||
a1 = a1.substr(2);
|
||||
}
|
||||
MTGAbility * a = NEW GenericRollDie(observer, id, card, target, a1, NULL, userchoice, 6);
|
||||
a->oneShot = 1;
|
||||
a->canBeInterrupted = false;
|
||||
return a;
|
||||
}
|
||||
|
||||
//roll a d8 die
|
||||
vector<string> splitRollD8 = parseBetween(s, "rolld8 ", " rolld8end");
|
||||
if (splitRollD8.size())
|
||||
{
|
||||
string a1 = splitRollD8[1];
|
||||
int userchoice = 0;
|
||||
if(a1[0] >= 48 && a1[0] <= 57){
|
||||
userchoice = (a1[0] - 48);
|
||||
a1 = a1.substr(2);
|
||||
}
|
||||
MTGAbility * a = NEW GenericRollDie(observer, id, card, target, a1, NULL, userchoice, 8);
|
||||
a->oneShot = 1;
|
||||
a->canBeInterrupted = false;
|
||||
return a;
|
||||
}
|
||||
|
||||
//roll a d10 die
|
||||
vector<string> splitRollD10 = parseBetween(s, "rolld10 ", " rolld10end");
|
||||
if (splitRollD10.size())
|
||||
{
|
||||
string a1 = splitRollD10[1];
|
||||
int userchoice = 0;
|
||||
if(a1[0] >= 48 && a1[0] <= 57){
|
||||
if(a1[1] >= 48 && a1[1] <= 57){
|
||||
userchoice = (a1[0] - 48)*10 + (a1[1] - 48);
|
||||
a1 = a1.substr(3);
|
||||
} else {
|
||||
userchoice = (a1[0] - 48);
|
||||
a1 = a1.substr(2);
|
||||
}
|
||||
}
|
||||
MTGAbility * a = NEW GenericRollDie(observer, id, card, target, a1, NULL, userchoice, 10);
|
||||
a->oneShot = 1;
|
||||
a->canBeInterrupted = false;
|
||||
return a;
|
||||
}
|
||||
|
||||
//roll a d12 die
|
||||
vector<string> splitRollD12 = parseBetween(s, "rolld12 ", " rolld12end");
|
||||
if (splitRollD12.size())
|
||||
{
|
||||
string a1 = splitRollD12[1];
|
||||
int userchoice = 0;
|
||||
if(a1[0] >= 48 && a1[0] <= 57){
|
||||
if(a1[1] >= 48 && a1[1] <= 57){
|
||||
userchoice = (a1[0] - 48)*10 + (a1[1] - 48);
|
||||
a1 = a1.substr(3);
|
||||
} else {
|
||||
userchoice = (a1[0] - 48);
|
||||
a1 = a1.substr(2);
|
||||
}
|
||||
}
|
||||
MTGAbility * a = NEW GenericRollDie(observer, id, card, target, a1, NULL, userchoice, 12);
|
||||
a->oneShot = 1;
|
||||
a->canBeInterrupted = false;
|
||||
return a;
|
||||
}
|
||||
|
||||
//roll a d20 die
|
||||
vector<string> splitRollD20 = parseBetween(s, "rolld20 ", " rolld20end");
|
||||
if (splitRollD20.size())
|
||||
{
|
||||
string a1 = splitRollD20[1];
|
||||
int userchoice = 0;
|
||||
if(a1[0] >= 48 && a1[0] <= 57){
|
||||
if(a1[1] >= 48 && a1[1] <= 57){
|
||||
userchoice = (a1[0] - 48)*10 + (a1[1] - 48);
|
||||
a1 = a1.substr(3);
|
||||
} else {
|
||||
userchoice = (a1[0] - 48);
|
||||
a1 = a1.substr(2);
|
||||
}
|
||||
}
|
||||
MTGAbility * a = NEW GenericRollDie(observer, id, card, target, a1, NULL, userchoice, 20);
|
||||
a->oneShot = 1;
|
||||
a->canBeInterrupted = false;
|
||||
return a;
|
||||
}
|
||||
|
||||
//Phase based actions
|
||||
found = s.find("phaseaction");
|
||||
if (found != string::npos)
|
||||
{
|
||||
return parsePhaseActionAbility(s,card,spell,target,restrictions,id);
|
||||
}
|
||||
|
||||
//may pay ability
|
||||
vector<string> splitMayPaysub = parseBetween(s, "pay[[","]]", true);
|
||||
if (splitMayPaysub.size())
|
||||
@@ -3554,6 +3690,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return a;
|
||||
}
|
||||
|
||||
//alter dungeon completed
|
||||
vector<string> splitDungeonCompleted = parseBetween(s, "completedungeon:", " ", false);
|
||||
if (splitDungeonCompleted.size())
|
||||
{
|
||||
int dungeoncompleted = atoi(splitDungeonCompleted[1].c_str());
|
||||
Targetable * t = spell ? spell->getNextTarget() : NULL;
|
||||
MTGAbility * a = NEW AAAlterDungeonCompleted(observer, id, card, t, dungeoncompleted, NULL, who);
|
||||
a->oneShot = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
//alter yidaro counter
|
||||
vector<string> splitYidaroCounter = parseBetween(s, "alteryidarocount:", " ", false);
|
||||
if (splitYidaroCounter.size())
|
||||
@@ -4312,6 +4459,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
if (splitMeldFrom[1].size())
|
||||
{
|
||||
splitMeldNames = splitMeldFrom[1];
|
||||
replace(splitMeldNames.begin(), splitMeldNames.end(), '^', ','); // To allow the usage of ^ instead of , char (e.g. using meldfrom keyword inside transforms)
|
||||
}
|
||||
MTGAbility * a = NEW AAMeldFrom(observer, id, card, target, splitMeldNames);
|
||||
a->oneShot = true;
|
||||
@@ -4326,6 +4474,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
if (splitMeld[1].size())
|
||||
{
|
||||
splitMeldName = splitMeld[1];
|
||||
replace(splitMeldName.begin(), splitMeldName.end(), '^', ','); // To allow the usage of ^ instead of , char (e.g. using meld keyword inside transforms)
|
||||
}
|
||||
MTGAbility * a = NEW AAMeld(observer, id, card, target, splitMeldName);
|
||||
a->oneShot = true;
|
||||
@@ -5135,6 +5284,7 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ
|
||||
badAbilities[(int)Constants::HANDDEATH] = true;
|
||||
badAbilities[(int)Constants::GAINEDHANDDEATH] = true;
|
||||
badAbilities[(int)Constants::INPLAYDEATH] = true;
|
||||
badAbilities[(int)Constants::COUNTERDEATH] = true;
|
||||
badAbilities[(int)Constants::INPLAYTAPDEATH] = true;
|
||||
badAbilities[(int)Constants::DOUBLEFACEDEATH] = true;
|
||||
badAbilities[(int)Constants::GAINEDDOUBLEFACEDEATH] = true;
|
||||
|
||||
@@ -267,6 +267,7 @@ void MTGCardInstance::initMTGCI()
|
||||
lastFlipResult = -1;
|
||||
dieSide = 0;
|
||||
lastRollResult = 0;
|
||||
dieNumFaces = 0;
|
||||
scryedCards = 0;
|
||||
isAttacking = NULL;
|
||||
storedCard = NULL;
|
||||
@@ -529,9 +530,14 @@ int MTGCardInstance::toGrave( bool forced )
|
||||
}
|
||||
if (basicAbilities[(int)Constants::INPLAYDEATH] || basicAbilities[(int)Constants::INPLAYTAPDEATH])
|
||||
{
|
||||
p->game->putInZone(this, p->game->inPlay, owner->game->battlefield);
|
||||
if(basicAbilities[(int)Constants::INPLAYTAPDEATH])
|
||||
tap(true);
|
||||
bool toTap = basicAbilities[(int)Constants::INPLAYTAPDEATH];
|
||||
bool addCounter = basicAbilities[(int)Constants::COUNTERDEATH];
|
||||
MTGCardInstance* ret = p->game->putInZone(this, p->game->inPlay, owner->game->graveyard);
|
||||
ret = p->game->putInZone(ret, owner->game->graveyard, owner->game->battlefield);
|
||||
if(toTap)
|
||||
ret->tap(true);
|
||||
if(addCounter)
|
||||
ret->counters->addCounter(1, 1, false);
|
||||
return 1;
|
||||
}
|
||||
if (!basicAbilities[(int)Constants::INDESTRUCTIBLE])
|
||||
@@ -1028,6 +1034,9 @@ bool MTGCardInstance::canPlayFromLibrary()
|
||||
if(isSorceryorInstant() && (has(Constants::CANPLAYINSTANTSORCERYTOPLIBRARY)
|
||||
|| (controller()->game->inPlay->nb_cards && controller()->game->inPlay->hasAbility(Constants::CANPLAYINSTANTSORCERYTOPLIBRARY))))
|
||||
found++;
|
||||
if((hasSubtype(Subtypes::TYPE_EQUIPMENT) || hasSubtype(Subtypes::TYPE_AURA)) && (has(Constants::CANPLAYAURAEQUIPTOPLIBRARY)
|
||||
|| (controller()->game->inPlay->nb_cards && controller()->game->inPlay->hasAbility(Constants::CANPLAYAURAEQUIPTOPLIBRARY))))
|
||||
found++;
|
||||
|
||||
if(found > 0)
|
||||
return true;
|
||||
|
||||
@@ -920,9 +920,11 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on
|
||||
s.erase(0, s.find_first_not_of("\t\n\v\f\r "));
|
||||
std::string::const_iterator it = s.begin();
|
||||
while (it != s.end() && std::isdigit(*it)) ++it;
|
||||
if(!s.empty() && it == s.end())
|
||||
Sideboard.push_back(s);
|
||||
else {
|
||||
if(!s.empty() && it == s.end()){
|
||||
MTGCard * card = database->getCardById(atoi(s.c_str()));
|
||||
if(card && !card->data->hasType("Dungeon")) // To add Dungeons in Sideboard you need to use #DNG tag.
|
||||
Sideboard.push_back(s);
|
||||
} else {
|
||||
int numberOfCopies = 1;
|
||||
size_t found = s.find(" *");
|
||||
if (found != string::npos){
|
||||
@@ -934,9 +936,10 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on
|
||||
for (int i = 0; i < numberOfCopies; i++){
|
||||
std::stringstream str_id;
|
||||
str_id << card->getId();
|
||||
Sideboard.push_back(str_id.str());
|
||||
if(!card->data->hasType("Dungeon")) // To add Dungeons in Sideboard you need to use #DNG tag.
|
||||
Sideboard.push_back(str_id.str());
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
DebugTrace("could not add to Sideboard any card with name: " << s);
|
||||
}
|
||||
}
|
||||
@@ -963,7 +966,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on
|
||||
CommandZone.push_back(s);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
size_t found = s.find(" *");
|
||||
if (found != string::npos)
|
||||
s = s.substr(0, found);
|
||||
@@ -980,12 +983,61 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on
|
||||
CommandZone.push_back(str_id.str());
|
||||
}
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
DebugTrace("could not add to CommandZone any card with name: " << s);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
found = s.find("DNG:"); // Now it's possible to add Dungeons even using their Name instead of ID such as normal deck cards.
|
||||
if (found != string::npos)
|
||||
{
|
||||
if(!database) continue;
|
||||
s = s.substr(found + 4);
|
||||
s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1);
|
||||
s.erase(0, s.find_first_not_of("\t\n\v\f\r "));
|
||||
std::string::const_iterator it = s.begin();
|
||||
while (it != s.end() && std::isdigit(*it)) ++it;
|
||||
if(!s.empty() && it == s.end()){
|
||||
MTGCard * newcard = database->getCardById(atoi(s.c_str()));
|
||||
if(!DungeonZone.size() && newcard && newcard->data->hasType("Dungeon") && newcard->getRarity() == Constants::RARITY_T) // If no dungeon has been added you can add one.
|
||||
DungeonZone.push_back(s);
|
||||
else if(DungeonZone.size() > 0 && newcard && newcard->data->hasType("Dungeon") && newcard->getRarity() == Constants::RARITY_T){ // Try to add the dungeon.
|
||||
bool found = false;
|
||||
for(unsigned int i = 0; i < DungeonZone.size(); i++){
|
||||
MTGCard * oldcard = database->getCardById(atoi((DungeonZone.at(i)).c_str()));
|
||||
if(oldcard && oldcard->data->name == newcard->data->name)
|
||||
found = true;
|
||||
}
|
||||
if(!found)
|
||||
DungeonZone.push_back(s);
|
||||
}
|
||||
} else {
|
||||
size_t found = s.find(" *");
|
||||
if (found != string::npos)
|
||||
s = s.substr(0, found);
|
||||
MTGCard * newcard = database->getCardByName(s);
|
||||
if (newcard){
|
||||
std::stringstream str_id;
|
||||
str_id << newcard->getId();
|
||||
if(!DungeonZone.size() && newcard && newcard->data->hasType("Dungeon") && newcard->getRarity() == Constants::RARITY_T) // If no dungeon has been added you can add one.
|
||||
DungeonZone.push_back(str_id.str());
|
||||
else if(DungeonZone.size() > 0 && newcard && newcard->data->hasType("Dungeon") && newcard->getRarity() == Constants::RARITY_T){ // Try to add the dungeon.
|
||||
bool found = false;
|
||||
for(unsigned int i = 0; i < DungeonZone.size() && !found; i++){
|
||||
MTGCard * oldcard = database->getCardById(atoi((DungeonZone.at(i)).c_str()));
|
||||
if(oldcard && oldcard->data->name == newcard->data->name)
|
||||
found = true;
|
||||
}
|
||||
if(!found)
|
||||
DungeonZone.push_back(str_id.str());
|
||||
}
|
||||
} else {
|
||||
DebugTrace("could not add to Dungeons any card with name: " << s);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (meta_only) continue; //Changed from break in order to read the command tag in metafile.
|
||||
@@ -1227,6 +1279,16 @@ void MTGDeck::replaceCMD(vector<string> newCMD)
|
||||
return;
|
||||
}
|
||||
|
||||
void MTGDeck::replaceDNG(vector<string> newDMG)
|
||||
{
|
||||
if(newDMG.size())
|
||||
{
|
||||
DungeonZone.clear();
|
||||
DungeonZone = newDMG;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int MTGDeck::remove(int cardid)
|
||||
{
|
||||
if (cards.find(cardid) == cards.end() || cards[cardid] == 0) return 0;
|
||||
@@ -1318,6 +1380,17 @@ int MTGDeck::save(const string& destFileName, bool useExpandedDescriptions, cons
|
||||
file << "#CMD:" << checkID << "\n";
|
||||
}
|
||||
}
|
||||
//save dungeons
|
||||
if(DungeonZone.size())
|
||||
{
|
||||
sort(DungeonZone.begin(), DungeonZone.end());
|
||||
for(unsigned int k = 0; k < DungeonZone.size(); k++)
|
||||
{
|
||||
int checkID = atoi(DungeonZone[k].c_str());
|
||||
if(checkID)
|
||||
file << "#DNG:" << checkID << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
JFileSystem::GetInstance()->Rename(tmp, destFileName);
|
||||
|
||||
@@ -214,7 +214,13 @@ const char* Constants::MTGBasicAbilities[] = {
|
||||
"undamageable", //It cannot be damaged by any source
|
||||
"lifefaker", //It's a card wich modify the life increasement when a @lifeof triggers occours (e.g. Angel of Vitality)
|
||||
"doublefacedeath", //It goes to temp zone after death (e.g. Double face card)
|
||||
"gaineddoublefacedeath" //It goes to temp after death (use just to give add ability to instants and sorceries which originally have not, e.g. with transforms keyword)
|
||||
"gaineddoublefacedeath", //It goes to temp after death (use just to give add ability to instants and sorceries which originally have not, e.g. with transforms keyword)
|
||||
"twodngtrg", //It makes rooms abilities trigger twice (e.g. Hama Pashar, Ruin Seeker)
|
||||
"nodngopp", //Opponent can't venture (e.g. "Keen-Eared Sentry")
|
||||
"nodngplr", //Controller can't venture
|
||||
"canplayauraequiplibrarytop", //auras and equipment
|
||||
"counterdeath", //It gains a 1/1 counter when it returns from graveyard (to use with inplaydeath and inplaytapdeath)"
|
||||
"dungeoncompleted" //This dungeon has been completed
|
||||
};
|
||||
|
||||
map<string,int> Constants::MTGBasicAbilitiesMap;
|
||||
|
||||
@@ -145,6 +145,21 @@ void MTGPlayerCards::initDeck(MTGDeck * deck)
|
||||
}
|
||||
}
|
||||
}
|
||||
//dungeon init
|
||||
if(deck->DungeonZone.size())
|
||||
{
|
||||
for(unsigned int j = 0; j < deck->DungeonZone.size(); j++)
|
||||
{
|
||||
string cardID = deck->DungeonZone[j];
|
||||
MTGCard * card = MTGCollection()->getCardById(atoi(cardID.c_str()));
|
||||
if(card)
|
||||
{
|
||||
MTGCardInstance * newCard = NEW MTGCardInstance(card, this);
|
||||
//Dungeons will be added to sideboard zone...
|
||||
sideboard->addCard(newCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MTGPlayerCards::~MTGPlayerCards()
|
||||
@@ -412,14 +427,25 @@ MTGCardInstance * MTGPlayerCards::putInGraveyard(MTGCardInstance * card)
|
||||
}
|
||||
else if (card->getCurrentZone() != card->controller()->game->hand && (card->basicAbilities[(int)Constants::INPLAYDEATH] || card->basicAbilities[(int)Constants::INPLAYTAPDEATH]))
|
||||
{
|
||||
MTGCardInstance* ret = putInZone(card, card->getCurrentZone(), card->owner->game->battlefield);
|
||||
if(card->basicAbilities[(int)Constants::INPLAYTAPDEATH])
|
||||
bool toTap = card->basicAbilities[(int)Constants::INPLAYTAPDEATH];
|
||||
bool addCounter = card->basicAbilities[(int)Constants::COUNTERDEATH];
|
||||
MTGCardInstance* ret = putInZone(card, card->getCurrentZone(), card->owner->game->graveyard);
|
||||
ret = putInZone(ret, ret->getCurrentZone(), ret->owner->game->battlefield);
|
||||
if(toTap)
|
||||
ret->tap(true);
|
||||
if(addCounter)
|
||||
ret->counters->addCounter(1, 1, false);
|
||||
return ret;
|
||||
}
|
||||
return putInZone(card, card->currentZone, card->owner->game->graveyard);
|
||||
}
|
||||
|
||||
// Moves a card to its owner's sideboard
|
||||
MTGCardInstance * MTGPlayerCards::putInSideboard(MTGCardInstance * card)
|
||||
{
|
||||
return putInZone(card, card->currentZone, card->owner->game->sideboard);
|
||||
}
|
||||
|
||||
// Moves a card to its owner's exile
|
||||
MTGCardInstance * MTGPlayerCards::putInExile(MTGCardInstance * card)
|
||||
{
|
||||
@@ -836,6 +862,7 @@ MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card, int createCopy
|
||||
copy->basicAbilities[Constants::GAINEDEXILEDEATH] = card->basicAbilities[Constants::GAINEDEXILEDEATH];
|
||||
copy->basicAbilities[Constants::GAINEDHANDDEATH] = card->basicAbilities[Constants::GAINEDHANDDEATH];
|
||||
copy->basicAbilities[Constants::GAINEDDOUBLEFACEDEATH] = card->basicAbilities[Constants::GAINEDDOUBLEFACEDEATH];
|
||||
copy->basicAbilities[Constants::DUNGEONCOMPLETED] = card->basicAbilities[Constants::DUNGEONCOMPLETED];
|
||||
copy->damageInflictedAsCommander = card->damageInflictedAsCommander;
|
||||
copy->numofcastfromcommandzone = card->numofcastfromcommandzone;
|
||||
for (int i = 0; i < ManaCost::MANA_PAID_WITH_BESTOW +1; i++)
|
||||
|
||||
@@ -36,6 +36,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck *
|
||||
drawCounter = 0;
|
||||
energyCount = 0;
|
||||
yidaroCount = 0;
|
||||
dungeonCompleted = 0;
|
||||
numOfCommandCast = 0;
|
||||
monarch = 0;
|
||||
surveilOffset = 0;
|
||||
|
||||
@@ -603,6 +603,7 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet)
|
||||
p->preventable = initState.playerData[i].player->preventable;
|
||||
p->energyCount = initState.playerData[i].player->energyCount;
|
||||
p->yidaroCount = initState.playerData[i].player->yidaroCount;
|
||||
p->dungeonCompleted = initState.playerData[i].player->dungeonCompleted;
|
||||
p->numOfCommandCast = initState.playerData[i].player->numOfCommandCast;
|
||||
p->monarch = initState.playerData[i].player->monarch;
|
||||
p->surveilOffset = initState.playerData[i].player->surveilOffset;
|
||||
|
||||
@@ -317,6 +317,11 @@ WEventCardExplored::WEventCardExplored(MTGCardInstance * card) :
|
||||
{
|
||||
}
|
||||
|
||||
WEventCardDungeonCompleted::WEventCardDungeonCompleted(MTGCardInstance * card, int totaldng, string playerName) :
|
||||
WEventCardUpdate(card), totaldng(totaldng), playerName(playerName)
|
||||
{
|
||||
}
|
||||
|
||||
WEventCardRollDie::WEventCardRollDie(MTGCardInstance * card, string playerName) :
|
||||
WEventCardUpdate(card), playerName(playerName)
|
||||
{
|
||||
@@ -570,6 +575,12 @@ Targetable * WEventCardExplored::getTarget(int target)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventCardDungeonCompleted::getTarget(int target)
|
||||
{
|
||||
if (target) return card;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Targetable * WEventCardRollDie::getTarget(int target)
|
||||
{
|
||||
if (target) return card;
|
||||
|
||||
@@ -594,9 +594,21 @@ void WParsedInt::init(string s, Spell * spell, MTGCardInstance * card)
|
||||
{
|
||||
intValue = (s == "mypoisoncount")?target->controller()->poisonCount:target->controller()->opponent()->poisonCount;
|
||||
}
|
||||
else if(s == "lastrollresult" || s == "lastrollchoice")
|
||||
else if(s == "lastrollresult" || s == "lastrollchoice" || s == "lastdiefaces" || s == "srclastrollresult" || s == "srclastrollchoice" || s == "srclastdiefaces")
|
||||
{
|
||||
intValue = (s == "lastrollresult")?target->lastRollResult:target->dieSide;
|
||||
intValue = 0;
|
||||
if(s == "lastrollresult")
|
||||
intValue = target->lastRollResult;
|
||||
else if(s == "srclastrollresult")
|
||||
intValue = card->lastRollResult;
|
||||
else if(s == "lastrollchoice")
|
||||
intValue = target->dieSide;
|
||||
else if(s == "srclastrollchoice")
|
||||
intValue = card->dieSide;
|
||||
else if(s == "lastdiefaces")
|
||||
intValue = target->dieNumFaces;
|
||||
else if(s == "srclastdiefaces")
|
||||
intValue = card->dieNumFaces;
|
||||
}
|
||||
else if(s == "lastflipresult" || s == "lastflipchoice")
|
||||
{
|
||||
@@ -926,6 +938,31 @@ void WParsedInt::init(string s, Spell * spell, MTGCardInstance * card)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.find("cardcountabil") != string::npos)//Count Total cards with specific ability
|
||||
{
|
||||
intValue = 0;
|
||||
bool different_names = (s.find("diffcardcountabil")!=string::npos)?true:false;
|
||||
string ability = (s.find("diffcardcountabil")!=string::npos)?s.substr(17):s.substr(13);
|
||||
vector<string> list;
|
||||
for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->inPlay->cards[j]->basicAbilities[Constants::GetBasicAbilityIndex(ability)] == 1){
|
||||
if(!different_names)
|
||||
intValue += 1;
|
||||
else{
|
||||
bool name_found = false;
|
||||
for(unsigned int i = 0; i < list.size() && !name_found; i++){
|
||||
if(list[i] == card->controller()->game->inPlay->cards[j]->name)
|
||||
name_found = true;
|
||||
}
|
||||
if(!name_found){
|
||||
list.push_back(card->controller()->game->inPlay->cards[j]->name);
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.find("cardcounttype") != string::npos)//Count Total cards of specific type
|
||||
{
|
||||
intValue = 0;
|
||||
@@ -1222,6 +1259,50 @@ void WParsedInt::extendedParse(string s, Spell * spell, MTGCardInstance * card)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.find("totalmana") != string::npos)//find the cards with specified total mana in target player library
|
||||
{
|
||||
intValue = 0;
|
||||
bool opponent = (s.find("oppototalmana")!=string::npos)?true:false;
|
||||
int manavalue = atoi((s.find("oppototalmana")!=string::npos)?s.substr(13).c_str():s.substr(9).c_str());
|
||||
int totalmana = 0;
|
||||
Player* p = card->controller();
|
||||
if (opponent)
|
||||
p = card->controller()->opponent();
|
||||
for (int j = p->game->library->nb_cards - 1; j >= 0 && totalmana < manavalue; --j){
|
||||
totalmana += p->game->library->cards[j]->getManaCost()->getConvertedCost();
|
||||
intValue = p->game->library->nb_cards - j;
|
||||
}
|
||||
}
|
||||
else if (s == "pdungeoncompleted" || s == "odungeoncompleted")
|
||||
{
|
||||
intValue = (s == "pdungeoncompleted")?card->controller()->dungeonCompleted:card->controller()->opponent()->dungeonCompleted;
|
||||
}
|
||||
else if (s == "pwrtotatt" || s == "thstotatt")//count Total Power or toughness of attacking creatures (e.g. Battle Cry Goblin)
|
||||
{
|
||||
intValue = 0;
|
||||
for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE) && card->controller()->game->inPlay->cards[j]->attacker){
|
||||
if(s == "pwrtotatt")
|
||||
intValue += card->controller()->game->inPlay->cards[j]->getCurrentPower();
|
||||
else
|
||||
intValue += card->controller()->game->inPlay->cards[j]->getCurrentToughness();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s == "pwrtotblo" || s == "thstotblo")//count Total Power or toughness of blocking creatures
|
||||
{
|
||||
intValue = 0;
|
||||
for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE) && card->controller()->game->inPlay->cards[j]->defenser){
|
||||
if(s == "pwrtotblo")
|
||||
intValue += card->controller()->game->inPlay->cards[j]->getCurrentPower();
|
||||
else
|
||||
intValue += card->controller()->game->inPlay->cards[j]->getCurrentToughness();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!intValue)//found nothing, try parsing a atoi
|
||||
{
|
||||
intValue = atoi(s.c_str());
|
||||
|
||||
Reference in New Issue
Block a user