- Trying to add generic classes for Triggered abilities. PLEASE DO NOT USE THESE RIGHT NOW, Not Tested AT ALL !
This commit is contained in:
wagic.the.homebrew
2008-11-12 14:38:30 +00:00
parent c97dd1f260
commit a418e10c47
6 changed files with 5003 additions and 5024 deletions
-1
View File
@@ -29,7 +29,6 @@ class ActionElement: public JGuiObject{
int newPhase; int newPhase;
int modal; int modal;
int waitingForAnswer; int waitingForAnswer;
void RenderMessageBackground(float y0, int height);
int getActivity(); int getActivity();
virtual void Update(float dt){}; virtual void Update(float dt){};
virtual void Render(){}; virtual void Render(){};
+58 -182
View File
@@ -1,3 +1,4 @@
#ifndef _CARDS_H_ #ifndef _CARDS_H_
#define _CARDS_H_ #define _CARDS_H_
@@ -34,6 +35,12 @@ class ADrawer:public ActivatedAbility{
game->mLayers->stackLayer()->addDraw(source->controller(),nbcards); game->mLayers->stackLayer()->addDraw(source->controller(),nbcards);
return 1; return 1;
} }
const char * getMenuText(){
return "Draw";
}
}; };
@@ -58,6 +65,10 @@ class ADestroyer:public TargetAbility{
return 0; return 0;
} }
const char * getMenuText(){
return "Destroy";
}
}; };
//Destroyer. TargetAbility //Destroyer. TargetAbility
@@ -65,6 +76,10 @@ class ABurier:public ADestroyer{
public: public:
ABurier(int _id, MTGCardInstance * _source, TargetChooser * _tc = NULL):ADestroyer(_id,_source, tc,1){ ABurier(int _id, MTGCardInstance * _source, TargetChooser * _tc = NULL):ADestroyer(_id,_source, tc,1){
} }
const char * getMenuText(){
return "Bury";
}
}; };
@@ -134,6 +149,10 @@ class ABasicAbilityModifierUntilEOT:public TargetAbility{
return 1; return 1;
} }
const char * getMenuText(){
return MTGBasicAbilities[ability];
}
}; };
@@ -180,6 +199,10 @@ class ABasicAbilityAuraModifierUntilEOT: public ActivatedAbility{
return 1; return 1;
} }
const char * getMenuText(){
return MTGBasicAbilities[ability];
}
}; };
@@ -674,6 +697,10 @@ class AStandardRegenerate:public ActivatedAbility{
return 1; return 1;
} }
const char * getMenuText(){
return "Regenerate";
}
}; };
/*Gives protection to a target */ /*Gives protection to a target */
@@ -899,7 +926,7 @@ class AColorLord:public ListMaintainerAbility{
int canBeInList(MTGCardInstance * card){ int canBeInList(MTGCardInstance * card){
if (notcolor > -1){ if (notcolor > -1){
if (card!=source && card->isACreature() && !card->hasColor(color)) return 1; if (card!=source && card->isACreature() && !card->hasColor(notcolor)) return 1;
}else{ }else{
if (card!=source && card->isACreature() && card->hasColor(color)) return 1; if (card!=source && card->isACreature() && card->hasColor(color)) return 1;
} }
@@ -947,6 +974,10 @@ class ADamager:public TargetAbility{
return 1; return 1;
} }
const char * getMenuText(){
return "Damage target";
}
}; };
@@ -965,8 +996,33 @@ class ATapper:public TargetAbility{
return 1; return 1;
} }
const char * getMenuText(){
return "Tap target";
}
}; };
//Ability to untap a target
class AUntaper:public TargetAbility{
public:
AUntaper(int _id, MTGCardInstance * card, ManaCost * _manacost, TargetChooser * _tc):TargetAbility(_id,card,_tc,_manacost){
}
int resolve(){
MTGCardInstance * _target = tc->getNextCardTarget();
if (_target){
_target->tapped = 0;
}
return 1;
}
const char * getMenuText(){
return "Untap target";
}
};
// 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...
class ALifeZoneLink:public MTGAbility{ class ALifeZoneLink:public MTGAbility{
@@ -1052,18 +1108,7 @@ class AControlStealAura: public MTGAbility{
//TODO put it back into owners's graveyard if needed... //TODO put it back into owners's graveyard if needed...
}; };
//Ability to untap a target
class AUntaper:public TargetAbility{
public:
AUntaper(int _id, MTGCardInstance * card, ManaCost * _manacost, TargetChooser * _tc):TargetAbility(_id,card,_tc,_manacost){
}
int resolve(){
tc->getNextCardTarget()->tapped = 0;
return 1;
}
};
//Same as StealControl Aura ???? Obsolete ? //Same as StealControl Aura ???? Obsolete ?
@@ -2715,6 +2760,7 @@ class AShieldOfTheAge: public TargetAbility{
}; };
// GiveLifeForTappedType // GiveLifeForTappedType
class AGiveLifeForTappedType:public MTGAbility{ class AGiveLifeForTappedType:public MTGAbility{
public: public:
char type[20]; char type[20];
@@ -2745,67 +2791,6 @@ class AGiveLifeForTappedType:public MTGAbility{
} }
}; };
// People of the Woods
class APeopleOfTheWoods:public ListMaintainerAbility{
public:
APeopleOfTheWoods(int _id, MTGCardInstance * _source):ListMaintainerAbility(_id, _source){
}
int canBeInList(MTGCardInstance * card){
if (source->controller()->game->inPlay->hasCard(card) && card->hasType("forest") ) return 1;
return 0;
}
int added(MTGCardInstance * card){
source->addToToughness(1);
return 1;
}
int removed(MTGCardInstance * card){
source->addToToughness(-1);
return 1;
}
};
//Abomination Kill blocking creature if white or green
class AAbomination :public MTGAbility{
public:
MTGCardInstance * opponents[20];
int nbOpponents;
AAbomination (int _id, MTGCardInstance * _source):MTGAbility(_id, _source){
nbOpponents = 0;
}
void Update(float dt){
if (newPhase != currentPhase){
if( newPhase == MTG_PHASE_COMBATDAMAGE){
nbOpponents = 0;
MTGCardInstance * opponent = source->getNextOpponent();
while ((opponent && opponent->hasColor(MTG_COLOR_GREEN)) || opponent->hasColor(MTG_COLOR_WHITE)){
opponents[nbOpponents] = opponent;
nbOpponents ++;
opponent = source->getNextOpponent(opponent);
}
}else if (newPhase == MTG_PHASE_COMBATEND){
for (int i = 0; i < nbOpponents ; i++){
game->mLayers->stackLayer()->addPutInGraveyard(opponents[i]);
}
}
}
}
int testDestroy(){
if(!game->isInPlay(source) && currentPhase != MTG_PHASE_UNTAP){
return 0;
}else{
return MTGAbility::testDestroy();
}
}
};
//Minion of Leshrac //Minion of Leshrac
class AMinionofLeshrac: public TargetAbility{ class AMinionofLeshrac: public TargetAbility{
public: public:
@@ -2868,114 +2853,5 @@ class ALostOrderofJarkeld:public ListMaintainerAbility{
}; };
//CreaturePowerToughnessModifierForAllTypeControlled
class ACreaturePowerToughnessModifierForAllTypeControlled:public ListMaintainerAbility{
public:
char type[20];
ACreaturePowerToughnessModifierForAllTypeControlled(int _id, MTGCardInstance * _source, const char * _type):ListMaintainerAbility(_id, _source){
}
int canBeInList(MTGCardInstance * card){
if (source->controller()->game->inPlay->hasCard(card) && card->hasType(type) ) return 1;
return 0;
}
int added(MTGCardInstance * card){
source->power += 1;
source->addToToughness(1);
return 1;
}
int removed(MTGCardInstance * card){
source->power -= 1;
source->addToToughness(-1);
return 1;
}
};
//GenericKirdApe
class AGenericKirdApe:public MTGAbility{
public:
int init;
char type [20];
int power;
int toughness;
AGenericKirdApe(int _id, MTGCardInstance * _source, const char * _type, int _power, int _toughness):MTGAbility(_id, _source){
init = 0;
}
void Update(float dt){
if (source->controller()->game->inPlay->hasType(type)){
if(!init){
init = 1;
source->power+=power;
source->addToToughness(toughness);
}
}else{
if (init){
init = 0;
source->power-=power;
source->addToToughness(-toughness);
}
}
}
};
//Rampage ability Tentative 2
class ARampageAbility:public MTGAbility{
public:
int nbOpponents;
int PowerModifier;
int ToughnessModifier;
int modifier;
ARampageAbility(int _id, MTGCardInstance * _source,int _PowerModifier, int _ToughnessModifier):MTGAbility(_id, _source){
modifier=0;
}
void Update(float dt){
if (source->isAttacker()){
MTGInPlay * inPlay = game->opponent()->game->inPlay;
for (int i = 0; i < inPlay->nb_cards; i ++){
MTGCardInstance * current = inPlay->cards[i];
if (current->isDefenser()){
modifier++;
}
}
source->power+= (PowerModifier * modifier);
source->addToToughness(ToughnessModifier * modifier);
}
}
};
//Rampage ability Tentative 1 - Did not work as expected
class A1RampageAbility:public MTGAbility{
public:
MTGCardInstance * opponents[20];
int nbOpponents;
int PowerModifier;
int ToughnessModifier;
A1RampageAbility(int _id, MTGCardInstance * _source,int _PowerModifier, int _ToughnessModifier):MTGAbility(_id, _source){
nbOpponents = 0;
}
void Update(float dt){
if (source->isAttacker()){
if (newPhase != currentPhase){
if( newPhase == MTG_PHASE_COMBATDAMAGE){
nbOpponents = 0;
MTGCardInstance * opponent = source->getNextOpponent();
while (opponent){
opponents[nbOpponents] = opponent;
nbOpponents ++;
source->power+= PowerModifier;
source->addToToughness(ToughnessModifier);
opponent = source->getNextOpponent(opponent);
}
}
}
}
}
};
#endif #endif
+84 -9
View File
@@ -20,18 +20,12 @@ using std::string;
using std::map; using std::map;
//Two stupid variables used to give a hint to the AI:
// Should I cast a spell on an ennemy or friendly unit ?
#define BAKA_EFFECT_GOOD 10 #define BAKA_EFFECT_GOOD 10
#define BAKA_EFFECT_BAD 11 #define BAKA_EFFECT_BAD 11
class AbilityFactory{
private:
int destroyAllFromTypeInPlay(const char * type, MTGCardInstance * source, int bury = 0);
int destroyAllFromColorInPlay(int color, MTGCardInstance * source, int bury = 0);
int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p);
public:
int magicText(int id, Spell * spell, MTGCardInstance * card = NULL);
void addAbilities(int _id, Spell * spell);
};
class MTGAbility: public ActionElement{ class MTGAbility: public ActionElement{
protected: protected:
@@ -113,6 +107,87 @@ class ListMaintainerAbility:public MTGAbility{
virtual int destroy(); virtual int destroy();
}; };
/* An attempt to globalize triggered abilities as much as possible */
class MTGAbilityBasicFeatures{
public:
Damageable * target;
GameObserver * game;
MTGCardInstance * source;
MTGAbilityBasicFeatures();
MTGAbilityBasicFeatures(MTGCardInstance * _source, Damageable * _target = NULL);
void init(MTGCardInstance * _source, Damageable * _target = NULL);
};
class Trigger:public MTGAbilityBasicFeatures{
public:
virtual int trigger()=0;
virtual int testDestroy(){return 0;};
};
class TriggerAtPhase:public Trigger{
public:
int currentPhase, newPhase;
int phaseId;
TriggerAtPhase(int _phaseId);
virtual int trigger();
};
class TriggerNextPhase:public TriggerAtPhase{
public:
int destroyActivated;
TriggerNextPhase(int _phaseId);
virtual int testDestroy();
};
class TriggeredEvent:public MTGAbilityBasicFeatures{
public:
virtual int resolve()=0;
};
class DrawEvent:public TriggeredEvent{
public:
Player * player;
int nbcards;
DrawEvent(Player * _player, int _nbcards);
int resolve();
};
class DestroyCondition:public MTGAbilityBasicFeatures{
public:
virtual int testDestroy();
};
class GenericTriggeredAbility:public TriggeredAbility{
public:
Trigger * t;
TriggeredEvent * te;
DestroyCondition * dc;
GenericTriggeredAbility(int id, MTGCardInstance * _source, Trigger * _t, TriggeredEvent * _te, DestroyCondition * _dc = NULL, Damageable * _target = NULL);
virtual int trigger();
virtual int resolve();
virtual int testDestroy();
~GenericTriggeredAbility();
};
/* Ability Factory */
class AbilityFactory{
private:
int destroyAllFromTypeInPlay(const char * type, MTGCardInstance * source, int bury = 0);
int destroyAllFromColorInPlay(int color, MTGCardInstance * source, int bury = 0);
int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p);
Trigger * parseTrigger(string magicText);
public:
int magicText(int id, Spell * spell, MTGCardInstance * card = NULL);
void addAbilities(int _id, Spell * spell);
};
#include "MTGCardInstance.h" #include "MTGCardInstance.h"
#endif #endif
+20 -6
View File
@@ -93,10 +93,8 @@ static int _b[7] = {20, 0, 140,15, 50,255,128};
#define MOUNTAINHOME 33 #define MOUNTAINHOME 33
#define SWAMPHOME 34 #define SWAMPHOME 34
#define PLAINSHOME 35 #define PLAINSHOME 35
#define FLANKING 36
#define RAMPAGE1 37
#define NB_BASIC_ABILITIES 38 #define NB_BASIC_ABILITIES 36
static const char * MTGBasicAbilities[] = { static const char * MTGBasicAbilities[] = {
"trample", "trample",
@@ -134,9 +132,7 @@ static const char * MTGBasicAbilities[] = {
"islandhome", "islandhome",
"moutainhome", "moutainhome",
"swamphome", "swamphome",
"plainshome", "plainshome"
"flanking",
"rampage",
}; };
@@ -169,6 +165,24 @@ static const char *MTGPhaseNames[] =
"---" "---"
}; };
static const char *MTGPhaseCodeNames[] =
{
"beginofturn",
"untap",
"upkeep",
"draw",
"firstmain",
"combatbegins",
"attackers",
"blockers",
"combatdamage",
"combatends",
"secondmain",
"endofturn",
"cleanup",
"beforenextturn"
};
-25
View File
@@ -12,31 +12,6 @@ ActionElement::ActionElement(int id):JGuiObject(id){
tc = NULL; tc = NULL;
} }
/*
void ActionElement::RenderMessageBackground(float y0, int _height){
float height = _height;
PIXEL_TYPE colors_up[] =
{
ARGB(0,255,255,255),
ARGB(0,255,255,255),
ARGB(128,255,255,255),
ARGB(128,255,255,255)
};
PIXEL_TYPE colors_down[] =
{
ARGB(128,255,255,255),
ARGB(128,255,255,255),
ARGB(0,255,255,255),
ARGB(0,255,255,255)
};
JRenderer * renderer = JRenderer::GetInstance();
renderer->FillRect(0,y0,SCREEN_WIDTH,height/2,colors_up);
renderer->FillRect(0,y0+height/2,SCREEN_WIDTH,height/2,colors_down);
// mEngine->DrawLine(0,y0,SCREEN_WIDTH,y0,ARGB(128,255,255,255));
// mEngine->DrawLine(0,y0+height,SCREEN_WIDTH,y0+height,ARGB(128,255,255,255));
}*/
int ActionElement::getActivity(){ int ActionElement::getActivity(){
+138 -98
View File
@@ -50,7 +50,26 @@ int AbilityFactory::putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone
return 1; return 1;
} }
//Some basic functionnalities that can be added automatically in the text file
Trigger * AbilityFactory::parseTrigger(string magicText){
int found = magicText.find("@");
if (found == string::npos) return NULL;
//Next Time...
found = magicText.find("next");
if (found != string::npos){
for (int i = 0; i < NB_MTG_PHASES; i++){
found = magicText.find(MTGPhaseCodeNames[i]);
if (found != string::npos){
return NEW TriggerNextPhase(i);
}
}
}
return NULL;
}
//Some basic functionalities that can be added automatically in the text file
int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
int dryMode = 0; int dryMode = 0;
if (!spell) dryMode = 1; if (!spell) dryMode = 1;
@@ -60,7 +79,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
if (!target) target = card; if (!target) target = card;
string magicText = card->magicText; string magicText = card->magicText;
if (card->alias && magicText.size() == 0){ if (card->alias && magicText.size() == 0){
//An awful way to gat access to the aliasedcard //An awful way to get access to the aliasedcard
magicText = GameObserver::GetInstance()->players[0]->game->collection->getCardById(card->alias)->magicText; magicText = GameObserver::GetInstance()->players[0]->game->collection->getCardById(card->alias)->magicText;
} }
string s; string s;
@@ -89,6 +108,13 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
int doTap = 0; int doTap = 0;
string lordType = ""; string lordType = "";
Trigger * trigger = parseTrigger(s);
//Dirty way to remove the trigger text (could get in the way)
if (trigger){
found = s.find(":");
s = s.substr(found+1);
}
//Tap in the cost ? //Tap in the cost ?
if (s.find("{t}") != string::npos) doTap = 1; if (s.find("{t}") != string::npos) doTap = 1;
@@ -154,17 +180,6 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
result++; result++;
continue; continue;
} }
//Tentative Destroyall not working char is not compatible with string variable
//found = s.find("destroyall(");
//if (found != string::npos){
// if (dryMode) return BAKA_EFFECT_GOOD;
// unsigned int end = s.find(")", found+11);
// if (end != string::npos){
// string type = s.substr(found+11,end-found-11).c_str();
// destroyAllFromTypeInPlay(type.c_str(), card);
// result++;
// continue;
//}
//Regeneration //Regeneration
found = s.find("}:regenerate"); found = s.find("}:regenerate");
@@ -211,10 +226,6 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
continue; continue;
} }
//Summon
//Reveal Take Target and put in in hand (should be also able to target hand since some card needs you to reveal a card in your hand
//Damage //Damage
found = s.find("damage"); found = s.find("damage");
if (found != string::npos){ if (found != string::npos){
@@ -266,7 +277,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
} }
//Draw //Draw
found = s.find("draw"); found = s.find("draw:");
if (found != string::npos){ if (found != string::npos){
unsigned int start = s.find(":",found); unsigned int start = s.find(":",found);
unsigned int end = s.find(" ",start); unsigned int end = s.find(" ",start);
@@ -278,6 +289,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
nbcards = atoi(s.substr(start+1).c_str()); nbcards = atoi(s.substr(start+1).c_str());
} }
if (dryMode) return BAKA_EFFECT_GOOD; if (dryMode) return BAKA_EFFECT_GOOD;
if (trigger){
DrawEvent * action = NEW DrawEvent(card->controller(),nbcards);
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action));
}else{
if (tc){ if (tc){
//TODO ? //TODO ?
}else{ }else{
@@ -288,6 +303,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
game->addObserver(NEW ADrawer(id,card,cost,nbcards,doTap)); game->addObserver(NEW ADrawer(id,card,cost,nbcards,doTap));
} }
} }
}
result++; result++;
continue; continue;
} }
@@ -450,7 +466,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
case 106525: //Ascendant Evincar case 106525: //Ascendant Evincar
{ {
game->addObserver(NEW AColorLord(_id, card,MTG_COLOR_BLACK,-1,1,1)); game->addObserver(NEW AColorLord(_id, card,MTG_COLOR_BLACK,-1,1,1));
game->addObserver(NEW AColorLord(_id, card,0,MTG_COLOR_BLACK,-1,-1)); game->addObserver(NEW AColorLord(_id + 1, card,0,MTG_COLOR_BLACK,-1,-1));
break; break;
} }
@@ -975,6 +991,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
MTGPlayerCards * zones = card->target->controller()->game; MTGPlayerCards * zones = card->target->controller()->game;
zones->putInZone(card->target,zones->inPlay,zones->hand); zones->putInZone(card->target,zones->inPlay,zones->hand);
break; break;
} }
case 1235: //Aspect of Wolf case 1235: //Aspect of Wolf
{ {
@@ -1270,77 +1287,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
break; break;
} }
// Addons ALA
case 175114: // Master of Etherium
{
game->addObserver(NEW ACreaturePowerToughnessModifierForAllTypeControlled(_id,card,"artifact"));
break;
}
case 174989: // Wild Nacatl
{
game->addObserver(NEW AGenericKirdApe(_id,card,"plains",1,1));
game->addObserver(NEW AGenericKirdApe(_id,card,"moutain",1,1));
break;
}
//Addons The Dark
case 1797: //Inferno does 6 damage to all players and all creatures.
{
for (int i = 0; i < 2 ; i++){
game->mLayers->stackLayer()->addDamage(card, game->players[i], 6);
for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++){
MTGCardInstance * current = game->players[i]->game->inPlay->cards[j];
if (current->isACreature()){
game->mLayers->stackLayer()->addDamage(card, current, 6);
}
}
}
break;
}
case 1773 : //People of the Woods
{
game->addObserver(NEW APeopleOfTheWoods(_id, card));
break;
}
case 1818: //Tivadar's Crusade
{
destroyAllFromTypeInPlay("goblin", card);
break;
}
//Addons Legends
case 1470: //Acid Rain
{
destroyAllFromTypeInPlay("forest", card);
break;
}
case 1427: //Abomination
{
game->addObserver(NEW AAbomination(_id,card));
break;
}
case 1533: //Livingplane
{
game->addObserver(NEW AConvertLandToCreatures(id, card, "land"));
break;
}
case 1607: //Divine Offering
{
card->target->controller()->game->putInGraveyard(card->target);
game->currentlyActing()->life+= card->target->getManaCost()->getConvertedCost();
break;
}
case 1625: //Lifeblood
{
game->addObserver(NEW AGiveLifeForTappedType (_id, card, "island"));
break;
}
//Addons ICE-AGE Cards //Addons ICE-AGE Cards
case 2631: //Jokulhaups case 2631: //Jokulhaups
{ {
@@ -1470,12 +1416,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
if (card->basicAbilities[PLAINSHOME]){ if (card->basicAbilities[PLAINSHOME]){
game->addObserver(NEW AStrongLandLinkCreature(_id, card,"plains")); game->addObserver(NEW AStrongLandLinkCreature(_id, card,"plains"));
} }
// New Abilities Flanking and Rampage
if (card->basicAbilities [RAMPAGE1]){
game->addObserver (NEW ARampageAbility(_id, card, 1, 1));
}
//Instants are put in the graveyard automatically if that's not already done //Instants are put in the graveyard automatically if that's not already done
if (!putSourceInGraveyard){ if (!putSourceInGraveyard){
if (card->hasType("instant") || card->hasType("sorcery")){ if (card->hasType("instant") || card->hasType("sorcery")){
@@ -1489,13 +1429,13 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
} }
MTGAbility::MTGAbility(int id, MTGCardInstance * card):ActionElement(id){ MTGAbility::MTGAbility(int id, MTGCardInstance * card):ActionElement(id){
game = GameObserver::GetInstance();; game = GameObserver::GetInstance();
source = card; source = card;
target = card; target = card;
} }
MTGAbility::MTGAbility(int id, MTGCardInstance * _source,Damageable * _target ):ActionElement(id){ MTGAbility::MTGAbility(int id, MTGCardInstance * _source,Damageable * _target ):ActionElement(id){
game = GameObserver::GetInstance();; game = GameObserver::GetInstance();
source = _source; source = _source;
target = _target; target = _target;
} }
@@ -1721,3 +1661,103 @@ int ListMaintainerAbility::destroy(){
cards.clear(); cards.clear();
return 1; return 1;
} }
/* An attempt to globalize triggered abilities as much as possible */
MTGAbilityBasicFeatures::MTGAbilityBasicFeatures(){
game = GameObserver::GetInstance();
}
MTGAbilityBasicFeatures::MTGAbilityBasicFeatures(MTGCardInstance * _source, Damageable * _target):source(_source),target(_target){
if (!target) target = source;
game = GameObserver::GetInstance();
}
void MTGAbilityBasicFeatures::init(MTGCardInstance * _source, Damageable * _target){
source = source;
target=_target;
if (!target) target = source;
}
TriggerAtPhase::TriggerAtPhase(int _phaseId):Trigger(),phaseId(_phaseId){
currentPhase = game->getCurrentGamePhase();
newPhase = -1;
}
int TriggerAtPhase::trigger(){
int result = 0;
newPhase = game->getCurrentGamePhase();
if (currentPhase != newPhase && newPhase == phaseId){
result = 1;
}
currentPhase = newPhase;
return result;
}
TriggerNextPhase::TriggerNextPhase(int _phaseId):TriggerAtPhase(_phaseId){
destroyActivated = 0;
}
int TriggerNextPhase::testDestroy(){
if (newPhase <= phaseId) destroyActivated = 1;
if ( newPhase > phaseId && destroyActivated){
return 1;
}
return 0;
}
DrawEvent::DrawEvent(Player * _player, int _nbcards):TriggeredEvent(),player(_player),nbcards(_nbcards){
}
int DrawEvent::resolve(){
game->mLayers->stackLayer()->addDraw(player,nbcards);
return nbcards;
}
int DestroyCondition::testDestroy(){
if (!game->isInPlay(source)){
return 1;
}
if (target && !game->isInPlay((MTGCardInstance *)target)){
source->controller()->game->putInGraveyard(source);//TODO put this in a better place ???
return 1;
}
return 0;
}
GenericTriggeredAbility::GenericTriggeredAbility(int id, MTGCardInstance * _source, Trigger * _t, TriggeredEvent * _te, DestroyCondition * _dc , Damageable * _target ): TriggeredAbility(id, _source,_target){
if (!target) target = source;
t = _t;
te = _te;
dc = _dc;
t->init(_source,_target);
te->init(_source,_target);
if (dc) dc->init(_source,_target);
}
int GenericTriggeredAbility::trigger(){
return t->trigger();
}
int GenericTriggeredAbility::resolve(){
return te->resolve();
}
int GenericTriggeredAbility::testDestroy(){
if (dc) return dc->testDestroy();
return t->testDestroy();
}
GenericTriggeredAbility::~GenericTriggeredAbility(){
delete t;
delete te;
SAFE_DELETE(dc);
}