- Trying to add generic classes for Triggered abilities. PLEASE DO NOT USE THESE RIGHT NOW, Not Tested AT ALL !
This commit is contained in:
wagic.the.homebrew
2008-11-12 14:38:30 +00:00
parent c97dd1f260
commit a418e10c47
6 changed files with 5003 additions and 5024 deletions

View File

@@ -29,7 +29,6 @@ class ActionElement: public JGuiObject{
int newPhase;
int modal;
int waitingForAnswer;
void RenderMessageBackground(float y0, int height);
int getActivity();
virtual void Update(float dt){};
virtual void Render(){};

File diff suppressed because it is too large Load Diff

View File

@@ -20,18 +20,12 @@ using std::string;
using std::map;
//Two stupid variables used to give a hint to the AI:
// Should I cast a spell on an ennemy or friendly unit ?
#define BAKA_EFFECT_GOOD 10
#define BAKA_EFFECT_BAD 11
class AbilityFactory{
private:
int destroyAllFromTypeInPlay(const char * type, MTGCardInstance * source, int bury = 0);
int destroyAllFromColorInPlay(int color, MTGCardInstance * source, int bury = 0);
int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p);
public:
int magicText(int id, Spell * spell, MTGCardInstance * card = NULL);
void addAbilities(int _id, Spell * spell);
};
class MTGAbility: public ActionElement{
protected:
@@ -67,7 +61,7 @@ class TriggeredAbility:public MTGAbility{
class ActivatedAbility:public MTGAbility{
public:
public:
ManaCost * cost;
int playerturnonly;
int needsTapping;
@@ -80,7 +74,7 @@ class ActivatedAbility:public MTGAbility{
};
class TargetAbility:public ActivatedAbility{
public:
public:
TargetAbility(int id, MTGCardInstance * card, TargetChooser * _tc,ManaCost * _cost = NULL, int _playerturnonly = 0,int tap = 1);
TargetAbility(int id, MTGCardInstance * card,ManaCost * _cost = NULL, int _playerturnonly = 0,int tap = 1);
virtual void Update(float dt);
@@ -90,7 +84,7 @@ class TargetAbility:public ActivatedAbility{
};
class InstantAbility:public MTGAbility{
public:
public:
int init;
virtual void Update(float dt);
virtual int testDestroy();
@@ -101,7 +95,7 @@ class InstantAbility:public MTGAbility{
/* State based effects. This class works ONLY for InPlay and needs to be extended for other areas of the game !!! */
class ListMaintainerAbility:public MTGAbility{
public:
public:
map<MTGCardInstance *,bool> cards;
ListMaintainerAbility(int _id):MTGAbility(_id,NULL){};
ListMaintainerAbility(int _id, MTGCardInstance *_source):MTGAbility(_id, _source){};
@@ -113,6 +107,87 @@ class ListMaintainerAbility:public MTGAbility{
virtual int destroy();
};
/* An attempt to globalize triggered abilities as much as possible */
class MTGAbilityBasicFeatures{
public:
Damageable * target;
GameObserver * game;
MTGCardInstance * source;
MTGAbilityBasicFeatures();
MTGAbilityBasicFeatures(MTGCardInstance * _source, Damageable * _target = NULL);
void init(MTGCardInstance * _source, Damageable * _target = NULL);
};
class Trigger:public MTGAbilityBasicFeatures{
public:
virtual int trigger()=0;
virtual int testDestroy(){return 0;};
};
class TriggerAtPhase:public Trigger{
public:
int currentPhase, newPhase;
int phaseId;
TriggerAtPhase(int _phaseId);
virtual int trigger();
};
class TriggerNextPhase:public TriggerAtPhase{
public:
int destroyActivated;
TriggerNextPhase(int _phaseId);
virtual int testDestroy();
};
class TriggeredEvent:public MTGAbilityBasicFeatures{
public:
virtual int resolve()=0;
};
class DrawEvent:public TriggeredEvent{
public:
Player * player;
int nbcards;
DrawEvent(Player * _player, int _nbcards);
int resolve();
};
class DestroyCondition:public MTGAbilityBasicFeatures{
public:
virtual int testDestroy();
};
class GenericTriggeredAbility:public TriggeredAbility{
public:
Trigger * t;
TriggeredEvent * te;
DestroyCondition * dc;
GenericTriggeredAbility(int id, MTGCardInstance * _source, Trigger * _t, TriggeredEvent * _te, DestroyCondition * _dc = NULL, Damageable * _target = NULL);
virtual int trigger();
virtual int resolve();
virtual int testDestroy();
~GenericTriggeredAbility();
};
/* Ability Factory */
class AbilityFactory{
private:
int destroyAllFromTypeInPlay(const char * type, MTGCardInstance * source, int bury = 0);
int destroyAllFromColorInPlay(int color, MTGCardInstance * source, int bury = 0);
int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p);
Trigger * parseTrigger(string magicText);
public:
int magicText(int id, Spell * spell, MTGCardInstance * card = NULL);
void addAbilities(int _id, Spell * spell);
};
#include "MTGCardInstance.h"
#endif

View File

@@ -93,50 +93,46 @@ static int _b[7] = {20, 0, 140,15, 50,255,128};
#define MOUNTAINHOME 33
#define SWAMPHOME 34
#define PLAINSHOME 35
#define FLANKING 36
#define RAMPAGE1 37
#define NB_BASIC_ABILITIES 38
#define NB_BASIC_ABILITIES 36
static const char * MTGBasicAbilities[] = {
"trample",
"forestwalk",
"islandwalk",
"mountainwalk",
"swampwalk",
"plainwalk",
"flying",
"first strike",
"double strike",
"fear",
"flash",
"haste",
"lifelink",
"reach",
"shroud",
"vigilance",
"defender",
"banding",
"protection from green",
"protection from blue",
"protection from red",
"protection from black",
"protection from white",
"unblockable",
"wither",
"persist",
"retrace",
"exalted",
"legendary",
"shadow",
"reachshadow",
"foresthome",
"islandhome",
"moutainhome",
"swamphome",
"plainshome",
"flanking",
"rampage",
"trample",
"forestwalk",
"islandwalk",
"mountainwalk",
"swampwalk",
"plainwalk",
"flying",
"first strike",
"double strike",
"fear",
"flash",
"haste",
"lifelink",
"reach",
"shroud",
"vigilance",
"defender",
"banding",
"protection from green",
"protection from blue",
"protection from red",
"protection from black",
"protection from white",
"unblockable",
"wither",
"persist",
"retrace",
"exalted",
"legendary",
"shadow",
"reachshadow",
"foresthome",
"islandhome",
"moutainhome",
"swamphome",
"plainshome"
};
@@ -152,7 +148,7 @@ static const char * MTGBasicAbilities[] = {
static const char *MTGPhaseNames[] =
{
{
"---",
"Untap",
"Upkeep",
@@ -167,7 +163,25 @@ static const char *MTGPhaseNames[] =
"End of turn",
"cleanup",
"---"
};
};
static const char *MTGPhaseCodeNames[] =
{
"beginofturn",
"untap",
"upkeep",
"draw",
"firstmain",
"combatbegins",
"attackers",
"blockers",
"combatdamage",
"combatends",
"secondmain",
"endofturn",
"cleanup",
"beforenextturn"
};

View File

@@ -12,31 +12,6 @@ ActionElement::ActionElement(int id):JGuiObject(id){
tc = NULL;
}
/*
void ActionElement::RenderMessageBackground(float y0, int _height){
float height = _height;
PIXEL_TYPE colors_up[] =
{
ARGB(0,255,255,255),
ARGB(0,255,255,255),
ARGB(128,255,255,255),
ARGB(128,255,255,255)
};
PIXEL_TYPE colors_down[] =
{
ARGB(128,255,255,255),
ARGB(128,255,255,255),
ARGB(0,255,255,255),
ARGB(0,255,255,255)
};
JRenderer * renderer = JRenderer::GetInstance();
renderer->FillRect(0,y0,SCREEN_WIDTH,height/2,colors_up);
renderer->FillRect(0,y0+height/2,SCREEN_WIDTH,height/2,colors_down);
// mEngine->DrawLine(0,y0,SCREEN_WIDTH,y0,ARGB(128,255,255,255));
// mEngine->DrawLine(0,y0+height,SCREEN_WIDTH,y0+height,ARGB(128,255,255,255));
}*/
int ActionElement::getActivity(){

View File

@@ -50,7 +50,26 @@ int AbilityFactory::putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone
return 1;
}
//Some basic functionnalities that can be added automatically in the text file
Trigger * AbilityFactory::parseTrigger(string magicText){
int found = magicText.find("@");
if (found == string::npos) return NULL;
//Next Time...
found = magicText.find("next");
if (found != string::npos){
for (int i = 0; i < NB_MTG_PHASES; i++){
found = magicText.find(MTGPhaseCodeNames[i]);
if (found != string::npos){
return NEW TriggerNextPhase(i);
}
}
}
return NULL;
}
//Some basic functionalities that can be added automatically in the text file
int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
int dryMode = 0;
if (!spell) dryMode = 1;
@@ -60,7 +79,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
if (!target) target = card;
string magicText = card->magicText;
if (card->alias && magicText.size() == 0){
//An awful way to gat access to the aliasedcard
//An awful way to get access to the aliasedcard
magicText = GameObserver::GetInstance()->players[0]->game->collection->getCardById(card->alias)->magicText;
}
string s;
@@ -89,6 +108,13 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
int doTap = 0;
string lordType = "";
Trigger * trigger = parseTrigger(s);
//Dirty way to remove the trigger text (could get in the way)
if (trigger){
found = s.find(":");
s = s.substr(found+1);
}
//Tap in the cost ?
if (s.find("{t}") != string::npos) doTap = 1;
@@ -154,17 +180,6 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
result++;
continue;
}
//Tentative Destroyall not working char is not compatible with string variable
//found = s.find("destroyall(");
//if (found != string::npos){
// if (dryMode) return BAKA_EFFECT_GOOD;
// unsigned int end = s.find(")", found+11);
// if (end != string::npos){
// string type = s.substr(found+11,end-found-11).c_str();
// destroyAllFromTypeInPlay(type.c_str(), card);
// result++;
// continue;
//}
//Regeneration
found = s.find("}:regenerate");
@@ -211,10 +226,6 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
continue;
}
//Summon
//Reveal Take Target and put in in hand (should be also able to target hand since some card needs you to reveal a card in your hand
//Damage
found = s.find("damage");
if (found != string::npos){
@@ -266,7 +277,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
}
//Draw
found = s.find("draw");
found = s.find("draw:");
if (found != string::npos){
unsigned int start = s.find(":",found);
unsigned int end = s.find(" ",start);
@@ -278,6 +289,10 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
nbcards = atoi(s.substr(start+1).c_str());
}
if (dryMode) return BAKA_EFFECT_GOOD;
if (trigger){
DrawEvent * action = NEW DrawEvent(card->controller(),nbcards);
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action));
}else{
if (tc){
//TODO ?
}else{
@@ -288,6 +303,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
game->addObserver(NEW ADrawer(id,card,cost,nbcards,doTap));
}
}
}
result++;
continue;
}
@@ -450,7 +466,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
case 106525: //Ascendant Evincar
{
game->addObserver(NEW AColorLord(_id, card,MTG_COLOR_BLACK,-1,1,1));
game->addObserver(NEW AColorLord(_id, card,0,MTG_COLOR_BLACK,-1,-1));
game->addObserver(NEW AColorLord(_id + 1, card,0,MTG_COLOR_BLACK,-1,-1));
break;
}
@@ -975,6 +991,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
MTGPlayerCards * zones = card->target->controller()->game;
zones->putInZone(card->target,zones->inPlay,zones->hand);
break;
}
case 1235: //Aspect of Wolf
{
@@ -1270,78 +1287,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
break;
}
// Addons ALA
case 175114: // Master of Etherium
{
game->addObserver(NEW ACreaturePowerToughnessModifierForAllTypeControlled(_id,card,"artifact"));
break;
}
case 174989: // Wild Nacatl
{
game->addObserver(NEW AGenericKirdApe(_id,card,"plains",1,1));
game->addObserver(NEW AGenericKirdApe(_id,card,"moutain",1,1));
break;
}
//Addons The Dark
case 1797: //Inferno does 6 damage to all players and all creatures.
{
for (int i = 0; i < 2 ; i++){
game->mLayers->stackLayer()->addDamage(card, game->players[i], 6);
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, 6);
}
}
}
break;
}
case 1773 : //People of the Woods
{
game->addObserver(NEW APeopleOfTheWoods(_id, card));
break;
}
case 1818: //Tivadar's Crusade
{
destroyAllFromTypeInPlay("goblin", card);
break;
}
//Addons Legends
case 1470: //Acid Rain
{
destroyAllFromTypeInPlay("forest", card);
break;
}
case 1427: //Abomination
{
game->addObserver(NEW AAbomination(_id,card));
break;
}
case 1533: //Livingplane
{
game->addObserver(NEW AConvertLandToCreatures(id, card, "land"));
break;
}
case 1607: //Divine Offering
{
card->target->controller()->game->putInGraveyard(card->target);
game->currentlyActing()->life+= card->target->getManaCost()->getConvertedCost();
break;
}
case 1625: //Lifeblood
{
game->addObserver(NEW AGiveLifeForTappedType (_id, card, "island"));
break;
}
//Addons ICE-AGE Cards
//Addons ICE-AGE Cards
case 2631: //Jokulhaups
{
destroyAllFromTypeInPlay("artifact", card);
@@ -1470,12 +1416,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
if (card->basicAbilities[PLAINSHOME]){
game->addObserver(NEW AStrongLandLinkCreature(_id, card,"plains"));
}
// New Abilities Flanking and Rampage
if (card->basicAbilities [RAMPAGE1]){
game->addObserver (NEW ARampageAbility(_id, card, 1, 1));
}
//Instants are put in the graveyard automatically if that's not already done
if (!putSourceInGraveyard){
if (card->hasType("instant") || card->hasType("sorcery")){
@@ -1489,13 +1429,13 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
}
MTGAbility::MTGAbility(int id, MTGCardInstance * card):ActionElement(id){
game = GameObserver::GetInstance();;
game = GameObserver::GetInstance();
source = card;
target = card;
}
MTGAbility::MTGAbility(int id, MTGCardInstance * _source,Damageable * _target ):ActionElement(id){
game = GameObserver::GetInstance();;
game = GameObserver::GetInstance();
source = _source;
target = _target;
}
@@ -1632,44 +1572,44 @@ void TriggeredAbility::Update(float dt){
//
InstantAbility::InstantAbility(int _id, MTGCardInstance * source):MTGAbility(_id, source){
//
InstantAbility::InstantAbility(int _id, MTGCardInstance * source):MTGAbility(_id, source){
init = 0;
for (int i = 0; i < 2; i++){
if(game->players[i]->game->inPlay->hasCard(source)){
game->players[i]->game->putInGraveyard(source);
}
}
}
}
void InstantAbility::Update(float dt){
void InstantAbility::Update(float dt){
if (!init){
init = resolve();
}
}
}
InstantAbility::InstantAbility(int _id, MTGCardInstance * source, Damageable * _target):MTGAbility(_id, source, _target){
InstantAbility::InstantAbility(int _id, MTGCardInstance * source, Damageable * _target):MTGAbility(_id, source, _target){
init = 0;
for (int i = 0; i < 2; i++){
if(game->players[i]->game->inPlay->hasCard(source)){
game->players[i]->game->putInGraveyard(source);
}
}
}
}
//Instant abilities last generally until the end of the turn
int InstantAbility::testDestroy(){
//Instant abilities last generally until the end of the turn
int InstantAbility::testDestroy(){
int newPhase = game->getCurrentGamePhase();
if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP) return 1;
currentPhase = newPhase;
return 0;
}
}
void ListMaintainerAbility::Update(float dt){
void ListMaintainerAbility::Update(float dt){
map<MTGCardInstance *,bool>::iterator it=cards.begin();
while(it != cards.end()){
MTGCardInstance * card = (*it).first;
@@ -1688,7 +1628,7 @@ void ListMaintainerAbility::Update(float dt){
}
if (doDelete || !canBeInList(card)){
#if defined (WIN32) || defined (LINUX)
OutputDebugString("DELETE FRO LISTMAINTAINER\n");
OutputDebugString("DELETE FRO LISTMAINTAINER\n");
#endif
cards.erase(card);
removed(card);
@@ -1709,10 +1649,10 @@ void ListMaintainerAbility::Update(float dt){
}
}
}
}
}
//Destroy the spell -> remove all targets
int ListMaintainerAbility::destroy(){
//Destroy the spell -> remove all targets
int ListMaintainerAbility::destroy(){
map<MTGCardInstance *,bool>::iterator it;
for ( it=cards.begin() ; it != cards.end(); it++ ){
@@ -1720,4 +1660,104 @@ int ListMaintainerAbility::destroy(){
}
cards.clear();
return 1;
}
}
/* An attempt to globalize triggered abilities as much as possible */
MTGAbilityBasicFeatures::MTGAbilityBasicFeatures(){
game = GameObserver::GetInstance();
}
MTGAbilityBasicFeatures::MTGAbilityBasicFeatures(MTGCardInstance * _source, Damageable * _target):source(_source),target(_target){
if (!target) target = source;
game = GameObserver::GetInstance();
}
void MTGAbilityBasicFeatures::init(MTGCardInstance * _source, Damageable * _target){
source = source;
target=_target;
if (!target) target = source;
}
TriggerAtPhase::TriggerAtPhase(int _phaseId):Trigger(),phaseId(_phaseId){
currentPhase = game->getCurrentGamePhase();
newPhase = -1;
}
int TriggerAtPhase::trigger(){
int result = 0;
newPhase = game->getCurrentGamePhase();
if (currentPhase != newPhase && newPhase == phaseId){
result = 1;
}
currentPhase = newPhase;
return result;
}
TriggerNextPhase::TriggerNextPhase(int _phaseId):TriggerAtPhase(_phaseId){
destroyActivated = 0;
}
int TriggerNextPhase::testDestroy(){
if (newPhase <= phaseId) destroyActivated = 1;
if ( newPhase > phaseId && destroyActivated){
return 1;
}
return 0;
}
DrawEvent::DrawEvent(Player * _player, int _nbcards):TriggeredEvent(),player(_player),nbcards(_nbcards){
}
int DrawEvent::resolve(){
game->mLayers->stackLayer()->addDraw(player,nbcards);
return nbcards;
}
int DestroyCondition::testDestroy(){
if (!game->isInPlay(source)){
return 1;
}
if (target && !game->isInPlay((MTGCardInstance *)target)){
source->controller()->game->putInGraveyard(source);//TODO put this in a better place ???
return 1;
}
return 0;
}
GenericTriggeredAbility::GenericTriggeredAbility(int id, MTGCardInstance * _source, Trigger * _t, TriggeredEvent * _te, DestroyCondition * _dc , Damageable * _target ): TriggeredAbility(id, _source,_target){
if (!target) target = source;
t = _t;
te = _te;
dc = _dc;
t->init(_source,_target);
te->init(_source,_target);
if (dc) dc->init(_source,_target);
}
int GenericTriggeredAbility::trigger(){
return t->trigger();
}
int GenericTriggeredAbility::resolve(){
return te->resolve();
}
int GenericTriggeredAbility::testDestroy(){
if (dc) return dc->testDestroy();
return t->testDestroy();
}
GenericTriggeredAbility::~GenericTriggeredAbility(){
delete t;
delete te;
SAFE_DELETE(dc);
}