Erwan
- 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:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,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();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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))
|
||||||
){
|
){
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user