Erwan
- Adding equipments. They work like auras, except you have to add an "auto={cost}:equip" line. See Behemoth sledge in ARB for an example. Please test a lot before committing, thanks :)
This commit is contained in:
@@ -1,4 +1,17 @@
|
||||
[card]
|
||||
id=179545
|
||||
name=Behemoth Sledge
|
||||
mana={1}{G}{W}
|
||||
type=Artifact
|
||||
subtype=Equipment
|
||||
text=Equipped creature gets +2/+2 and has lifelink and trample. Equip {3}
|
||||
auto={3}:equip
|
||||
auto=2/2
|
||||
auto=lifelink
|
||||
auto=trample
|
||||
rarity=U
|
||||
[/card]
|
||||
[card]
|
||||
text=Trample, haste At end of turn, Blitz Hellion's owner shuffles it into his or her library.
|
||||
auto=@next my endofturn:moveto(myLibrary) && shuffle
|
||||
id=179406
|
||||
|
||||
@@ -72,15 +72,7 @@ toughness=1
|
||||
text=As long as you control another multicolored permanent, Bant Sureblade gets +1/+1 and has first strike.
|
||||
rarity=C
|
||||
[/card]
|
||||
[card]
|
||||
id=179545
|
||||
name=Behemoth Sledge
|
||||
mana={1}{G}{W}
|
||||
type=Artifact
|
||||
subtype=Equipment
|
||||
text=Equipped creature gets +2/+2 and has lifelink and trample. Equip {3}
|
||||
rarity=U
|
||||
[/card]
|
||||
|
||||
[card]
|
||||
id=185057
|
||||
name=Bituminous Blast
|
||||
|
||||
@@ -93,6 +93,10 @@ basal_sliver.txt
|
||||
beacon_of_creation.txt
|
||||
beacon_of_destruction.txt
|
||||
beacon_of_unrest.txt
|
||||
behemoth_sledge.txt
|
||||
behemoth_sledge2.txt
|
||||
behemoth_sledge3.txt
|
||||
behemoth_sledge4.txt
|
||||
belligerent_hatchling.txt
|
||||
benalish_knight.txt
|
||||
black_vise.txt
|
||||
@@ -355,4 +359,5 @@ momir/overcost.txt
|
||||
########################
|
||||
#AI Tests
|
||||
########################
|
||||
ai/goblin_artillery.txt
|
||||
#Removed until we can have these tests work on all machines :(
|
||||
#ai/goblin_artillery.txt
|
||||
|
||||
31
projects/mtg/bin/Res/test/behemoth_sledge.txt
Normal file
31
projects/mtg/bin/Res/test/behemoth_sledge.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
#Test:equipment
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
hand:behemoth sledge
|
||||
manapool:{4}{G}{W}
|
||||
inplay:grizzly bears
|
||||
[PLAYER2]
|
||||
[DO]
|
||||
behemoth sledge
|
||||
behemoth sledge
|
||||
grizzly bears
|
||||
next
|
||||
#begin
|
||||
next
|
||||
#attackers
|
||||
grizzly bears
|
||||
next
|
||||
#blockers
|
||||
next
|
||||
#damage
|
||||
next
|
||||
#end combat
|
||||
[ASSERT]
|
||||
COMBATEND
|
||||
[PLAYER1]
|
||||
life:24
|
||||
inplay:grizzly bears,behemoth sledge
|
||||
[PLAYER2]
|
||||
life:16
|
||||
[END]
|
||||
34
projects/mtg/bin/Res/test/behemoth_sledge2.txt
Normal file
34
projects/mtg/bin/Res/test/behemoth_sledge2.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
#Test:equipment
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
hand:behemoth sledge
|
||||
manapool:{7}{G}{W}
|
||||
inplay:grizzly bears,raging goblin
|
||||
[PLAYER2]
|
||||
[DO]
|
||||
behemoth sledge
|
||||
behemoth sledge
|
||||
grizzly bears
|
||||
behemoth sledge
|
||||
raging goblin
|
||||
next
|
||||
#begin
|
||||
next
|
||||
#attackers
|
||||
grizzly bears
|
||||
raging goblin
|
||||
next
|
||||
#blockers
|
||||
next
|
||||
#damage
|
||||
next
|
||||
#end combat
|
||||
[ASSERT]
|
||||
COMBATEND
|
||||
[PLAYER1]
|
||||
life:23
|
||||
inplay:grizzly bears,raging goblin,behemoth sledge
|
||||
[PLAYER2]
|
||||
life:15
|
||||
[END]
|
||||
33
projects/mtg/bin/Res/test/behemoth_sledge3.txt
Normal file
33
projects/mtg/bin/Res/test/behemoth_sledge3.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
#Test:equipment
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
hand:behemoth sledge
|
||||
manapool:{4}{G}{W}
|
||||
inplay:raging goblin
|
||||
[PLAYER2]
|
||||
inplay:mountain
|
||||
hand:lightning bolt
|
||||
[DO]
|
||||
behemoth sledge
|
||||
behemoth sledge
|
||||
raging goblin
|
||||
eot
|
||||
next
|
||||
#upkeeep
|
||||
next
|
||||
#draw
|
||||
next
|
||||
#firstmain
|
||||
mountain
|
||||
lightning bolt
|
||||
raging goblin
|
||||
[ASSERT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
inplay:behemoth sledge
|
||||
graveyard:raging goblin
|
||||
[PLAYER2]
|
||||
inplay:mountain
|
||||
graveyard:lightning bolt
|
||||
[END]
|
||||
54
projects/mtg/bin/Res/test/behemoth_sledge4.txt
Normal file
54
projects/mtg/bin/Res/test/behemoth_sledge4.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
#Test:equipment
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
hand:behemoth sledge
|
||||
manapool:{4}{G}{W}
|
||||
inplay:raging goblin
|
||||
[PLAYER2]
|
||||
inplay:mountain,island,forest
|
||||
hand:smash
|
||||
[DO]
|
||||
behemoth sledge
|
||||
behemoth sledge
|
||||
raging goblin
|
||||
eot
|
||||
next
|
||||
#upkeeep
|
||||
next
|
||||
#draw
|
||||
next
|
||||
#firstmain
|
||||
mountain
|
||||
island
|
||||
forest
|
||||
smash
|
||||
behemoth sledge
|
||||
eot
|
||||
next
|
||||
#upkeeep
|
||||
next
|
||||
#draw
|
||||
next
|
||||
#firstmain
|
||||
next
|
||||
#begin
|
||||
next
|
||||
#attackers
|
||||
raging goblin
|
||||
next
|
||||
#blocker
|
||||
next
|
||||
#damage
|
||||
next
|
||||
#end
|
||||
[ASSERT]
|
||||
COMBATEND
|
||||
[PLAYER1]
|
||||
graveyard:behemoth sledge
|
||||
inplay:raging goblin
|
||||
[PLAYER2]
|
||||
inplay:mountain,island,forest
|
||||
graveyard:smash
|
||||
life:19
|
||||
[END]
|
||||
@@ -945,6 +945,76 @@ class ABasicAbilityAuraModifierUntilEOT: public ActivatedAbility{
|
||||
};
|
||||
|
||||
|
||||
class AEquip:public TargetAbility{
|
||||
public:
|
||||
vector<MTGAbility *> currentAbilities;
|
||||
AEquip(int _id, MTGCardInstance * _source, ManaCost * _cost=NULL, int doTap=0, int myturnOnly = 1):TargetAbility(_id,_source,NULL,_cost,myturnOnly,doTap){
|
||||
|
||||
}
|
||||
|
||||
int unequip(){
|
||||
source->target = NULL;
|
||||
for (size_t i = 0; i < currentAbilities.size(); ++i){
|
||||
MTGAbility * a = currentAbilities[i];
|
||||
if(dynamic_cast<AEquip *>(a)){
|
||||
SAFE_DELETE(a);
|
||||
continue;
|
||||
}
|
||||
GameObserver::GetInstance()->removeObserver(currentAbilities[i]);
|
||||
}
|
||||
currentAbilities.clear();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int equip(MTGCardInstance * equipped){
|
||||
source->target = equipped;
|
||||
AbilityFactory af;
|
||||
af.getAbilities(¤tAbilities,NULL,source);
|
||||
for (size_t i = 0; i < currentAbilities.size(); ++i){
|
||||
MTGAbility * a = currentAbilities[i];
|
||||
if(dynamic_cast<AEquip *>(a)) continue;
|
||||
a->addToGame();
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int resolve(){
|
||||
MTGCardInstance * mTarget = tc->getNextCardTarget();
|
||||
if (!mTarget) return 0;
|
||||
if (mTarget == source) return 0;
|
||||
unequip();
|
||||
equip(mTarget);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char * getMenuText(){
|
||||
return "Equip";
|
||||
}
|
||||
|
||||
|
||||
int testDestroy(){
|
||||
if (source->target && !game->isInPlay(source->target))
|
||||
unequip();
|
||||
return TargetAbility::testDestroy();
|
||||
}
|
||||
|
||||
int destroy(){
|
||||
unequip();
|
||||
return TargetAbility::destroy();
|
||||
}
|
||||
|
||||
AEquip * clone() const{
|
||||
AEquip * a = NEW AEquip(*this);
|
||||
a->isClone = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*Gives life each time a spell matching CardDescriptor's criteria are match . Optionnal manacost*/
|
||||
class ASpellCastLife:public MTGAbility{
|
||||
|
||||
@@ -203,6 +203,7 @@ class AbilityFactory{
|
||||
int parsePowerToughness(string s, int *power, int *toughness);
|
||||
TriggeredAbility * parseTrigger(string s, int id, Spell * spell, MTGCardInstance *card, Targetable * target);
|
||||
public:
|
||||
int getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCardInstance * card = NULL, int id = 0);
|
||||
MTGAbility * parseMagicLine(string s, int id, Spell * spell, MTGCardInstance *card, int activated = 0, int forceUEOT = 0);
|
||||
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);
|
||||
|
||||
@@ -264,6 +264,9 @@ ActionLayer::ActionLayer(){
|
||||
}
|
||||
|
||||
ActionLayer::~ActionLayer(){
|
||||
for (int i=mCount-1;i>=0;i--){
|
||||
moveToGarbage((ActionElement *)mObjects[i]);
|
||||
}
|
||||
SAFE_DELETE(abilitiesMenu);
|
||||
cleanGarbage();
|
||||
}
|
||||
|
||||
@@ -83,7 +83,12 @@ ActionLayer * DuelLayers::actionLayer(){
|
||||
DuelLayers::DuelLayers() : nbitems(0) {}
|
||||
|
||||
DuelLayers::~DuelLayers(){
|
||||
for (int i = 0; i < nbitems; ++i) delete objects[i];
|
||||
int _nbitems = nbitems;
|
||||
nbitems = 0;
|
||||
for (int i = 0; i < _nbitems; ++i){
|
||||
delete objects[i];
|
||||
objects[i] = NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < waiters.size(); ++i)
|
||||
delete(waiters[i]);
|
||||
|
||||
@@ -215,6 +215,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return amp;
|
||||
}
|
||||
|
||||
AEquip *ae = dynamic_cast<AEquip*>(a);
|
||||
if (ae){
|
||||
ae->cost = cost;
|
||||
TargetChooserFactory tcf;
|
||||
ae->tc = tcf.createTargetChooser("creature|myBattlefield", card);
|
||||
return ae;
|
||||
}
|
||||
|
||||
|
||||
int limit = 0;
|
||||
unsigned int limit_str = s.find("limit:");
|
||||
if (limit_str != string::npos){
|
||||
@@ -405,6 +414,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return tok;
|
||||
}
|
||||
|
||||
//Equipment
|
||||
found = s.find("equip");
|
||||
if (found != string::npos){
|
||||
MTGAbility * a = NEW AEquip(id,card);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
//MoveTo Move a card from a zone to another
|
||||
found = s.find("moveto(");
|
||||
@@ -825,19 +841,9 @@ int AbilityFactory::computeX(Spell * spell, MTGCardInstance * card){
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Some basic functionalities that can be added automatically in the text file
|
||||
/*
|
||||
* Several objects are computed from the text string, and have a direct influence on what action we should take
|
||||
* (direct impact on the game such as draw a card immediately, or create a New GameObserver and add it to the Abilities,etc..)
|
||||
* These objects are:
|
||||
* - trigger (if there is an "@" in the string, this is a triggered ability)
|
||||
* - target (if there ie a "target(" in the string, then this is a TargetAbility)
|
||||
* - doTap (a dirty way to know if tapping is included in the cost...
|
||||
*/
|
||||
int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int mode, TargetChooser * tc){
|
||||
int dryMode = 0;
|
||||
if (!spell) dryMode = 1;
|
||||
|
||||
int AbilityFactory::getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCardInstance * card, int id){
|
||||
|
||||
if (!card && spell) card = spell->source;
|
||||
if (!card) return 0;
|
||||
MTGCardInstance * target = card->target;
|
||||
@@ -854,7 +860,6 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int
|
||||
unsigned int found;
|
||||
int result = id;
|
||||
|
||||
|
||||
while (magicText.size()){
|
||||
found = magicText.find("\n");
|
||||
if (found != string::npos){
|
||||
@@ -866,6 +871,34 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int
|
||||
}
|
||||
|
||||
MTGAbility * a = parseMagicLine(line, result, spell, card);
|
||||
if (a){
|
||||
v->push_back(a);
|
||||
result++;
|
||||
}else{
|
||||
OutputDebugString("ABILITYFACTORY ERROR: Parser returned NULL\n");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//Some basic functionalities that can be added automatically in the text file
|
||||
/*
|
||||
* Several objects are computed from the text string, and have a direct influence on what action we should take
|
||||
* (direct impact on the game such as draw a card immediately, or create a New GameObserver and add it to the Abilities,etc..)
|
||||
* These objects are:
|
||||
* - trigger (if there is an "@" in the string, this is a triggered ability)
|
||||
* - target (if there ie a "target(" in the string, then this is a TargetAbility)
|
||||
* - doTap (a dirty way to know if tapping is included in the cost...
|
||||
*/
|
||||
int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int mode, TargetChooser * tc){
|
||||
int dryMode = 0;
|
||||
if (!spell) dryMode = 1;
|
||||
|
||||
vector<MTGAbility *> v;
|
||||
int result = getAbilities(&v,spell,card,id);
|
||||
|
||||
for (size_t i = 0; i < v.size(); ++i){
|
||||
MTGAbility * a = v[i];
|
||||
if (dryMode){
|
||||
result = abilityEfficiency(a, card->controller(),mode,tc);
|
||||
SAFE_DELETE(a);
|
||||
@@ -879,7 +912,6 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int
|
||||
}else{
|
||||
a->addToGame();
|
||||
}
|
||||
result++;
|
||||
}else{
|
||||
OutputDebugString("ABILITYFACTORY ERROR: Parser returned NULL\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user