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]
|
||||
[DO]
|
||||
Windswept Heath
|
||||
choice 1
|
||||
Plains
|
||||
[ASSERT]
|
||||
firstmain
|
||||
|
||||
@@ -53,8 +53,6 @@ public:
|
||||
intValue = target->getManaCost()->getConvertedCost();
|
||||
}else if (s == "lifetotal"){
|
||||
intValue = target->controller()->life;
|
||||
}else if (s == "sunburst"){
|
||||
intValue = target->costAmount;
|
||||
}else if (s == "odcount"){
|
||||
intValue = target->controller()->opponent()->damageCount;
|
||||
}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]
|
||||
//Ex : the rack, ivory tower...
|
||||
|
||||
@@ -44,11 +44,10 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
||||
MTGGameZone * currentZone;
|
||||
Pos* view;
|
||||
int X;
|
||||
int costAmount;
|
||||
int frozen;
|
||||
int regenerateTokens;
|
||||
int isToken;
|
||||
int stillInUse();
|
||||
int getCostAmount();
|
||||
Player * lastController;
|
||||
MTGGameZone * getCurrentZone();
|
||||
MTGGameZone * previousZone;
|
||||
@@ -75,7 +74,7 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
||||
int removeType(int value, int removeAll = 0);
|
||||
|
||||
//Combat
|
||||
bool blocked; //Blocked this turn or not?
|
||||
bool blocked; //Blocked this turn or not?
|
||||
MTGCardInstance * defenser;
|
||||
list<MTGCardInstance *>blockers;
|
||||
int attacker;
|
||||
|
||||
@@ -111,8 +111,11 @@ class Constants
|
||||
WILTING = 53,
|
||||
VIGOR = 54,
|
||||
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
|
||||
|
||||
@@ -64,6 +64,23 @@ class MTGPersistRule:public MTGAbility{
|
||||
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{
|
||||
public:
|
||||
@@ -146,7 +163,6 @@ class MTGDeathtouchRule:public MTGAbility{
|
||||
virtual MTGDeathtouchRule * clone() const;
|
||||
};
|
||||
|
||||
|
||||
/* HUD Display */
|
||||
|
||||
class HUDString {
|
||||
|
||||
@@ -45,6 +45,10 @@ int Damage::resolve(){
|
||||
target = ev->damage->target;
|
||||
if (!damage) return 0;
|
||||
|
||||
//asorbing effects for cards controller-----------
|
||||
|
||||
//reserved for culmulitive absorb ability coding
|
||||
|
||||
//prevent next damage-----------------------------
|
||||
if((target)->preventable >= 1) {
|
||||
int preventing =(target)->preventable;
|
||||
@@ -71,6 +75,9 @@ int Damage::resolve(){
|
||||
damage = 0;
|
||||
(_target)->counters->removeCounter(1,1);
|
||||
}
|
||||
if ((_target)->has(Constants::ABSORB)) {
|
||||
damage -= 1;
|
||||
}
|
||||
if ((_target)->has(Constants::WILTING)) {
|
||||
for (int i = 0; i < damage; i++){
|
||||
for (int i = damage; i > 0; i--){
|
||||
|
||||
@@ -25,6 +25,8 @@ void DuelLayers::init(){
|
||||
action->Add(NEW MTGBlockRule(-1));
|
||||
action->Add(NEW MTGLegendRule(-1));
|
||||
action->Add(NEW MTGPersistRule(-1));
|
||||
action->Add(NEW MTGUnearthRule(-1));
|
||||
action->Add(NEW MTGSneakAttackRule(-1));
|
||||
action->Add(NEW MTGLifelinkRule(-1));
|
||||
action->Add(NEW MTGDeathtouchRule(-1));
|
||||
action->Add(NEW OtherAbilitiesEventReceiver(-1));
|
||||
|
||||
@@ -114,7 +114,21 @@ void GameObserver::nextGamePhase(){
|
||||
for (int i = 0; i < 2; ++i)
|
||||
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){
|
||||
//Auto Hand cleaning, in case the player didn't do it himself
|
||||
while(currentPlayer->game->hand->nb_cards > 7)
|
||||
@@ -465,12 +479,11 @@ int GameObserver::untap(MTGCardInstance * card) {
|
||||
return 0;
|
||||
}
|
||||
if (card->has(Constants::DOESNOTUNTAP)) return 0;
|
||||
|
||||
if (card->frozen > 0) return 0;
|
||||
card->attemptUntap();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
TargetChooser * GameObserver::getCurrentTargetChooser(){
|
||||
TargetChooser * _tc = mLayers->actionLayer()->getCurrentTargetChooser();
|
||||
if (_tc) return _tc;
|
||||
|
||||
@@ -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...)
|
||||
found = s.find("untap");
|
||||
if (found != string::npos){
|
||||
|
||||
@@ -97,6 +97,7 @@ void MTGCardInstance::initMTGCI(){
|
||||
belongs_to=NULL;
|
||||
tapped = 0;
|
||||
untapping = 0;
|
||||
frozen = 0;
|
||||
summoningSickness = 1;
|
||||
preventable = 0;
|
||||
target = NULL;
|
||||
@@ -109,7 +110,6 @@ void MTGCardInstance::initMTGCI(){
|
||||
next = NULL;
|
||||
lastController = NULL;
|
||||
regenerateTokens = 0;
|
||||
costAmount = 0;
|
||||
blocked = false;
|
||||
currentZone = NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
int MTGCardInstance::getCostAmount(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGCardInstance::changeController(Player * newController){
|
||||
Player * originalOwner = controller();
|
||||
if (originalOwner == newController) return this;
|
||||
|
||||
@@ -64,6 +64,9 @@ const char* Constants::MTGBasicAbilities[] = {
|
||||
"wilting",//source takes damage in the form of -1/-1 counters.
|
||||
"vigor",//instead of taking damage the source gains +1/+1 counters
|
||||
"changeling",//this card is every creature type at all times
|
||||
"absorb",//timeshifted sliver ability. if damage would be dealt to card, prevent 1 of that damage.
|
||||
"treason",
|
||||
"unearth",
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -355,9 +355,11 @@ void MTGInPlay::untapAll(){
|
||||
for (i = 0; i < nb_cards; i ++){
|
||||
MTGCardInstance * card = cards[i];
|
||||
card->setUntapping();
|
||||
if (!card->basicAbilities[Constants::DOESNOTUNTAP]){
|
||||
card->attemptUntap();
|
||||
}
|
||||
if (!card->basicAbilities[Constants::DOESNOTUNTAP]){
|
||||
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;
|
||||
}
|
||||
if (playerMana->canAfford(cost)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -53,19 +52,10 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){
|
||||
ManaCost * alternative = card->getManaCost()->alternative;
|
||||
ManaCost * playerMana = player->getManaPool();
|
||||
//this handles extra cost payments at the moment a card is played.
|
||||
if (cost->isExtraPaymentSet()){
|
||||
if (!game->targetListIsSet(card)){
|
||||
return 0;
|
||||
}
|
||||
}else{
|
||||
cost->setExtraCostsAction(this, card);
|
||||
game->waitForExtraPayment = cost->extraCosts;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//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 (cost->alternative->isExtraPaymentSet()){
|
||||
if (cost->alternative->isExtraPaymentSet()){
|
||||
if (!game->targetListIsSet(card)){
|
||||
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());
|
||||
int payResult = player->getManaPool()->pay(card->getManaCost());
|
||||
@@ -550,8 +549,80 @@ HUDDisplay::~HUDDisplay(){
|
||||
a->isClone = 1;
|
||||
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){}
|
||||
|
||||
int MTGTokensCleanup::receiveEvent(WEvent * e){
|
||||
@@ -684,4 +755,3 @@ HUDDisplay::~HUDDisplay(){
|
||||
a->isClone = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user