Erwan
- Magic 2010: Combat Damages don't go on the stack anymore - Comp rules: "goes to graveyard" effects don't go on the stack anymore - Regenerate "fixed" (untested) - Basic "ReplacementEffect" mechanism for damage prevention. Can be extended to other replacement effects with some limits. - TODO: Damages don't go on the stack, the abilities that create them do.
This commit is contained in:
@@ -45,12 +45,17 @@ int Damage::resolve(){
|
||||
_target->doDamageTest = 1;
|
||||
}
|
||||
|
||||
int a = target->dealDamage(damage);
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
WEvent * e = NEW WEventDamage(this);
|
||||
e = g->replacementEffects->replace(e);
|
||||
|
||||
//Send Damage event to listeners
|
||||
WEventDamage * e = NEW WEventDamage(this);
|
||||
GameObserver::GetInstance()->receiveEvent(e);
|
||||
delete e;
|
||||
int a = 0;
|
||||
if (damage) a = target->dealDamage(damage);
|
||||
|
||||
//Send (Damage/Replaced effect) event to listeners
|
||||
|
||||
g->receiveEvent(e);
|
||||
SAFE_DELETE(e);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -169,6 +169,7 @@ int DamageResolverLayer::initResolve(){
|
||||
if (empty()){
|
||||
if (!damageStack->empty()){
|
||||
game->mLayers->stackLayer()->addAction(damageStack);
|
||||
game->mLayers->stackLayer()->resolve(); //Wagic 2010
|
||||
}else{
|
||||
SAFE_DELETE(damageStack);
|
||||
}
|
||||
@@ -246,6 +247,7 @@ int DamageResolverLayer::resolveDamages(){
|
||||
}
|
||||
}
|
||||
game->mLayers->stackLayer()->addAction(damageStack);
|
||||
game->mLayers->stackLayer()->resolve(); //Wagic 2010
|
||||
remainingDamageSteps--;
|
||||
resetObjects();
|
||||
damageStack = NULL;
|
||||
|
||||
@@ -51,6 +51,7 @@ GameObserver::GameObserver(Player * _players[], int _nb_players){
|
||||
reaction = 0;
|
||||
gameOver = NULL;
|
||||
phaseRing = NEW PhaseRing(_players,_nb_players);
|
||||
replacementEffects = NEW ReplacementEffects();
|
||||
}
|
||||
|
||||
void GameObserver::setGamePhaseManager(MTGGamePhase * _phases){
|
||||
@@ -229,6 +230,7 @@ GameObserver::~GameObserver(){
|
||||
SAFE_DELETE(targetChooser);
|
||||
SAFE_DELETE(mLayers);
|
||||
SAFE_DELETE(phaseRing);
|
||||
SAFE_DELETE(replacementEffects);
|
||||
LOG("==GameObserver Destroyed==");
|
||||
|
||||
}
|
||||
@@ -442,6 +444,7 @@ void GameObserver::untapPhase(){
|
||||
}
|
||||
|
||||
int GameObserver::receiveEvent(WEvent * e){
|
||||
if (!e) return 0;
|
||||
return mLayers->receiveEvent(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,14 +37,12 @@ int AbilityFactory::destroyAllInPlay(TargetChooser * tc, int bury){
|
||||
tc->source = NULL; // This is to prevent protection from... as objects that destroy all do not actually target
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
for (int i = 0; i < 2 ; i++){
|
||||
for (int j = game->players[i]->game->inPlay->nb_cards-1; j >=0 ; j--){
|
||||
MTGCardInstance * current = game->players[i]->game->inPlay->cards[j];
|
||||
Player * p = game->players[i];
|
||||
for (int j = p->game->inPlay->nb_cards-1; j >=0 ; j--){
|
||||
MTGCardInstance * current = p->game->inPlay->cards[j];
|
||||
if (tc->canTarget(current)){
|
||||
if (bury){
|
||||
game->players[i]->game->putInGraveyard(current);
|
||||
}else{
|
||||
game->mLayers->stackLayer()->addPutInGraveyard(current);
|
||||
}
|
||||
if (bury) current->bury();
|
||||
else current->destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,7 +544,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
|
||||
if (tc){
|
||||
game->addObserver(NEW ABurier(id, card,tc));
|
||||
}else{
|
||||
target->controller()->game->putInGraveyard(target);
|
||||
target->bury();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -584,7 +582,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
|
||||
if (tc){
|
||||
game->addObserver(NEW ADestroyer(id, card,tc,0,cost));
|
||||
}else{
|
||||
game->mLayers->stackLayer()->addPutInGraveyard(target);
|
||||
target->destroy();
|
||||
}
|
||||
}
|
||||
result++;
|
||||
@@ -1605,19 +1603,19 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
|
||||
int _x = x;
|
||||
MTGCardInstance * target = spell->getNextCardTarget();
|
||||
while(target && _x){
|
||||
game->mLayers->stackLayer()->addPutInGraveyard(target);
|
||||
_x--;
|
||||
target = spell->getNextCardTarget(target);
|
||||
target->destroy();
|
||||
_x--;
|
||||
target = spell->getNextCardTarget(target);
|
||||
}
|
||||
x-=_x;
|
||||
for (int i = 0; i < 2 ; i++){
|
||||
game->mLayers->stackLayer()->addDamage(card, game->players[i], x);
|
||||
for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++){
|
||||
MTGCardInstance * current = game->players[i]->game->inPlay->cards[j];
|
||||
if (current->isACreature()){
|
||||
game->mLayers->stackLayer()->addDamage(card, current, x);
|
||||
}
|
||||
}
|
||||
game->mLayers->stackLayer()->addDamage(card, game->players[i], x);
|
||||
for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++){
|
||||
MTGCardInstance * current = game->players[i]->game->inPlay->cards[j];
|
||||
if (current->isACreature()){
|
||||
game->mLayers->stackLayer()->addDamage(card, current, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ void MTGCardInstance::initMTGCI(){
|
||||
previous = NULL;
|
||||
next = NULL;
|
||||
lastController = NULL;
|
||||
regenerateTokens = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,13 +129,20 @@ int MTGCardInstance::afterDamage(){
|
||||
doDamageTest = 0;
|
||||
if (!isACreature()) return 0;
|
||||
if (life <=0 && isInPlay()){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
game->mLayers->stackLayer()->addPutInGraveyard(this);
|
||||
return 1;
|
||||
return destroy();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGCardInstance::bury(){
|
||||
Player * p = controller();
|
||||
p->game->putInZone(this,p->game->inPlay,owner->game->graveyard);
|
||||
return 1;
|
||||
}
|
||||
int MTGCardInstance::destroy(){
|
||||
if (!triggerRegenerate()) return bury();
|
||||
return 0;
|
||||
}
|
||||
|
||||
MTGGameZone * MTGCardInstance::getCurrentZone(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
@@ -194,10 +202,17 @@ void MTGCardInstance::resetAllDamage(){
|
||||
nb_damages = 0;
|
||||
}
|
||||
|
||||
void MTGCardInstance::regenerate(){
|
||||
int MTGCardInstance::regenerate(){
|
||||
return ++regenerateTokens;
|
||||
}
|
||||
|
||||
int MTGCardInstance::triggerRegenerate(){
|
||||
if (! regenerateTokens) return 0;
|
||||
regenerateTokens--;
|
||||
tapped = 1;
|
||||
life = toughness;
|
||||
initAttackersDefensers();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +232,7 @@ int MTGCardInstance::cleanup(){
|
||||
if (previous && !previous->stillInUse()){
|
||||
SAFE_DELETE(previous);
|
||||
}
|
||||
regenerateTokens = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "../include/config.h"
|
||||
#include "../include/ReplacementEffects.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/TargetChooser.h"
|
||||
#include "../include/Damage.h"
|
||||
|
||||
|
||||
REDamagePrevention::REDamagePrevention(TargetChooser *_tcSource, TargetChooser *_tcTarget,int _damage, bool _oneShot):damage(_damage), tcSource(_tcSource), tcTarget(_tcTarget), oneShot(_oneShot){
|
||||
}
|
||||
|
||||
WEvent * REDamagePrevention::replace (WEvent *event){
|
||||
if (!event) return event;
|
||||
if (!damage) return event;
|
||||
WEventDamage * e = dynamic_cast<WEventDamage*>(event);
|
||||
if (!e) return event;
|
||||
Damage *d = e->damage;
|
||||
if ((!tcSource || tcSource->canTarget(d->source)) &&
|
||||
(!tcTarget || tcTarget->canTarget(d->target))
|
||||
){
|
||||
if (damage == -1){
|
||||
d->damage = 0;
|
||||
delete event;
|
||||
if (oneShot) damage = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (damage >= d->damage){
|
||||
damage-= d->damage;
|
||||
d->damage = 0;
|
||||
delete event;
|
||||
return NULL;
|
||||
}
|
||||
d->damage -= damage;
|
||||
damage = 0;
|
||||
delete event;
|
||||
WEventDamage* newEvent = NEW WEventDamage(d);
|
||||
return newEvent;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
REDamagePrevention::~REDamagePrevention(){
|
||||
SAFE_DELETE(tcSource);
|
||||
SAFE_DELETE(tcTarget);
|
||||
}
|
||||
|
||||
ReplacementEffects::ReplacementEffects(){}
|
||||
|
||||
WEvent * ReplacementEffects::replace(WEvent *e){
|
||||
list<ReplacementEffect *>::iterator it;
|
||||
|
||||
for ( it=modifiers.begin() ; it != modifiers.end(); it++ ){
|
||||
ReplacementEffect *re = *it;
|
||||
WEvent * newEvent = re->replace(e);
|
||||
if (!newEvent) return NULL;
|
||||
if (newEvent != e) return replace(newEvent);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int ReplacementEffects::add(ReplacementEffect * re){
|
||||
modifiers.push_back(re);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ReplacementEffects::remove (ReplacementEffect *re){
|
||||
modifiers.remove(re);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ReplacementEffects::~ReplacementEffects(){
|
||||
list<ReplacementEffect *>::iterator it;
|
||||
for ( it=modifiers.begin() ; it != modifiers.end(); it++ ){
|
||||
ReplacementEffect *re = *it;
|
||||
delete(re);
|
||||
}
|
||||
modifiers.clear();
|
||||
}
|
||||
@@ -330,7 +330,21 @@ int TargetChooser::targetListSet(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
a specific Card
|
||||
**/
|
||||
CardTargetChooser::CardTargetChooser(MTGCardInstance * _card, MTGCardInstance * source):TargetChooser(source){
|
||||
validTarget = _card;
|
||||
}
|
||||
|
||||
int CardTargetChooser::canTarget(Targetable * target ){
|
||||
if (!TargetChooser::canTarget(target)) return 0;
|
||||
if (target->typeAsTarget() == TARGET_CARD){
|
||||
MTGCardInstance * card = (MTGCardInstance *) target;
|
||||
if (card == validTarget) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Choose anything that has a given list of types
|
||||
@@ -522,9 +536,15 @@ int TargetZoneChooser::targetsZone(MTGGameZone * z){
|
||||
}
|
||||
|
||||
/* Player Target */
|
||||
|
||||
PlayerTargetChooser::PlayerTargetChooser(MTGCardInstance * card, int _maxtargets, Player *_p):TargetChooser(card, _maxtargets){
|
||||
p = _p;
|
||||
}
|
||||
|
||||
int PlayerTargetChooser::canTarget(Targetable * target){
|
||||
if (target->typeAsTarget() == TARGET_PLAYER){
|
||||
return 1;
|
||||
Player * _target = (Player *) target;
|
||||
if (!p || p == _target) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user