fix windswept_heath.txt missing choice 1, added unearth support without workaround, tweaked alternative cost, added treason/sneak attack ability, added frozen.
This commit is contained in:
@@ -11,6 +11,7 @@ library:Forest,Plains,Mountain,Swamp,Island
|
|||||||
[PLAYER2]
|
[PLAYER2]
|
||||||
[DO]
|
[DO]
|
||||||
Windswept Heath
|
Windswept Heath
|
||||||
|
choice 1
|
||||||
Plains
|
Plains
|
||||||
[ASSERT]
|
[ASSERT]
|
||||||
firstmain
|
firstmain
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ public:
|
|||||||
intValue = target->getManaCost()->getConvertedCost();
|
intValue = target->getManaCost()->getConvertedCost();
|
||||||
}else if (s == "lifetotal"){
|
}else if (s == "lifetotal"){
|
||||||
intValue = target->controller()->life;
|
intValue = target->controller()->life;
|
||||||
}else if (s == "sunburst"){
|
|
||||||
intValue = target->costAmount;
|
|
||||||
}else if (s == "odcount"){
|
}else if (s == "odcount"){
|
||||||
intValue = target->controller()->opponent()->damageCount;
|
intValue = target->controller()->opponent()->damageCount;
|
||||||
}else if (s == "opponentlifetotal"){
|
}else if (s == "opponentlifetotal"){
|
||||||
@@ -2330,6 +2328,32 @@ class AAUntapper:public ActivatedAbility{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Can prevent a card from untapping next untap */
|
||||||
|
class AAFrozen:public ActivatedAbility{
|
||||||
|
public:
|
||||||
|
AAFrozen(int id, MTGCardInstance * card, MTGCardInstance * _target,ManaCost * _cost = NULL, int doTap = 0):ActivatedAbility(id,card, _cost,0,doTap){
|
||||||
|
target = _target;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolve(){
|
||||||
|
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||||
|
if (_target){
|
||||||
|
while (_target->next) _target=_target->next; //This is for cards such as rampant growth
|
||||||
|
_target->frozen += 1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * getMenuText(){
|
||||||
|
return "Freeze";
|
||||||
|
}
|
||||||
|
|
||||||
|
AAFrozen * clone() const{
|
||||||
|
AAFrozen * a = NEW AAFrozen(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase]
|
// Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase]
|
||||||
//Ex : the rack, ivory tower...
|
//Ex : the rack, ivory tower...
|
||||||
|
|||||||
@@ -44,11 +44,10 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
|||||||
MTGGameZone * currentZone;
|
MTGGameZone * currentZone;
|
||||||
Pos* view;
|
Pos* view;
|
||||||
int X;
|
int X;
|
||||||
int costAmount;
|
int frozen;
|
||||||
int regenerateTokens;
|
int regenerateTokens;
|
||||||
int isToken;
|
int isToken;
|
||||||
int stillInUse();
|
int stillInUse();
|
||||||
int getCostAmount();
|
|
||||||
Player * lastController;
|
Player * lastController;
|
||||||
MTGGameZone * getCurrentZone();
|
MTGGameZone * getCurrentZone();
|
||||||
MTGGameZone * previousZone;
|
MTGGameZone * previousZone;
|
||||||
@@ -75,7 +74,7 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
|||||||
int removeType(int value, int removeAll = 0);
|
int removeType(int value, int removeAll = 0);
|
||||||
|
|
||||||
//Combat
|
//Combat
|
||||||
bool blocked; //Blocked this turn or not?
|
bool blocked; //Blocked this turn or not?
|
||||||
MTGCardInstance * defenser;
|
MTGCardInstance * defenser;
|
||||||
list<MTGCardInstance *>blockers;
|
list<MTGCardInstance *>blockers;
|
||||||
int attacker;
|
int attacker;
|
||||||
|
|||||||
@@ -111,8 +111,11 @@ class Constants
|
|||||||
WILTING = 53,
|
WILTING = 53,
|
||||||
VIGOR = 54,
|
VIGOR = 54,
|
||||||
CHANGELING = 55,
|
CHANGELING = 55,
|
||||||
|
ABSORB = 56,//this need to be coded for players too "If a source would deal damage"
|
||||||
|
TREASON = 57,
|
||||||
|
UNEARTH = 58,
|
||||||
|
|
||||||
NB_BASIC_ABILITIES = 56,
|
NB_BASIC_ABILITIES = 59,
|
||||||
|
|
||||||
|
|
||||||
RARITY_S = 'S', //Special Rarity
|
RARITY_S = 'S', //Special Rarity
|
||||||
|
|||||||
@@ -64,6 +64,23 @@ class MTGPersistRule:public MTGAbility{
|
|||||||
virtual MTGPersistRule * clone() const;
|
virtual MTGPersistRule * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MTGUnearthRule:public MTGAbility{
|
||||||
|
public:
|
||||||
|
MTGUnearthRule(int _id);
|
||||||
|
int receiveEvent(WEvent * event);
|
||||||
|
virtual ostream& toString(ostream& out) const;
|
||||||
|
int testDestroy();
|
||||||
|
virtual MTGUnearthRule * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MTGSneakAttackRule:public MTGAbility{
|
||||||
|
public:
|
||||||
|
MTGSneakAttackRule(int _id);
|
||||||
|
int receiveEvent(WEvent * event);
|
||||||
|
virtual ostream& toString(ostream& out) const;
|
||||||
|
int testDestroy();
|
||||||
|
virtual MTGSneakAttackRule * clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
class MTGTokensCleanup:public MTGAbility{
|
class MTGTokensCleanup:public MTGAbility{
|
||||||
public:
|
public:
|
||||||
@@ -146,7 +163,6 @@ class MTGDeathtouchRule:public MTGAbility{
|
|||||||
virtual MTGDeathtouchRule * clone() const;
|
virtual MTGDeathtouchRule * clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* HUD Display */
|
/* HUD Display */
|
||||||
|
|
||||||
class HUDString {
|
class HUDString {
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ int Damage::resolve(){
|
|||||||
target = ev->damage->target;
|
target = ev->damage->target;
|
||||||
if (!damage) return 0;
|
if (!damage) return 0;
|
||||||
|
|
||||||
|
//asorbing effects for cards controller-----------
|
||||||
|
|
||||||
|
//reserved for culmulitive absorb ability coding
|
||||||
|
|
||||||
//prevent next damage-----------------------------
|
//prevent next damage-----------------------------
|
||||||
if((target)->preventable >= 1) {
|
if((target)->preventable >= 1) {
|
||||||
int preventing =(target)->preventable;
|
int preventing =(target)->preventable;
|
||||||
@@ -71,6 +75,9 @@ int Damage::resolve(){
|
|||||||
damage = 0;
|
damage = 0;
|
||||||
(_target)->counters->removeCounter(1,1);
|
(_target)->counters->removeCounter(1,1);
|
||||||
}
|
}
|
||||||
|
if ((_target)->has(Constants::ABSORB)) {
|
||||||
|
damage -= 1;
|
||||||
|
}
|
||||||
if ((_target)->has(Constants::WILTING)) {
|
if ((_target)->has(Constants::WILTING)) {
|
||||||
for (int i = 0; i < damage; i++){
|
for (int i = 0; i < damage; i++){
|
||||||
for (int i = damage; i > 0; i--){
|
for (int i = damage; i > 0; i--){
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ void DuelLayers::init(){
|
|||||||
action->Add(NEW MTGBlockRule(-1));
|
action->Add(NEW MTGBlockRule(-1));
|
||||||
action->Add(NEW MTGLegendRule(-1));
|
action->Add(NEW MTGLegendRule(-1));
|
||||||
action->Add(NEW MTGPersistRule(-1));
|
action->Add(NEW MTGPersistRule(-1));
|
||||||
|
action->Add(NEW MTGUnearthRule(-1));
|
||||||
|
action->Add(NEW MTGSneakAttackRule(-1));
|
||||||
action->Add(NEW MTGLifelinkRule(-1));
|
action->Add(NEW MTGLifelinkRule(-1));
|
||||||
action->Add(NEW MTGDeathtouchRule(-1));
|
action->Add(NEW MTGDeathtouchRule(-1));
|
||||||
action->Add(NEW OtherAbilitiesEventReceiver(-1));
|
action->Add(NEW OtherAbilitiesEventReceiver(-1));
|
||||||
|
|||||||
@@ -114,7 +114,21 @@ void GameObserver::nextGamePhase(){
|
|||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
players[i]->getManaPool()->init();
|
players[i]->getManaPool()->init();
|
||||||
|
|
||||||
//After End of turn
|
// //End of turn--unearth clean up---leaving this as comment for code refference. origanal method i had for unearth now handled by sneakattackrule.
|
||||||
|
//if (currentGamePhase == Constants::MTG_PHASE_ENDOFTURN) {
|
||||||
|
// GameObserver *game = game->GetInstance();
|
||||||
|
// Player * p = game->currentPlayer;
|
||||||
|
// MTGGameZone * z = p->game->inPlay;
|
||||||
|
// for (int i= 0; i < z->nb_cards; i++){
|
||||||
|
// MTGCardInstance * card = z->cards[i];
|
||||||
|
//if (card->has(Constants::UNEARTH)) {
|
||||||
|
// for(i = z->nb_cards; i > -1; i--){
|
||||||
|
// card->controller()->game->putInExile(card);
|
||||||
|
//}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
if (currentGamePhase == Constants::MTG_PHASE_AFTER_EOT){
|
if (currentGamePhase == Constants::MTG_PHASE_AFTER_EOT){
|
||||||
//Auto Hand cleaning, in case the player didn't do it himself
|
//Auto Hand cleaning, in case the player didn't do it himself
|
||||||
while(currentPlayer->game->hand->nb_cards > 7)
|
while(currentPlayer->game->hand->nb_cards > 7)
|
||||||
@@ -465,12 +479,11 @@ int GameObserver::untap(MTGCardInstance * card) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (card->has(Constants::DOESNOTUNTAP)) return 0;
|
if (card->has(Constants::DOESNOTUNTAP)) return 0;
|
||||||
|
if (card->frozen > 0) return 0;
|
||||||
card->attemptUntap();
|
card->attemptUntap();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TargetChooser * GameObserver::getCurrentTargetChooser(){
|
TargetChooser * GameObserver::getCurrentTargetChooser(){
|
||||||
TargetChooser * _tc = mLayers->actionLayer()->getCurrentTargetChooser();
|
TargetChooser * _tc = mLayers->actionLayer()->getCurrentTargetChooser();
|
||||||
if (_tc) return _tc;
|
if (_tc) return _tc;
|
||||||
|
|||||||
@@ -1193,6 +1193,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//frozen, next untap this does not untap.
|
||||||
|
found = s.find("frozen");
|
||||||
|
if (found != string::npos){
|
||||||
|
MTGAbility * a = NEW AAFrozen(id,card,target);
|
||||||
|
a->oneShot = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
//Untapper (Ley Druid...)
|
//Untapper (Ley Druid...)
|
||||||
found = s.find("untap");
|
found = s.find("untap");
|
||||||
if (found != string::npos){
|
if (found != string::npos){
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ void MTGCardInstance::initMTGCI(){
|
|||||||
belongs_to=NULL;
|
belongs_to=NULL;
|
||||||
tapped = 0;
|
tapped = 0;
|
||||||
untapping = 0;
|
untapping = 0;
|
||||||
|
frozen = 0;
|
||||||
summoningSickness = 1;
|
summoningSickness = 1;
|
||||||
preventable = 0;
|
preventable = 0;
|
||||||
target = NULL;
|
target = NULL;
|
||||||
@@ -109,7 +110,6 @@ void MTGCardInstance::initMTGCI(){
|
|||||||
next = NULL;
|
next = NULL;
|
||||||
lastController = NULL;
|
lastController = NULL;
|
||||||
regenerateTokens = 0;
|
regenerateTokens = 0;
|
||||||
costAmount = 0;
|
|
||||||
blocked = false;
|
blocked = false;
|
||||||
currentZone = NULL;
|
currentZone = NULL;
|
||||||
data = this; //an MTGCardInstance point to itself for data, allows to update it without killing the underlying database item
|
data = this; //an MTGCardInstance point to itself for data, allows to update it without killing the underlying database item
|
||||||
@@ -297,10 +297,6 @@ int MTGCardInstance::hasSummoningSickness(){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MTGCardInstance::getCostAmount(){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MTGCardInstance * MTGCardInstance::changeController(Player * newController){
|
MTGCardInstance * MTGCardInstance::changeController(Player * newController){
|
||||||
Player * originalOwner = controller();
|
Player * originalOwner = controller();
|
||||||
if (originalOwner == newController) return this;
|
if (originalOwner == newController) return this;
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ const char* Constants::MTGBasicAbilities[] = {
|
|||||||
"wilting",//source takes damage in the form of -1/-1 counters.
|
"wilting",//source takes damage in the form of -1/-1 counters.
|
||||||
"vigor",//instead of taking damage the source gains +1/+1 counters
|
"vigor",//instead of taking damage the source gains +1/+1 counters
|
||||||
"changeling",//this card is every creature type at all times
|
"changeling",//this card is every creature type at all times
|
||||||
|
"absorb",//timeshifted sliver ability. if damage would be dealt to card, prevent 1 of that damage.
|
||||||
|
"treason",
|
||||||
|
"unearth",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -355,9 +355,11 @@ void MTGInPlay::untapAll(){
|
|||||||
for (i = 0; i < nb_cards; i ++){
|
for (i = 0; i < nb_cards; i ++){
|
||||||
MTGCardInstance * card = cards[i];
|
MTGCardInstance * card = cards[i];
|
||||||
card->setUntapping();
|
card->setUntapping();
|
||||||
if (!card->basicAbilities[Constants::DOESNOTUNTAP]){
|
if (!card->basicAbilities[Constants::DOESNOTUNTAP]){
|
||||||
card->attemptUntap();
|
if(card->frozen < 1) {card->attemptUntap();}
|
||||||
}
|
if(card->frozen >= 1) {card->frozen = 0;}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,8 @@ int cardsinhand = game->players[0]->game->hand->nb_cards;
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (playerMana->canAfford(cost)){
|
if (playerMana->canAfford(cost)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -53,19 +52,10 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){
|
|||||||
ManaCost * alternative = card->getManaCost()->alternative;
|
ManaCost * alternative = card->getManaCost()->alternative;
|
||||||
ManaCost * playerMana = player->getManaPool();
|
ManaCost * playerMana = player->getManaPool();
|
||||||
//this handles extra cost payments at the moment a card is played.
|
//this handles extra cost payments at the moment a card is played.
|
||||||
if (cost->isExtraPaymentSet()){
|
|
||||||
if (!game->targetListIsSet(card)){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
cost->setExtraCostsAction(this, card);
|
|
||||||
game->waitForExtraPayment = cost->extraCosts;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//as long as you dont have enough mana to pay the real cost, and the alternative contains extra cost, add extras
|
//as long as you dont have enough mana to pay the real cost, and the alternative contains extra cost, add extras
|
||||||
if(!playerMana->canAfford(cost) && playerMana->canAfford(alternative)){
|
if(!playerMana->canAfford(cost) && playerMana->canAfford(alternative)){
|
||||||
if (cost->alternative->isExtraPaymentSet()){
|
if (cost->alternative->isExtraPaymentSet()){
|
||||||
if (!game->targetListIsSet(card)){
|
if (!game->targetListIsSet(card)){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -76,6 +66,15 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
if (cost->isExtraPaymentSet()){
|
||||||
|
if (!game->targetListIsSet(card)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
cost->setExtraCostsAction(this, card);
|
||||||
|
game->waitForExtraPayment = cost->extraCosts;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
|
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
|
||||||
int payResult = player->getManaPool()->pay(card->getManaCost());
|
int payResult = player->getManaPool()->pay(card->getManaCost());
|
||||||
@@ -550,8 +549,80 @@ HUDDisplay::~HUDDisplay(){
|
|||||||
a->isClone = 1;
|
a->isClone = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
//unearth rule----------------------------------
|
||||||
|
//if the card leaves play, exile it instead.
|
||||||
|
MTGUnearthRule::MTGUnearthRule(int _id):MTGAbility(_id,NULL){};
|
||||||
|
|
||||||
|
int MTGUnearthRule::receiveEvent(WEvent * event){
|
||||||
|
if (event->type == WEvent::CHANGE_ZONE){
|
||||||
|
WEventZoneChange * e = (WEventZoneChange *) event;
|
||||||
|
MTGCardInstance * card = e->card->previous;
|
||||||
|
if (card && card->basicAbilities[Constants::UNEARTH]){
|
||||||
|
int ok = 0;
|
||||||
|
for (int i = 0; i < 2 ; i++){
|
||||||
|
Player * p = game->players[i];
|
||||||
|
if (e->from == p->game->inPlay) ok = 1;
|
||||||
|
}
|
||||||
|
if (!ok) return 0;
|
||||||
|
for (int i = 0; i < 2 ; i++){
|
||||||
|
Player * p = game->players[i];
|
||||||
|
if (e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library){
|
||||||
|
p->game->putInExile(e->card);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream& MTGUnearthRule::toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "MTGUnearthRule ::: (";
|
||||||
|
return MTGAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
int MTGUnearthRule::testDestroy(){return 0;}
|
||||||
|
MTGUnearthRule * MTGUnearthRule::clone() const{
|
||||||
|
MTGUnearthRule * a = NEW MTGUnearthRule(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
//sneakattack rule------------------------------------------------------
|
||||||
|
//this rule also handles the exile of unearth cards at end of turn.
|
||||||
|
|
||||||
|
MTGSneakAttackRule::MTGSneakAttackRule(int _id):MTGAbility(_id,NULL){};
|
||||||
|
|
||||||
|
int MTGSneakAttackRule::receiveEvent(WEvent *e){
|
||||||
|
if (WEventPhaseChange* event = dynamic_cast<WEventPhaseChange*>(e)) {
|
||||||
|
if (Constants::MTG_PHASE_ENDOFTURN == event->from->id) {
|
||||||
|
for (int j = 0; j < 2 ; j++){
|
||||||
|
Player * p = game->players[j];
|
||||||
|
MTGGameZone * z = p->game->inPlay;
|
||||||
|
for (int i= 0; i < z->nb_cards; i++){
|
||||||
|
MTGCardInstance * card = z->cards[i];
|
||||||
|
if (card->has(Constants::TREASON)) {p->game->putInGraveyard(card);i--;}
|
||||||
|
if (card->has(Constants::UNEARTH)) {p->game->putInExile(card);i--;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream& MTGSneakAttackRule::toString(ostream& out) const
|
||||||
|
{
|
||||||
|
out << "MTGSneakAttackRule ::: (";
|
||||||
|
return MTGAbility::toString(out) << ")";
|
||||||
|
}
|
||||||
|
int MTGSneakAttackRule::testDestroy(){return 0;}
|
||||||
|
MTGSneakAttackRule * MTGSneakAttackRule::clone() const{
|
||||||
|
MTGSneakAttackRule * a = NEW MTGSneakAttackRule(*this);
|
||||||
|
a->isClone = 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
//-------------------------------------------------------------------
|
||||||
MTGTokensCleanup::MTGTokensCleanup(int _id):MTGAbility(_id, NULL){}
|
MTGTokensCleanup::MTGTokensCleanup(int _id):MTGAbility(_id, NULL){}
|
||||||
|
|
||||||
int MTGTokensCleanup::receiveEvent(WEvent * e){
|
int MTGTokensCleanup::receiveEvent(WEvent * e){
|
||||||
@@ -684,4 +755,3 @@ HUDDisplay::~HUDDisplay(){
|
|||||||
a->isClone = 1;
|
a->isClone = 1;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user