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:
Vittorio Alfieri
2021-07-17 02:33:08 +02:00
parent d98956a1b8
commit 31ab9edc81
43 changed files with 9693 additions and 1740 deletions
+7 -2
View File
@@ -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)
+59 -12
View File
@@ -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
+161 -25
View File
@@ -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;
+4 -2
View File
@@ -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
View File
@@ -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;
+12 -3
View File
@@ -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;
+80 -7
View File
@@ -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);
+7 -1
View File
@@ -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;
+29 -2
View File
@@ -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++)
+1
View File
@@ -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;
+1
View File
@@ -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;
+11
View File
@@ -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;
+83 -2
View File
@@ -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());