- 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:
wagic.the.homebrew@gmail.com
2009-12-10 13:44:05 +00:00
parent 86ad1ef8c7
commit ca35754273
12 changed files with 298 additions and 25 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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]

View 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]

View 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]

View 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]

View File

@@ -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(&currentAbilities,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{

View File

@@ -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);

View File

@@ -264,6 +264,9 @@ ActionLayer::ActionLayer(){
}
ActionLayer::~ActionLayer(){
for (int i=mCount-1;i>=0;i--){
moveToGarbage((ActionElement *)mObjects[i]);
}
SAFE_DELETE(abilitiesMenu);
cleanGarbage();
}

View File

@@ -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]);

View File

@@ -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");
}