Salmelo:"Here is another patch, this time adding counters to target specifications, so now you should be able to target things with counters on them as well as use counters for criterion for Lord, aslongas, foreach, etc.
I had to muddle the syntax a little bit though, so heres an example, taken from gwafa hazid, whom I added to the primitives to test with.
lord(creature[counter{0/0.1.Bribe}]|opponentbattlefield) cantattack
obviously the part we are worried about is the counter part, note that those are curly braces { } and periods . instead of parentheses ( ) and commas , this is so that it does not conflict with how targets are normally parsed, which it did before I changed those. Counters still work the same way everywhere else though, you only need to use { } and periods in target code.
Also, you can use counter{any} to specify that it should look for things with any kind of counter on them, not just specific ones, this is used by Kulrath Knight, for example.
I also consolidated most of the code used to parse counter specifications, as it seemed unnecessary duplicating it three times.
Anyway, aside from this major addition, I also added Gwafa Hazid, Profiteer; and Kulrath Knight to the primitives, as well as a test file for each to make sure it worked.
Hopefully y'all will find this patch useful.
Oh, and I should point out that it only works with one Counter in the target specification, i imagine if you put two in the same one then it would either overwrite the first with the second or merge them into some sort of hybrid counter monstrosity, either way, I wouldn't suggest it. "
Cards with vanishing are also codable now. Have a look at the comments for explanation.
daily_build.
306 lines
9.3 KiB
C++
306 lines
9.3 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 "../include/GameObserver.h"
|
|
#include "ActionElement.h"
|
|
#include <string>
|
|
#include <map>
|
|
#include <hge/hgeparticle.h>
|
|
#include "../include/Damage.h"
|
|
#include "../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{
|
|
protected:
|
|
char menuText[25];
|
|
|
|
GameObserver * game;
|
|
public:
|
|
int oneShot;
|
|
int forceDestroy;
|
|
ManaCost * cost;
|
|
Targetable * target;
|
|
int aType;
|
|
MTGCardInstance * source;
|
|
MTGAbility(int id, MTGCardInstance * card);
|
|
MTGAbility(int id, MTGCardInstance * _source, Targetable * _target);
|
|
virtual int testDestroy();
|
|
virtual ~MTGAbility();
|
|
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,
|
|
};
|
|
};
|
|
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
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,
|
|
};
|
|
int restrictions;
|
|
int needsTapping;
|
|
ActivatedAbility(int id, MTGCardInstance * card,ManaCost * _cost = NULL, int _restrictions = NO_RESTRICTION,int tap = 1);
|
|
virtual int reactToClick(MTGCardInstance * card);
|
|
virtual int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
|
virtual int reactToTargetClick(Targetable * object);
|
|
virtual int resolve() = 0;
|
|
virtual ActivatedAbility* clone() const = 0;
|
|
virtual ostream& toString(ostream& out) const;
|
|
};
|
|
|
|
class TargetAbility:public ActivatedAbility{
|
|
public:
|
|
MTGAbility * ability;
|
|
TargetAbility(int id, MTGCardInstance * card, TargetChooser * _tc,ManaCost * _cost = NULL, int _playerturnonly = 0,int tap = 1);
|
|
TargetAbility(int id, MTGCardInstance * card,ManaCost * _cost = NULL, int _playerturnonly = 0,int tap = 1);
|
|
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;
|
|
~TargetAbility();
|
|
};
|
|
|
|
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,Damageable * _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<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();
|
|
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;
|
|
TriggerAtPhase(int id, MTGCardInstance * source, Targetable * target,int _phaseId, int who = 0);
|
|
virtual int trigger();
|
|
int resolve(){return 0;};
|
|
virtual TriggerAtPhase* clone() const;
|
|
};
|
|
|
|
class TriggerNextPhase:public TriggerAtPhase{
|
|
public:
|
|
int destroyActivated;
|
|
TriggerNextPhase(int id, MTGCardInstance * source, Targetable * target,int _phaseId, int who = 0);
|
|
virtual TriggerNextPhase* clone() const;
|
|
virtual int testDestroy();
|
|
|
|
};
|
|
|
|
|
|
class GenericTriggeredAbility:public TriggeredAbility{
|
|
public:
|
|
TriggeredAbility * t;
|
|
MTGAbility * ability;
|
|
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();
|
|
void Update(float dt);
|
|
virtual GenericTriggeredAbility* clone() const;
|
|
const char * getMenuText();
|
|
~GenericTriggeredAbility();
|
|
};
|
|
|
|
/* Ability Factory */
|
|
class AbilityFactory{
|
|
private:
|
|
int countCards(TargetChooser * tc, Player * player = NULL, int option = 0);
|
|
TriggeredAbility * parseTrigger(string s, int id, Spell * spell, MTGCardInstance *card, Targetable * target);
|
|
int parseRestriction(string s);
|
|
public:
|
|
Counter * parseCounter(string s, MTGCardInstance * target);
|
|
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, int activated = 0, int forceUEOT = 0,MTGGameZone * dest = NULL);
|
|
int abilityEfficiency(MTGAbility * a, Player * p, int mode = MODE_ABILITY, TargetChooser * tc = 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 doTap = 0, int who = TargetChooser::UNSET);
|
|
Targetable * getTarget();
|
|
};
|
|
|
|
class AManaProducer: public ActivatedAbilityTP{
|
|
protected:
|
|
|
|
|
|
string menutext;
|
|
Player * controller;
|
|
|
|
public:
|
|
ManaCost * output;
|
|
int tap;
|
|
AManaProducer(int id, MTGCardInstance * card, Targetable * t, ManaCost * _output, ManaCost * _cost = NULL, int doTap = 1, 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;
|
|
};
|
|
|
|
#include "MTGCardInstance.h"
|
|
|
|
#endif
|
|
|