added abilities:
proliferate
ProliferateChooser:new targetchooser for cards with counter and poison counters "proliferation".
MenuAbility:new internal ability to create custom menus of abilities which can be activated in sequence one after another.
multikicker, syntax kicker=multi{b}
works with variable word "kicked", the amount of times it was kicked.
target=<number>tc,target=<upto:>tc,target=<anyamount>tc,target(<number>tc),target(<upto:>tc),target(<anynumber>tc);
multitarget is now supported with the exception of "devided any way you choose" which can not be supported becuase we allow detoggling of targeted cards with a "second" click....so you can not click the same card 2 times to add it to the targets list twice for example.
this is minor, as the bulk of multitarget is not "devided"
removed 's' parsing for multitarget, added a limit of 1000 to "unlimited" for easier handling; we currently can't handle activation of an ability on a 1000 cards very well on any platform(infact i don't suggest it)
Countershroud(counterstring), this MTGAbility allows you to denote that a card can not have counters of the type "counterstring" put on it.
"any" is for no counters allowed at all. this is a replacement effect. cards state that they can still be the targets of counter effects, however on resolve nothing is placed on them instead.
@counteradded(counterstring) from(target):,@counterremoved(counterstring) from(target):: these are triggers for cards which state "whenever you add a counter of "counterstring" to "target"; added counterEvents struct;
other changes:
added support for ai handling of multitargeted spells.
changed a few of delete( into SAFE_DELETE(, safed up a couple areas where they did not seem safe to me;
added better handling of menus presented to ai, it will try to select the best based on eff returns.
added varible lastactioncontroller for ai use, it keeps it truely from ever tripping over itself and brings ai more inline with MTG rules.
converted TC into a protected member.
added "abilitybelongsto" string to tc, and set "owner" of the tc. a tc should never belong to "no one" it should always have a owner.
abilitybelongs to string is solely for easier debugging, i found it was a pain to never know what ability created a tc while i coded multitarget. the owner of the tc is the only one that should be using it, if an ability needs to declare the opponent as the owner (choose discard which is currently unsupported for example) this will allow us to better handle that situation by setting the tc owner in the ability which called it.
rewrote the logic of "checkonly" in ai choose targets, the only time it is "checkonly" is when it is trying to see if it had a target for a spell before it cast it, i now set this in the actual function call instead, the old method was far to error prone.
wrote logic for ai checking of menu objects presented to it,
ai will now make better choices when a menu is presented to it based on what it already knows. this changes it from it's old method of "just click the first option".
taught ai how to use multi-mana producers such as birds and duel lands by adding a method for it to find it's mana for a payment. it can effectively use cards like birds of paradise and sol ring(without locking up). It's primary method of pMana searching was maintain for performance(no need to deep search if we have it in pMana).
added a vector to actionlayer to store mana abilities for pMana. this provides us with a dramatic improvement when mana lords are present by reducing the amount of objects that need checking when ai checks pMana.
with 80 mana objects and a ton of lords one instance i checked went from 8000ish checks down to 80<===big difference.
added "tapped" green coloring(sorry i missed that!)...added red coloring to current actionLayers current action card (usually the source).
changed "type(" restrictions second amount from atoi into wparsedint for more flexiable coding.
add "&" parsing to CD targetchooser, removed "iscolorandcolor" variables and functions becuase they were a hack the real fix was this.
cretaure[dragon&black&blue] a creature that is a dragon, and black and also blue.
changed some of the ai computeactions and
removed unneeded gaurds in ai chooseblockers, they did more harm then good.
574 lines
16 KiB
C++
574 lines
16 KiB
C++
#ifndef _MTGABILITY_H_
|
|
#define _MTGABILITY_H_
|
|
|
|
|
|
|
|
class MTGCardInstance;
|
|
class Spell;
|
|
class Damageable;
|
|
class PlayGuiObject;
|
|
class ManaCost;
|
|
class MTGGameZone;
|
|
class Player;
|
|
class AManaProducer;
|
|
class WEvent;
|
|
class Counter;
|
|
|
|
#include "GameObserver.h"
|
|
#include "ActionElement.h"
|
|
#include <string>
|
|
#include <map>
|
|
#include <hge/hgeparticle.h>
|
|
#include "Damage.h"
|
|
#include "TargetChooser.h"
|
|
using std::string;
|
|
using std::map;
|
|
|
|
|
|
//stupid variables used to give a hint to the AI:
|
|
// Should I cast a spell on an enemy or friendly unit ?
|
|
#define BAKA_EFFECT_GOOD 1
|
|
#define BAKA_EFFECT_BAD -1
|
|
#define BAKA_EFFECT_DONTKNOW 0
|
|
#define MODE_PUTINTOPLAY 1
|
|
#define MODE_ABILITY 2
|
|
#define MODE_TARGET 3
|
|
|
|
#define COUNT_POWER 1
|
|
|
|
#define PARSER_LORD 1
|
|
#define PARSER_FOREACH 2
|
|
#define PARSER_ASLONGAS 3
|
|
|
|
class MTGAbility : public ActionElement
|
|
{
|
|
private:
|
|
ManaCost* mCost;
|
|
protected:
|
|
char menuText[50];
|
|
|
|
GameObserver * game;
|
|
public:
|
|
enum
|
|
{
|
|
NO_RESTRICTION = 0,
|
|
PLAYER_TURN_ONLY = 1,
|
|
AS_SORCERY = 2,
|
|
MY_BEFORE_BEGIN = 3,
|
|
MY_UNTAP = 4,
|
|
MY_UPKEEP = 5,
|
|
MY_DRAW = 6,
|
|
MY_FIRSTMAIN = 7,
|
|
MY_COMBATBEGIN = 8,
|
|
MY_COMBATATTACKERS = 9,
|
|
MY_COMBATBLOCKERS = 10,
|
|
MY_COMBATDAMAGE = 11,
|
|
MY_COMBATEND = 12,
|
|
MY_SECONDMAIN = 13,
|
|
MY_ENDOFTURN = 14,
|
|
MY_EOT = 15,
|
|
MY_CLEANUP = 16,
|
|
MY_AFTER_EOT = 17,
|
|
|
|
OPPONENT_BEFORE_BEGIN = 23,
|
|
OPPONENT_UNTAP = 24,
|
|
OPPONENT_UPKEEP = 25,
|
|
OPPONENT_DRAW = 26,
|
|
OPPONENT_FIRSTMAIN = 27,
|
|
OPPONENT_COMBATBEGIN = 28,
|
|
OPPONENT_COMBATATTACKERS = 29,
|
|
OPPONENT_COMBATBLOCKERS = 30,
|
|
OPPONENT_COMBATDAMAGE = 31,
|
|
OPPONENT_COMBATEND = 32,
|
|
OPPONENT_SECONDMAIN = 33,
|
|
OPPONENT_ENDOFTURN = 34,
|
|
OPPONENT_EOT = 35,
|
|
OPPONENT_CLEANUP = 36,
|
|
OPPONENT_AFTER_EOT = 37,
|
|
|
|
BEFORE_BEGIN = 43,
|
|
UNTAP = 44,
|
|
UPKEEP = 45,
|
|
DRAW = 46,
|
|
FIRSTMAIN = 47,
|
|
COMBATBEGIN = 48,
|
|
COMBATATTACKERS = 49,
|
|
COMBATBLOCKERS = 50,
|
|
COMBATDAMAGE = 51,
|
|
COMBATEND = 52,
|
|
SECONDMAIN = 53,
|
|
ENDOFTURN = 54,
|
|
EOT = 55,
|
|
CLEANUP = 56,
|
|
AFTER_EOT = 57,
|
|
|
|
OPPONENT_TURN_ONLY = 60,
|
|
|
|
};
|
|
|
|
bool oneShot;
|
|
int forceDestroy;
|
|
int forcedAlive;
|
|
bool canBeInterrupted;
|
|
ManaCost* alternative;
|
|
ManaCost* BuyBack;
|
|
ManaCost* FlashBack;
|
|
ManaCost* Retrace;
|
|
ManaCost* morph;
|
|
ManaCost* suspend;
|
|
|
|
Targetable * target;
|
|
int aType;
|
|
int naType;
|
|
int abilitygranted;
|
|
MTGCardInstance * source;
|
|
|
|
int parseCastRestrictions(MTGCardInstance* card, Player* player, string restrictions, string otherRestrictions);
|
|
int allowedToCast(MTGCardInstance* card, Player* player);
|
|
int allowedToAltCast(MTGCardInstance* card, Player* player);
|
|
MTGAbility(int id, MTGCardInstance * card);
|
|
MTGAbility(int id, MTGCardInstance * _source, Targetable * _target);
|
|
MTGAbility(const MTGAbility& copyFromMe);
|
|
virtual int testDestroy();
|
|
virtual ~MTGAbility();
|
|
ManaCost * getCost() {return mCost;};
|
|
void setCost(ManaCost * cost, bool forceDelete = 0);
|
|
|
|
virtual void Render()
|
|
{
|
|
}
|
|
|
|
virtual int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual int reactToClick(MTGCardInstance * card)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual int receiveEvent(WEvent * event)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual void Update(float dt)
|
|
{
|
|
}
|
|
|
|
virtual int fireAbility();
|
|
virtual int stillInUse(MTGCardInstance * card);
|
|
|
|
virtual int resolve()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual MTGAbility* clone() const = 0;
|
|
virtual ostream& toString(ostream& out) const;
|
|
virtual int addToGame();
|
|
virtual int removeFromGame();
|
|
|
|
/*Poor man's casting */
|
|
/* Todo replace that crap with dynamic casting */
|
|
enum
|
|
{
|
|
UNKNOWN = 0,
|
|
MANA_PRODUCER = 1,
|
|
MTG_ATTACK_RULE = 2,
|
|
DAMAGER = 3,
|
|
STANDARD_REGENERATE = 4,
|
|
PUT_INTO_PLAY = 5,
|
|
MOMIR = 6,
|
|
MTG_BLOCK_RULE = 7,
|
|
ALTERNATIVE_COST = 8,
|
|
BUYBACK_COST = 9,
|
|
FLASHBACK_COST = 10,
|
|
RETRACE_COST = 11,
|
|
MTG_COMBATTRIGGERS_RULE = 12,
|
|
STANDARD_PREVENT = 13,
|
|
STANDARD_EQUIP = 14,
|
|
STANDARD_LEVELUP = 15,
|
|
FOREACH = 16,
|
|
STANDARD_DRAW = 17,
|
|
STANDARD_PUMP = 18,
|
|
STANDARD_BECOMES = 19,
|
|
UPCOST = 20,
|
|
STANDARDABILITYGRANT = 21,
|
|
UNTAPPER = 22,
|
|
TAPPER = 23,
|
|
LIFER = 24,
|
|
CLONING = 25,
|
|
STANDARD_TEACH = 26,
|
|
STANDARD_TOKENCREATOR = 27,
|
|
MORPH_COST = 28,
|
|
SUSPEND_COST = 29,
|
|
COUNTERS = 30,
|
|
PUT_INTO_PLAY_WITH_KICKER = 31,
|
|
STANDARD_FIZZLER = 32,
|
|
|
|
|
|
};
|
|
};
|
|
|
|
class NestedAbility
|
|
{
|
|
public:
|
|
MTGAbility* ability;
|
|
NestedAbility(MTGAbility* _ability);
|
|
};
|
|
|
|
class TriggeredAbility : public MTGAbility
|
|
{
|
|
public:
|
|
TriggeredAbility(int id, MTGCardInstance* card);
|
|
TriggeredAbility(int id, MTGCardInstance* _source, Targetable* _target);
|
|
virtual void Update(float dt);
|
|
|
|
virtual void Render()
|
|
{
|
|
}
|
|
|
|
virtual int trigger()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual int triggerOnEvent(WEvent * e)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int receiveEvent(WEvent * e);
|
|
virtual int resolve() = 0;
|
|
virtual TriggeredAbility* clone() const = 0;
|
|
virtual ostream& toString(ostream& out) const;
|
|
};
|
|
|
|
|
|
//Triggers are not "real" abilities. They don't resolve, they just "trigger" and are associated to other abilities that will be addedToGame when the Trigger triggers
|
|
class Trigger: public TriggeredAbility {
|
|
private:
|
|
bool mOnce;
|
|
bool mActiveTrigger;
|
|
|
|
public:
|
|
Trigger(int id, MTGCardInstance * source, bool once, TargetChooser * _tc = NULL);
|
|
int resolve()
|
|
{
|
|
return 0; //This is a trigger, this function should not be called
|
|
}
|
|
int triggerOnEvent(WEvent * event);
|
|
virtual int triggerOnEventImpl(WEvent * event) = 0;
|
|
|
|
};
|
|
|
|
class ActivatedAbility : public MTGAbility
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
NO_RESTRICTION = 0,
|
|
PLAYER_TURN_ONLY = 1,
|
|
AS_SORCERY = 2,
|
|
MY_BEFORE_BEGIN = 3,
|
|
MY_UNTAP = 4,
|
|
MY_UPKEEP = 5,
|
|
MY_DRAW = 6,
|
|
MY_FIRSTMAIN = 7,
|
|
MY_COMBATBEGIN = 8,
|
|
MY_COMBATATTACKERS = 9,
|
|
MY_COMBATBLOCKERS = 10,
|
|
MY_COMBATDAMAGE = 11,
|
|
MY_COMBATEND = 12,
|
|
MY_SECONDMAIN = 13,
|
|
MY_ENDOFTURN = 14,
|
|
MY_EOT = 15,
|
|
MY_CLEANUP = 16,
|
|
MY_AFTER_EOT = 17,
|
|
|
|
OPPONENT_BEFORE_BEGIN = 23,
|
|
OPPONENT_UNTAP = 24,
|
|
OPPONENT_UPKEEP = 25,
|
|
OPPONENT_DRAW = 26,
|
|
OPPONENT_FIRSTMAIN = 27,
|
|
OPPONENT_COMBATBEGIN = 28,
|
|
OPPONENT_COMBATATTACKERS = 29,
|
|
OPPONENT_COMBATBLOCKERS = 30,
|
|
OPPONENT_COMBATDAMAGE = 31,
|
|
OPPONENT_COMBATEND = 32,
|
|
OPPONENT_SECONDMAIN = 33,
|
|
OPPONENT_ENDOFTURN = 34,
|
|
OPPONENT_EOT = 35,
|
|
OPPONENT_CLEANUP = 36,
|
|
OPPONENT_AFTER_EOT = 37,
|
|
|
|
BEFORE_BEGIN = 43,
|
|
UNTAP = 44,
|
|
UPKEEP = 45,
|
|
DRAW = 46,
|
|
FIRSTMAIN = 47,
|
|
COMBATBEGIN = 48,
|
|
COMBATATTACKERS = 49,
|
|
COMBATBLOCKERS = 50,
|
|
COMBATDAMAGE = 51,
|
|
COMBATEND = 52,
|
|
SECONDMAIN = 53,
|
|
ENDOFTURN = 54,
|
|
EOT = 55,
|
|
CLEANUP = 56,
|
|
AFTER_EOT = 57,
|
|
|
|
OPPONENT_TURN_ONLY = 69,
|
|
};
|
|
|
|
ManaCost* abilityCost;
|
|
int restrictions;
|
|
int limitPerTurn;
|
|
int counters;
|
|
int needsTapping;
|
|
string limit;
|
|
MTGAbility* sideEffect;
|
|
MTGAbility* sa;
|
|
string usesBeforeSideEffects;
|
|
int uses;
|
|
|
|
ActivatedAbility(int id, MTGCardInstance* card, ManaCost* _cost = NULL, int _restrictions = NO_RESTRICTION, string limit = "", MTGAbility* sideEffect = NULL, string usesBeforeSideEffects = "");
|
|
virtual ~ActivatedAbility();
|
|
|
|
virtual void Update(float dt)
|
|
{
|
|
if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT)
|
|
{
|
|
counters = 0;
|
|
}
|
|
return MTGAbility::Update(dt);
|
|
}
|
|
virtual int reactToClick(MTGCardInstance * card);
|
|
virtual int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
|
virtual int reactToTargetClick(Targetable * object);
|
|
virtual int activateAbility();
|
|
virtual int resolve() = 0;
|
|
void activateSideEffect();
|
|
virtual ActivatedAbility* clone() const = 0;
|
|
virtual ostream& toString(ostream& out) const;
|
|
};
|
|
|
|
class TargetAbility : public ActivatedAbility, public NestedAbility
|
|
{
|
|
public:
|
|
TargetAbility(int id, MTGCardInstance * card, TargetChooser * _tc,ManaCost * _cost = NULL, int _playerturnonly = 0);
|
|
TargetAbility(int id, MTGCardInstance * card,ManaCost * _cost = NULL, int _playerturnonly = 0);
|
|
~TargetAbility();
|
|
|
|
virtual int reactToClick(MTGCardInstance * card);
|
|
virtual int reactToTargetClick(Targetable * object);
|
|
virtual TargetAbility* clone() const = 0;
|
|
virtual void Render();
|
|
virtual int resolve();
|
|
virtual const char * getMenuText();
|
|
virtual ostream& toString(ostream& out) const;
|
|
};
|
|
|
|
class InstantAbility:public MTGAbility
|
|
{
|
|
public:
|
|
int init;
|
|
virtual void Update(float dt);
|
|
virtual int testDestroy();
|
|
InstantAbility(int _id, MTGCardInstance * source);
|
|
InstantAbility(int _id, MTGCardInstance * source,Targetable * _target);
|
|
|
|
virtual int resolve()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual InstantAbility* clone() const = 0;
|
|
virtual ostream& toString(ostream& out) const;
|
|
};
|
|
|
|
/* State based effects. This class works ONLY for InPlay and needs to be extended for other areas of the game !!! */
|
|
class ListMaintainerAbility:public MTGAbility
|
|
{
|
|
public:
|
|
map<MTGCardInstance *,bool> cards;
|
|
map<MTGCardInstance *,bool> checkCards;
|
|
map<Player *,bool> players;
|
|
ListMaintainerAbility(int _id)
|
|
: MTGAbility(_id, NULL)
|
|
{
|
|
}
|
|
|
|
ListMaintainerAbility(int _id, MTGCardInstance *_source)
|
|
: MTGAbility(_id, _source)
|
|
{
|
|
}
|
|
|
|
ListMaintainerAbility(int _id, MTGCardInstance *_source,Damageable * _target)
|
|
: MTGAbility(_id, _source, _target)
|
|
{
|
|
}
|
|
|
|
virtual void Update(float dt);
|
|
void updateTargets();
|
|
void checkTargets();
|
|
virtual bool canTarget(MTGGameZone * zone);
|
|
virtual int canBeInList(MTGCardInstance * card) = 0;
|
|
virtual int added(MTGCardInstance * card) = 0;
|
|
virtual int removed(MTGCardInstance * card) = 0;
|
|
|
|
virtual int canBeInList(Player * p)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual int added(Player * p)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual int removed(Player * p)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual int destroy();
|
|
virtual ListMaintainerAbility* clone() const = 0;
|
|
virtual ostream& toString(ostream& out) const;
|
|
};
|
|
|
|
class TriggerAtPhase:public TriggeredAbility
|
|
{
|
|
public:
|
|
int phaseId;
|
|
int who;
|
|
bool sourceUntapped;
|
|
bool sourceTap;
|
|
bool lifelost;
|
|
int lifeamount;
|
|
bool once,activeTrigger;
|
|
TriggerAtPhase(int id, MTGCardInstance * source, Targetable * target,int _phaseId, int who = 0,bool sourceUntapped = false,bool sourceTap = false,bool lifelost = false, int lifeamount = 0, bool once = false);
|
|
virtual int trigger();
|
|
int resolve(){return 0;};
|
|
virtual TriggerAtPhase* clone() const;
|
|
};
|
|
|
|
class TriggerNextPhase : public TriggerAtPhase
|
|
{
|
|
public:
|
|
int destroyActivated;
|
|
bool sourceUntapped;
|
|
bool sourceTap;
|
|
bool once,activeTrigger;
|
|
TriggerNextPhase(int id, MTGCardInstance * source, Targetable * target,int _phaseId, int who = 0,bool sourceUntapped = false,bool sourceTap = false,bool once = false);
|
|
virtual TriggerNextPhase* clone() const;
|
|
virtual int testDestroy();
|
|
|
|
};
|
|
|
|
|
|
class GenericTriggeredAbility : public TriggeredAbility, public NestedAbility
|
|
{
|
|
public:
|
|
TriggeredAbility * t;
|
|
queue<Targetable *> targets;
|
|
MTGAbility * destroyCondition;
|
|
GenericTriggeredAbility(int id, MTGCardInstance * _source, TriggeredAbility * _t, MTGAbility * a,MTGAbility * dc = NULL, Targetable * _target = NULL);
|
|
virtual int trigger();
|
|
virtual int triggerOnEvent(WEvent * e);
|
|
virtual int resolve();
|
|
virtual int testDestroy();
|
|
|
|
Targetable * getTriggerTarget(WEvent * e, MTGAbility * a);
|
|
void setTriggerTargets(Targetable * ta, MTGAbility * a);
|
|
|
|
void Update(float dt);
|
|
virtual GenericTriggeredAbility* clone() const;
|
|
const char * getMenuText();
|
|
~GenericTriggeredAbility();
|
|
};
|
|
|
|
/* Ability Factory */
|
|
class AbilityFactory
|
|
{
|
|
private:
|
|
string storedString;
|
|
int countCards(TargetChooser * tc, Player * player = NULL, int option = 0);
|
|
TriggeredAbility * parseTrigger(string s, string magicText, int id, Spell * spell, MTGCardInstance *card, Targetable * target);
|
|
MTGAbility * getAlternateCost( string s, int id, Spell *spell, MTGCardInstance *card );
|
|
MTGAbility * getManaReduxAbility(string s, int id, Spell *spell, MTGCardInstance *card, MTGCardInstance *target);
|
|
TargetChooser * parseSimpleTC(const std::string& s, const std::string& starter, MTGCardInstance *card, bool forceNoTarget = true);
|
|
|
|
public:
|
|
int parseRestriction(string s);
|
|
int parseCastRestrictions(MTGCardInstance * card = NULL,Player * player= NULL,string restrictions= "",string otherRestrictions= "");
|
|
Counter * parseCounter(string s, MTGCardInstance * target, Spell * spell = NULL);
|
|
int parsePowerToughness(string s, int *power, int *toughness);
|
|
int getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCardInstance * card = NULL, int id = 0, MTGGameZone * dest = NULL);
|
|
MTGAbility* parseMagicLine(string s, int id, Spell * spell, MTGCardInstance *card, bool activated = false, bool forceUEOT = false, MTGGameZone * dest = NULL);
|
|
int abilityEfficiency(MTGAbility * a, Player * p, int mode = MODE_ABILITY, TargetChooser * tc = NULL,Targetable * target = NULL);
|
|
int magicText(int id, Spell * spell, MTGCardInstance * card = NULL, int mode = MODE_PUTINTOPLAY, TargetChooser * tc = NULL, MTGGameZone * dest = NULL);
|
|
static int computeX(Spell * spell, MTGCardInstance * card);
|
|
static MTGAbility * getCoreAbility(MTGAbility * a);
|
|
int destroyAllInPlay(TargetChooser * tc, int bury = 0);
|
|
int moveAll(TargetChooser * tc, string destinationZone);
|
|
int damageAll(TargetChooser * tc, int damage);
|
|
int TapAll(TargetChooser * tc);
|
|
int UntapAll(TargetChooser * tc);
|
|
void addAbilities(int _id, Spell * spell);
|
|
};
|
|
|
|
|
|
class ActivatedAbilityTP : public ActivatedAbility
|
|
{
|
|
public:
|
|
int who;
|
|
ActivatedAbilityTP(int id, MTGCardInstance * card, Targetable * _target = NULL, ManaCost * cost=NULL, int who = TargetChooser::UNSET);
|
|
Targetable * getTarget();
|
|
};
|
|
|
|
class InstantAbilityTP : public InstantAbility
|
|
{
|
|
public:
|
|
int who;
|
|
InstantAbilityTP(int id, MTGCardInstance * card, Targetable * _target = NULL, int who = TargetChooser::UNSET);
|
|
Targetable * getTarget();
|
|
};
|
|
|
|
class AbilityTP : public MTGAbility
|
|
{
|
|
public:
|
|
int who;
|
|
AbilityTP(int id, MTGCardInstance * card, Targetable * _target = NULL, int who = TargetChooser::UNSET);
|
|
|
|
Targetable * getTarget();
|
|
|
|
virtual ~AbilityTP()
|
|
{
|
|
}
|
|
};
|
|
|
|
class AManaProducer : public ActivatedAbilityTP
|
|
{
|
|
protected:
|
|
|
|
Player * controller;
|
|
|
|
public:
|
|
string menutext;
|
|
ManaCost * output;
|
|
int tap;
|
|
AManaProducer(int id, MTGCardInstance * card, Targetable * t, ManaCost * _output, ManaCost * _cost = NULL, int who = TargetChooser::UNSET);
|
|
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL);
|
|
int resolve();
|
|
int reactToClick(MTGCardInstance* _card);
|
|
const char * getMenuText();
|
|
~AManaProducer();
|
|
virtual AManaProducer * clone() const;
|
|
};
|
|
|
|
#endif
|
|
|