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.
|
||||
id=1108
|
||||
name=Ebony Horse
|
||||
auto={2}{T}:untap target(creature[attacking]|myBattlefield) && preventAllCombatDamage to(mytgt) ueot && preventAllCombatDamage from(mytgt) ueot
|
||||
rarity=R
|
||||
mana={3}
|
||||
type=Artifact
|
||||
|
||||
@@ -121,6 +121,7 @@ drift_of_the_dead.txt
|
||||
dromad_purebred.txt
|
||||
dross_harvester.txt
|
||||
duskwalker.txt
|
||||
ebony_horse.txt
|
||||
elvish_piper.txt
|
||||
elvish_promenade.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
|
||||
*/
|
||||
@@ -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
|
||||
class AFarmstead:public ActivatedAbility{
|
||||
public:
|
||||
|
||||
@@ -13,6 +13,10 @@ class GameObserver;
|
||||
#define DAMAGEABLE_MTGCARDINSTANCE 0
|
||||
#define DAMAGEABLE_PLAYER 1
|
||||
|
||||
#define DAMAGE_ALL_TYPES 0
|
||||
#define DAMAGE_COMBAT 1
|
||||
#define DAMAGE_OTHER 2
|
||||
|
||||
class Damageable:public Targetable {
|
||||
protected:
|
||||
|
||||
@@ -28,13 +32,14 @@ class Damageable:public Targetable {
|
||||
|
||||
class Damage: public Interruptible {
|
||||
protected:
|
||||
void init(MTGCardInstance * source, Damageable * target, int damage);
|
||||
void init(MTGCardInstance * source, Damageable * target, int damage, int typeOfDamage);
|
||||
public:
|
||||
Damageable * target;
|
||||
int typeOfDamage;
|
||||
int damage;
|
||||
void Render();
|
||||
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();
|
||||
virtual ostream& toString(ostream& out) const;
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ class PlayGuiObject: public JGuiObject, public JGuiListener, public Pos{
|
||||
float defaultHeight;
|
||||
bool mHasFocus;
|
||||
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 CheckUserInput(u32 key) {return false;};
|
||||
virtual bool ButtonPressed(){return true;};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <list>
|
||||
using namespace std;
|
||||
#include "../include/Damage.h"
|
||||
#include "WEvent.h"
|
||||
|
||||
class TargetChooser;
|
||||
@@ -21,8 +22,9 @@ protected:
|
||||
TargetChooser * tcTarget;
|
||||
int damage;
|
||||
bool oneShot;
|
||||
int typeOfDamage;
|
||||
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);
|
||||
~REDamagePrevention();
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ class TargetChooser: public TargetsList {
|
||||
|
||||
class TargetChooserFactory{
|
||||
public:
|
||||
TargetChooser * createTargetChooser(string s, MTGCardInstance * card);
|
||||
TargetChooser * createTargetChooser(string s, MTGCardInstance * card, MTGAbility * ability = NULL);
|
||||
TargetChooser * createTargetChooser(MTGCardInstance * card);
|
||||
};
|
||||
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
#include "../include/WResourceManager.h"
|
||||
|
||||
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) {
|
||||
init(source, target, damage);
|
||||
Damage::Damage(MTGCardInstance * source, Damageable * target, int damage,int _typeOfDamage) {
|
||||
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;
|
||||
source = _source;
|
||||
|
||||
@@ -70,7 +71,6 @@ int Damage::resolve(){
|
||||
//Send (Damage/Replaced effect) event to listeners
|
||||
|
||||
g->receiveEvent(e);
|
||||
//SAFE_DELETE(e);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ void DamagerDamaged::addDamage(int damage, DamagerDamaged* source){
|
||||
if (0 >= i->damage) damages.erase(i);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ int GuiCombat::resolve() // Returns the number of damage objects dealt this turn
|
||||
stack->Add(NEW Damage(*d));
|
||||
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)
|
||||
stack->Add(NEW Damage(*d));
|
||||
}
|
||||
|
||||
@@ -370,7 +370,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
//Regeneration
|
||||
found = s.find("regenerate");
|
||||
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(" 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
|
||||
found = s.find("damage");
|
||||
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)
|
||||
@@ -983,12 +1013,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
|
||||
game->addObserver(NEW ADragonWhelp(_id,card));
|
||||
break;
|
||||
}
|
||||
case 1108: //Ebony Horse
|
||||
{
|
||||
AEbonyHorse * ability = NEW AEbonyHorse(_id,card);
|
||||
game->addObserver(ability);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1345: //Farmstead
|
||||
{
|
||||
game->addObserver(NEW AFarmstead(_id, card,card->target));
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
#include "../include/ReplacementEffects.h"
|
||||
#include "../include/MTGCardInstance.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){
|
||||
@@ -14,6 +14,7 @@ WEvent * REDamagePrevention::replace (WEvent *event){
|
||||
WEventDamage * e = dynamic_cast<WEventDamage*>(event);
|
||||
if (!e) return event;
|
||||
Damage *d = e->damage;
|
||||
if (d->typeOfDamage != typeOfDamage && typeOfDamage != DAMAGE_ALL_TYPES) return event;
|
||||
if ((!tcSource || tcSource->canTarget(d->source)) &&
|
||||
(!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;
|
||||
|
||||
int zones[10];
|
||||
@@ -15,6 +15,13 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
size_t found;
|
||||
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 ");
|
||||
if (found == 0){
|
||||
other = true;
|
||||
|
||||
Reference in New Issue
Block a user