- Added "PreventAllCombatDamage" [from(...)] [to(...)] keyword. Please test it on a few cards before we "mass" use it. As a side effect, fixed issue 155 (ebony horse target).
This commit is contained in:
wagic.the.homebrew@gmail.com
2009-11-14 11:35:29 +00:00
parent 5781060d83
commit 9ca552093e
15 changed files with 2695 additions and 2577 deletions
+1
View File
@@ -665,6 +665,7 @@ type=Sorcery
text={2}, {T}: Untap target attacking creature you control. Prevent all combat damage that would be dealt to and dealt by that creature this turn. text={2}, {T}: Untap target attacking creature you control. Prevent all combat damage that would be dealt to and dealt by that creature this turn.
id=1108 id=1108
name=Ebony Horse name=Ebony Horse
auto={2}{T}:untap target(creature[attacking]|myBattlefield) && preventAllCombatDamage to(mytgt) ueot && preventAllCombatDamage from(mytgt) ueot
rarity=R rarity=R
mana={3} mana={3}
type=Artifact type=Artifact
+1
View File
@@ -121,6 +121,7 @@ drift_of_the_dead.txt
dromad_purebred.txt dromad_purebred.txt
dross_harvester.txt dross_harvester.txt
duskwalker.txt duskwalker.txt
ebony_horse.txt
elvish_piper.txt elvish_piper.txt
elvish_promenade.txt elvish_promenade.txt
emblem_of_the_warmind.txt emblem_of_the_warmind.txt
+27
View File
@@ -0,0 +1,27 @@
#2, Tap: Untap target attacking creature you control.
# Prevent all combat damage that would be dealt to and dealt by that creature this turn.
[INIT]
COMBATATTACKERS
[PLAYER1]
inplay:grizzly bears,ebony horse,mountain,swamp
[PLAYER2]
inplay:hypnotic specter
[DO]
grizzly bears
next
hypnotic specter
next
yes
mountain
swamp
ebony horse
grizzly bears
endofinterruption
next
[ASSERT]
COMBATEND
[PLAYER1]
inplay:grizzly bears,ebony horse,mountain,swamp
[PLAYER2]
inplay:hypnotic specter
[END]
+76 -27
View File
@@ -2147,6 +2147,82 @@ public:
}; };
class APreventAllCombatDamage:public MTGAbility{
public:
string to, from;
REDamagePrevention * re;
APreventAllCombatDamage(int id,MTGCardInstance * source,string to,string from):MTGAbility(id,source),to(to),from(from){
re = NULL;
}
int addToGame(){
if (re) {
OutputDebugString("FATAL:re shouldn't be already set in APreventAllCombatDAMAGE\n");
return 0;
}
TargetChooserFactory tcf;
TargetChooser *toTc = tcf.createTargetChooser(to,source,this);
if (toTc) toTc->targetter = NULL;
TargetChooser *fromTc = tcf.createTargetChooser(from,source,this);
if (fromTc) fromTc->targetter = NULL;
re = NEW REDamagePrevention (this, fromTc, toTc, -1, false, DAMAGE_COMBAT);
game->replacementEffects->add(re);
return 1;
}
int Destroy(){
game->replacementEffects->remove(re);
delete re;
return 1;
}
APreventAllCombatDamage * clone() const{
APreventAllCombatDamage * a = NEW APreventAllCombatDamage(*this);
a->isClone = 1;
return a;
}
};
//Adds types/abilities/P/T to a card (until end of turn)
class APreventAllCombatDamageUEOT: public InstantAbility{
public:
APreventAllCombatDamage * ability;
APreventAllCombatDamageUEOT(int id,MTGCardInstance * source,string to, string from):InstantAbility(id,source){
ability = NEW APreventAllCombatDamage(id,source,to, from);
}
int resolve(){
ability->target = this->target;
ability->addToGame();
return 1;
}
int destroy(){
ability->destroy();
return 1;
}
const char * getMenuText(){
return ability->getMenuText();
}
APreventAllCombatDamageUEOT * clone() const{
APreventAllCombatDamageUEOT * a = NEW APreventAllCombatDamageUEOT(*this);
a->ability = this->ability->clone();
a->isClone = 1;
return a;
}
~APreventAllCombatDamageUEOT(){
delete ability;
}
};
/* /*
Specific Classes Specific Classes
*/ */
@@ -2607,33 +2683,6 @@ class ADisruptingScepter:public TargetAbility{
}; };
//1108 Ebony Horse
class AEbonyHorse:public TargetAbility{
public:
AEbonyHorse(int _id, MTGCardInstance * _source):TargetAbility(_id,_source, NEW CreatureTargetChooser()){
int _cost[] = {Constants::MTG_COLOR_ARTIFACT, 2};
cost = NEW ManaCost(_cost,1);
}
int resolve(){
MTGCardInstance * _target = tc->getNextCardTarget();
if (_target->isAttacker()) _target->toggleAttacker();
return 1;
}
virtual ostream& toString(ostream& out) const
{
out << "AEbonyHorse ::: (";
return TargetAbility::toString(out) << ")";
}
AEbonyHorse * clone() const{
AEbonyHorse * a = NEW AEbonyHorse(*this);
a->isClone = 1;
return a;
}
};
//1345 Farmstead //1345 Farmstead
class AFarmstead:public ActivatedAbility{ class AFarmstead:public ActivatedAbility{
public: public:
+7 -2
View File
@@ -13,6 +13,10 @@ class GameObserver;
#define DAMAGEABLE_MTGCARDINSTANCE 0 #define DAMAGEABLE_MTGCARDINSTANCE 0
#define DAMAGEABLE_PLAYER 1 #define DAMAGEABLE_PLAYER 1
#define DAMAGE_ALL_TYPES 0
#define DAMAGE_COMBAT 1
#define DAMAGE_OTHER 2
class Damageable:public Targetable { class Damageable:public Targetable {
protected: protected:
@@ -28,13 +32,14 @@ class Damageable:public Targetable {
class Damage: public Interruptible { class Damage: public Interruptible {
protected: protected:
void init(MTGCardInstance * source, Damageable * target, int damage); void init(MTGCardInstance * source, Damageable * target, int damage, int typeOfDamage);
public: public:
Damageable * target; Damageable * target;
int typeOfDamage;
int damage; int damage;
void Render(); void Render();
Damage(MTGCardInstance* source, Damageable * target); Damage(MTGCardInstance* source, Damageable * target);
Damage(MTGCardInstance* source, Damageable * target, int damage); Damage(MTGCardInstance* source, Damageable * target, int damage, int typeOfDamage = DAMAGE_OTHER);
int resolve(); int resolve();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
}; };
+1 -1
View File
@@ -24,7 +24,7 @@ class PlayGuiObject: public JGuiObject, public JGuiListener, public Pos{
float defaultHeight; float defaultHeight;
bool mHasFocus; bool mHasFocus;
int type; int type;
virtual void Entering(){mHasFocus = true; zoom = 1.4;}; virtual void Entering(){mHasFocus = true; zoom = 1.4f;};
virtual bool Leaving(u32 key){mHasFocus = false; zoom = 1.0; return true;}; virtual bool Leaving(u32 key){mHasFocus = false; zoom = 1.0; return true;};
virtual bool CheckUserInput(u32 key) {return false;}; virtual bool CheckUserInput(u32 key) {return false;};
virtual bool ButtonPressed(){return true;}; virtual bool ButtonPressed(){return true;};
+3 -1
View File
@@ -3,6 +3,7 @@
#include <list> #include <list>
using namespace std; using namespace std;
#include "../include/Damage.h"
#include "WEvent.h" #include "WEvent.h"
class TargetChooser; class TargetChooser;
@@ -21,8 +22,9 @@ protected:
TargetChooser * tcTarget; TargetChooser * tcTarget;
int damage; int damage;
bool oneShot; bool oneShot;
int typeOfDamage;
public: public:
REDamagePrevention(MTGAbility * _source, TargetChooser *_tcSource = NULL,TargetChooser *_tcTarget = NULL, int _damage = -1, bool _oneShot = true); REDamagePrevention(MTGAbility * _source, TargetChooser *_tcSource = NULL,TargetChooser *_tcTarget = NULL, int _damage = -1, bool _oneShot = true, int typeOfDamage = DAMAGE_ALL_TYPES);
WEvent * replace (WEvent *e); WEvent * replace (WEvent *e);
~REDamagePrevention(); ~REDamagePrevention();
}; };
+1 -1
View File
@@ -58,7 +58,7 @@ class TargetChooser: public TargetsList {
class TargetChooserFactory{ class TargetChooserFactory{
public: public:
TargetChooser * createTargetChooser(string s, MTGCardInstance * card); TargetChooser * createTargetChooser(string s, MTGCardInstance * card, MTGAbility * ability = NULL);
TargetChooser * createTargetChooser(MTGCardInstance * card); TargetChooser * createTargetChooser(MTGCardInstance * card);
}; };
+5 -5
View File
@@ -7,14 +7,15 @@
#include "../include/WResourceManager.h" #include "../include/WResourceManager.h"
Damage::Damage(MTGCardInstance * source, Damageable * target) { Damage::Damage(MTGCardInstance * source, Damageable * target) {
init(source, target, source->getPower()); init(source, target, source->getPower(), DAMAGE_OTHER);
} }
Damage::Damage(MTGCardInstance * source, Damageable * target, int damage) { Damage::Damage(MTGCardInstance * source, Damageable * target, int damage,int _typeOfDamage) {
init(source, target, damage); init(source, target, damage, _typeOfDamage);
} }
void Damage::init(MTGCardInstance * _source, Damageable * _target, int _damage){ void Damage::init(MTGCardInstance * _source, Damageable * _target, int _damage, int _typeOfDamage){
typeOfDamage = _typeOfDamage;
target = _target; target = _target;
source = _source; source = _source;
@@ -70,7 +71,6 @@ int Damage::resolve(){
//Send (Damage/Replaced effect) event to listeners //Send (Damage/Replaced effect) event to listeners
g->receiveEvent(e); g->receiveEvent(e);
//SAFE_DELETE(e);
return a; return a;
} }
+1 -1
View File
@@ -28,7 +28,7 @@ void DamagerDamaged::addDamage(int damage, DamagerDamaged* source){
if (0 >= i->damage) damages.erase(i); if (0 >= i->damage) damages.erase(i);
return; return;
} }
if (0 < damage) damages.push_back(Damage(source->card, card, damage)); if (0 < damage) damages.push_back(Damage(source->card, card, damage,DAMAGE_COMBAT));
return; return;
} }
+1 -1
View File
@@ -314,7 +314,7 @@ int GuiCombat::resolve() // Returns the number of damage objects dealt this turn
stack->Add(NEW Damage(*d)); stack->Add(NEW Damage(*d));
dmg -= (*q)->sumDamages(); dmg -= (*q)->sumDamages();
} }
if (dmg > 0) stack->Add(NEW Damage((*it)->card, go->opponent(), dmg)); if (dmg > 0) stack->Add(NEW Damage((*it)->card, go->opponent(), dmg, DAMAGE_COMBAT));
for (vector<Damage>::iterator d = (*it)->damages.begin(); d != (*it)->damages.end(); ++d) for (vector<Damage>::iterator d = (*it)->damages.begin(); d != (*it)->damages.end(); ++d)
stack->Add(NEW Damage(*d)); stack->Add(NEW Damage(*d));
} }
+34 -9
View File
@@ -370,7 +370,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a; return a;
} }
//Regeneration //Regeneration
found = s.find("regenerate"); found = s.find("regenerate");
if (found != string::npos){ if (found != string::npos){
@@ -447,6 +446,39 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
if (s.find(" opponent") != string::npos) who=TargetChooser::OPPONENT; if (s.find(" opponent") != string::npos) who=TargetChooser::OPPONENT;
if (s.find(" targetcontroller") != string::npos) who=TargetChooser::TARGET_CONTROLLER; if (s.find(" targetcontroller") != string::npos) who=TargetChooser::TARGET_CONTROLLER;
found = s.find("ueot");
if (found!= string::npos) forceUEOT = 1;
//PreventCombat Damage
found = s.find("preventallcombatdamage");
if (found != string::npos){
string to = "";
string from = "";
found = s.find("to(");
if (found != string::npos){
size_t end = s.find (")", found);
to = s.substr(found+3,end - found - 3);
}
found = s.find("from(");
if (found != string::npos){
size_t end = s.find (")", found);
from = s.substr(found+5,end - found - 5);
}
MTGAbility * ab;
if (forceUEOT){
ab = NEW APreventAllCombatDamageUEOT(id,card,to,from);
}else{
ab = NEW APreventAllCombatDamage(id,card,to,from);
}
return ab;
}
//Damage //Damage
found = s.find("damage"); found = s.find("damage");
if (found != string::npos){ if (found != string::npos){
@@ -605,8 +637,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
} }
found = s.find("ueot");
if (found!= string::npos) forceUEOT = 1;
//Becomes... (animate artifact...: becomes(Creature, manacost/manacost) //Becomes... (animate artifact...: becomes(Creature, manacost/manacost)
@@ -983,12 +1013,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
game->addObserver(NEW ADragonWhelp(_id,card)); game->addObserver(NEW ADragonWhelp(_id,card));
break; break;
} }
case 1108: //Ebony Horse
{
AEbonyHorse * ability = NEW AEbonyHorse(_id,card);
game->addObserver(ability);
break;
}
case 1345: //Farmstead case 1345: //Farmstead
{ {
game->addObserver(NEW AFarmstead(_id, card,card->target)); game->addObserver(NEW AFarmstead(_id, card,card->target));
+3 -2
View File
@@ -2,10 +2,10 @@
#include "../include/ReplacementEffects.h" #include "../include/ReplacementEffects.h"
#include "../include/MTGCardInstance.h" #include "../include/MTGCardInstance.h"
#include "../include/TargetChooser.h" #include "../include/TargetChooser.h"
#include "../include/Damage.h"
REDamagePrevention::REDamagePrevention(MTGAbility * source, TargetChooser *tcSource, TargetChooser *tcTarget, int damage, bool oneShot):source(source), tcSource(tcSource), tcTarget(tcTarget), damage(damage), oneShot(oneShot){
REDamagePrevention::REDamagePrevention(MTGAbility * source, TargetChooser *tcSource, TargetChooser *tcTarget, int damage, bool oneShot, int typeOfDamage):source(source), tcSource(tcSource), tcTarget(tcTarget), damage(damage), oneShot(oneShot), typeOfDamage(typeOfDamage){
} }
WEvent * REDamagePrevention::replace (WEvent *event){ WEvent * REDamagePrevention::replace (WEvent *event){
@@ -14,6 +14,7 @@ WEvent * REDamagePrevention::replace (WEvent *event){
WEventDamage * e = dynamic_cast<WEventDamage*>(event); WEventDamage * e = dynamic_cast<WEventDamage*>(event);
if (!e) return event; if (!e) return event;
Damage *d = e->damage; Damage *d = e->damage;
if (d->typeOfDamage != typeOfDamage && typeOfDamage != DAMAGE_ALL_TYPES) return event;
if ((!tcSource || tcSource->canTarget(d->source)) && if ((!tcSource || tcSource->canTarget(d->source)) &&
(!tcTarget || tcTarget->canTarget(d->target)) (!tcTarget || tcTarget->canTarget(d->target))
){ ){
+8 -1
View File
@@ -7,7 +7,7 @@
TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInstance * card){ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInstance * card, MTGAbility * ability){
if (!s.size()) return NULL; if (!s.size()) return NULL;
int zones[10]; int zones[10];
@@ -15,6 +15,13 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
size_t found; size_t found;
bool other = false; bool other = false;
found = s.find("mytgt");
if (found == 0){
MTGCardInstance * target = card->target;
if (ability) target = (MTGCardInstance *) (ability->target);
return NEW CardTargetChooser(target,card);
};
found = s.find("other "); found = s.find("other ");
if (found == 0){ if (found == 0){
other = true; other = true;