- Fixed a bug with Composite golem (and summoning sickness for Mana abilities in general)
- Improved test suite speed
This commit is contained in:
wagic.the.homebrew
2009-02-06 16:06:37 +00:00
parent bd632ed346
commit 6ea40147a3
7 changed files with 233 additions and 192 deletions
+1
View File
@@ -21,6 +21,7 @@ ascendant_evincar2.txt
brass_man.txt brass_man.txt
castle.txt castle.txt
circle_of_protection.txt circle_of_protection.txt
composite_golem.txt
control_magic.txt control_magic.txt
control_magic2.txt control_magic2.txt
counsel_of_the_soratami.txt counsel_of_the_soratami.txt
@@ -0,0 +1,16 @@
#Composite golem sacrifice ability subject to summoning Sickness ?
SummoningSickness
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:135275
[PLAYER2]
[DO]
135275
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:135275
manapool:{W}{U}{B}{R}{G}
[PLAYER2]
[END]
-188
View File
@@ -616,195 +616,7 @@ class ASpellCounterEnchantment:public TargetAbility{
}; };
/*Mana Producers (lands)
//These have a reactToClick function, and therefore two manaProducers on the same card conflict with each other
//That means the player has to choose one. although that is perfect for cards such as birds of paradise or badlands,
other solutions need to be provided for abilities that add mana (ex: mana flare)
*/
/*
Currently the mana is added to the pool AFTER the animation
This is VERY BAD, since we don't have any control on the duration of the animation. This can lead to bugs with
the AI, who is expecting to have the mana in its manapool right after clicking the land card !!!
The sum of "dt" has to be 0.25 for the mana to be in the manapool currently
*/
class AManaProducer: public MTGAbility{
protected:
static int currentlyTapping;
ManaCost * cost;
ManaCost * output;
string menutext;
float x0,y0,x1,y1,x,y;
float animation;
Player * controller;
hgeParticleSystem * mParticleSys;
public:
AManaProducer(int id, MTGCardInstance * card, ManaCost * _output, ManaCost * _cost = NULL ):MTGAbility(id, card){
LOG("==Creating ManaProducer Object");
if (!_cost) OutputDebugString("NO COST???\n");
cost = _cost;
output=_output;
x1 = 10;
y1 = 220;
Player * player = card->controller();
if (player == game->players[1]) y1 = 100;
x = x1;
y = y1;
animation = 0.f;
mParticleSys = NULL;
menutext = "";
int landColor = output->getMainColor();
if (landColor == Constants::MTG_COLOR_RED){
mParticleSys = NEW hgeParticleSystem("graphics/manared.psi",GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_BLUE){
mParticleSys = NEW hgeParticleSystem("graphics/manablue.psi", GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_GREEN){
mParticleSys = NEW hgeParticleSystem("graphics/managreen.psi", GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_BLACK){
mParticleSys = NEW hgeParticleSystem("graphics/manablack.psi", GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_WHITE){
mParticleSys = NEW hgeParticleSystem("graphics/manawhite.psi", GameApp::CommonRes->GetQuad("particles"));
}else{
mParticleSys = NEW hgeParticleSystem("graphics/mana.psi", GameApp::CommonRes->GetQuad("particles"));
}
LOG("==ManaProducer Object Creation successful !");
}
void Update(float dt){
if (mParticleSys) mParticleSys->Update(dt);
if (animation){
x = (1.f - animation)*x1 + animation * x0;
y = (1.f - animation)*y1 + animation * y0;
if (mParticleSys) mParticleSys->MoveTo(x, y);
if (mParticleSys && animation == 1.f) mParticleSys->Fire();
animation -= 4 *dt;
if (!animation) animation = -1;
if (animation < 0){
animation = 0;
currentlyTapping--;
resolve();
if (mParticleSys) mParticleSys->Stop();
}
}
}
void Render(){
JRenderer * renderer = JRenderer::GetInstance();
if (animation){
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE);
if (mParticleSys) mParticleSys->Render();
// set normal blending
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
}
}
int isReactingToClick(MTGCardInstance * _card){
int result = 0;
if (_card == source && !source->isTapped() && game->currentlyActing()->game->inPlay->hasCard(source) && (source->hasType("land") || !source->hasSummoningSickness()) ){
if (!cost || game->currentlyActing()->getManaPool()->canAfford(cost)) result = 1;
}
return result;
}
int resolve(){
controller = source->controller();
controller->getManaPool()->add(output);
return 1;
}
int reactToClick(MTGCardInstance * _card){
if (!isReactingToClick( _card)) return 0;
OutputDebugString("React To click 1\n");
if (cost){
cost->setExtraCostsAction(this, _card);
OutputDebugString("React To click 2\n");
if (!cost->isExtraPaymentSet()){
OutputDebugString("React To click 3\n");
GameObserver::GetInstance()->waitForExtraPayment = cost->extraCosts;
return 0;
}
GameObserver::GetInstance()->currentlyActing()->getManaPool()->pay(cost);
cost->doPayExtra();
}
source->tapped = 1;
currentlyTapping++;
animation = 1.f;
CardGui * cardg = game->mLayers->playLayer()->getByCard(source);
if (cardg){
x0 = cardg->x + 15;
y0 = cardg->y + 20;
}
if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME].getIntValue() > 0 && currentlyTapping < 3){
JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/mana.wav");
if (sample) JSoundSystem::GetInstance()->PlaySample(sample);
}
return 1;
}
const char * getMenuText(){
if (menutext.size())return menutext.c_str();
menutext = "Add ";
char buffer[128];
int alreadyHasOne = 0;
for (int i= 0; i < 6; i++){
int value = output->getCost(i);
if (value){
if (alreadyHasOne) menutext.append(",");
sprintf(buffer, "%i ", value);
menutext.append(buffer);
switch (i){
case Constants::MTG_COLOR_RED:
menutext.append("red");
break;
case Constants::MTG_COLOR_BLUE:
menutext.append("blue");
break;
case Constants::MTG_COLOR_GREEN:
menutext.append("green");
break;
case Constants::MTG_COLOR_WHITE:
menutext.append("white");
break;
case Constants::MTG_COLOR_BLACK:
menutext.append("black");
break;
default:
break;
}
alreadyHasOne = 1;
}
}
menutext.append(" mana");
return menutext.c_str();
}
int testDestroy(){
if (animation >0) return 0;
return MTGAbility::testDestroy();
}
~AManaProducer(){
LOG("==Destroying ManaProducer Object");
SAFE_DELETE(cost);
SAFE_DELETE(output);
SAFE_DELETE(mParticleSys);
LOG("==Destroying ManaProducer Object Successful!");
}
};
int AManaProducer::currentlyTapping = 0;
/* Lifelink Ability */ /* Lifelink Ability */
class ALifeLink:public MTGAbility{ class ALifeLink:public MTGAbility{
+27
View File
@@ -12,10 +12,12 @@ class TargetChooser;
class ManaCost; class ManaCost;
class MTGGameZone; class MTGGameZone;
class Player; class Player;
class AManaProducer;
#include "ActionElement.h" #include "ActionElement.h"
#include <string> #include <string>
#include <map> #include <map>
#include <hge/hgeparticle.h>
using std::string; using std::string;
using std::map; using std::map;
@@ -207,6 +209,31 @@ class AbilityFactory{
}; };
class AManaProducer: public MTGAbility{
protected:
ManaCost * cost;
ManaCost * output;
string menutext;
float x0,y0,x1,y1,x,y;
float animation;
Player * controller;
int tap;
hgeParticleSystem * mParticleSys;
public:
static int currentlyTapping;
AManaProducer(int id, MTGCardInstance * card, ManaCost * _output, ManaCost * _cost = NULL, int doTap = 1 );
void Update(float dt);
void Render();
int isReactingToClick(MTGCardInstance * _card);
int resolve();
int reactToClick(MTGCardInstance * _card);
const char * getMenuText();
int testDestroy();
~AManaProducer();
};
#include "MTGCardInstance.h" #include "MTGCardInstance.h"
#endif #endif
+1
View File
@@ -47,6 +47,7 @@ class TestSuiteState{
}; };
class TestSuite{ class TestSuite{
public: public:
int summoningSickness;
float timerLimit; float timerLimit;
int currentAction; int currentAction;
TestSuiteState initState; TestSuiteState initState;
+179 -1
View File
@@ -518,7 +518,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
if (input->isNull()){ if (input->isNull()){
SAFE_DELETE(input); SAFE_DELETE(input);
} }
MTGAbility * a = NEW AManaProducer(id, target, output, input); MTGAbility * a = NEW AManaProducer(id, target, output, input,doTap);
if (multi){ if (multi){
multi->Add(a); multi->Add(a);
}else{ }else{
@@ -1973,3 +1973,181 @@ GenericTriggeredAbility::~GenericTriggeredAbility(){
delete te; delete te;
SAFE_DELETE(dc); SAFE_DELETE(dc);
} }
/*Mana Producers (lands)
//These have a reactToClick function, and therefore two manaProducers on the same card conflict with each other
//That means the player has to choose one. although that is perfect for cards such as birds of paradise or badlands,
other solutions need to be provided for abilities that add mana (ex: mana flare)
*/
/*
Currently the mana is added to the pool AFTER the animation
This is VERY BAD, since we don't have any control on the duration of the animation. This can lead to bugs with
the AI, who is expecting to have the mana in its manapool right after clicking the land card !!!
The sum of "dt" has to be 0.25 for the mana to be in the manapool currently
*/
AManaProducer::AManaProducer(int id, MTGCardInstance * card, ManaCost * _output, ManaCost * _cost , int doTap):MTGAbility(id, card), tap(doTap){
LOG("==Creating ManaProducer Object");
cost = _cost;
output=_output;
x1 = 10;
y1 = 220;
Player * player = card->controller();
if (player == game->players[1]) y1 = 100;
x = x1;
y = y1;
animation = 0.f;
mParticleSys = NULL;
menutext = "";
int landColor = output->getMainColor();
if (landColor == Constants::MTG_COLOR_RED){
mParticleSys = NEW hgeParticleSystem("graphics/manared.psi",GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_BLUE){
mParticleSys = NEW hgeParticleSystem("graphics/manablue.psi", GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_GREEN){
mParticleSys = NEW hgeParticleSystem("graphics/managreen.psi", GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_BLACK){
mParticleSys = NEW hgeParticleSystem("graphics/manablack.psi", GameApp::CommonRes->GetQuad("particles"));
}else if (landColor == Constants::MTG_COLOR_WHITE){
mParticleSys = NEW hgeParticleSystem("graphics/manawhite.psi", GameApp::CommonRes->GetQuad("particles"));
}else{
mParticleSys = NEW hgeParticleSystem("graphics/mana.psi", GameApp::CommonRes->GetQuad("particles"));
}
LOG("==ManaProducer Object Creation successful !");
}
void AManaProducer::Update(float dt){
if (mParticleSys) mParticleSys->Update(dt);
if (animation){
x = (1.f - animation)*x1 + animation * x0;
y = (1.f - animation)*y1 + animation * y0;
if (mParticleSys) mParticleSys->MoveTo(x, y);
if (mParticleSys && animation == 1.f) mParticleSys->Fire();
animation -= 4 *dt;
if (!animation) animation = -1;
if (animation < 0){
animation = 0;
currentlyTapping--;
resolve();
if (mParticleSys) mParticleSys->Stop();
}
}
}
void AManaProducer::Render(){
JRenderer * renderer = JRenderer::GetInstance();
if (animation){
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE);
if (mParticleSys) mParticleSys->Render();
// set normal blending
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
}
}
int AManaProducer::isReactingToClick(MTGCardInstance * _card){
int result = 0;
if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source) && (source->hasType("land") || !tap || !source->hasSummoningSickness()) ){
if (!cost || game->currentlyActing()->getManaPool()->canAfford(cost)) result = 1;
}
return result;
}
int AManaProducer::resolve(){
controller = source->controller();
controller->getManaPool()->add(output);
return 1;
}
int AManaProducer::reactToClick(MTGCardInstance * _card){
if (!isReactingToClick( _card)) return 0;
OutputDebugString("React To click 1\n");
if (cost){
cost->setExtraCostsAction(this, _card);
OutputDebugString("React To click 2\n");
if (!cost->isExtraPaymentSet()){
OutputDebugString("React To click 3\n");
GameObserver::GetInstance()->waitForExtraPayment = cost->extraCosts;
return 0;
}
GameObserver::GetInstance()->currentlyActing()->getManaPool()->pay(cost);
cost->doPayExtra();
}
if (tap) source->tapped = 1;
currentlyTapping++;
animation = 1.f;
CardGui * cardg = game->mLayers->playLayer()->getByCard(source);
if (cardg){
x0 = cardg->x + 15;
y0 = cardg->y + 20;
}
if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME].getIntValue() > 0 && currentlyTapping < 3){
JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/mana.wav");
if (sample) JSoundSystem::GetInstance()->PlaySample(sample);
}
return 1;
}
const char * AManaProducer::getMenuText(){
if (menutext.size())return menutext.c_str();
menutext = "Add ";
char buffer[128];
int alreadyHasOne = 0;
for (int i= 0; i < 6; i++){
int value = output->getCost(i);
if (value){
if (alreadyHasOne) menutext.append(",");
sprintf(buffer, "%i ", value);
menutext.append(buffer);
switch (i){
case Constants::MTG_COLOR_RED:
menutext.append("red");
break;
case Constants::MTG_COLOR_BLUE:
menutext.append("blue");
break;
case Constants::MTG_COLOR_GREEN:
menutext.append("green");
break;
case Constants::MTG_COLOR_WHITE:
menutext.append("white");
break;
case Constants::MTG_COLOR_BLACK:
menutext.append("black");
break;
default:
break;
}
alreadyHasOne = 1;
}
}
menutext.append(" mana");
return menutext.c_str();
}
int AManaProducer::testDestroy(){
if (animation >0) return 0;
return MTGAbility::testDestroy();
}
AManaProducer::~AManaProducer(){
LOG("==Destroying ManaProducer Object");
SAFE_DELETE(cost);
SAFE_DELETE(output);
SAFE_DELETE(mParticleSys);
LOG("==Destroying ManaProducer Object Successful!");
}
int AManaProducer::currentlyTapping = 0;
+9 -3
View File
@@ -1,5 +1,6 @@
#include "../include/TestSuiteAI.h" #include "../include/TestSuiteAI.h"
#include "../include/config.h" #include "../include/config.h"
#include "../include/MTGAbility.h"
#include <string> #include <string>
using std::string; using std::string;
@@ -45,7 +46,7 @@ int TestSuiteAI::Act(float dt){
GameObserver * g = GameObserver::GetInstance(); GameObserver * g = GameObserver::GetInstance();
g->gameOver = NULL; // Prevent draw rule from losing the game g->gameOver = NULL; // Prevent draw rule from losing the game
timer+= dt; timer+= dt;
if (timer < suite->timerLimit) return 1; if (AManaProducer::currentlyTapping || timer < suite->timerLimit) return 1;
timer = 0; timer = 0;
string action = suite->getNextAction(); string action = suite->getNextAction();
@@ -212,7 +213,7 @@ void TestSuite::initGame(){
if (!timerLimit){ if (!timerLimit){
timerLimit = 0.3; timerLimit = 0.3;
}else{ }else{
timerLimit = 0.26; timerLimit = 0.1;
} }
//Put the GameObserver in the initial state //Put the GameObserver in the initial state
GameObserver * g = GameObserver::GetInstance(); GameObserver * g = GameObserver::GetInstance();
@@ -237,7 +238,7 @@ void TestSuite::initGame(){
Spell * spell = NEW Spell(card); Spell * spell = NEW Spell(card);
p->game->putInZone(card, p->game->hand, p->game->stack); p->game->putInZone(card, p->game->hand, p->game->stack);
spell->resolve(); spell->resolve();
card->summoningSickness = 0; if (!summoningSickness) card->summoningSickness = 0;
delete spell; delete spell;
}else{ }else{
if (!p->game->library->hasCard(card)){ if (!p->game->library->hasCard(card)){
@@ -358,6 +359,7 @@ TestSuite::TestSuite(const char * filename){
} }
int TestSuite::loadNext(){ int TestSuite::loadNext(){
summoningSickness = 0;
if (!nbfiles) return 0; if (!nbfiles) return 0;
if (currentfile >= nbfiles) return 0; if (currentfile >= nbfiles) return 0;
load(files[currentfile].c_str()); load(files[currentfile].c_str());
@@ -430,6 +432,10 @@ void TestSuite::load(const char * _filename){
if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files if (s[s.size()-1] == '\r') s.erase(s.size()-1); //Handle DOS files
if (s[0] == '#') continue; if (s[0] == '#') continue;
std::transform( s.begin(), s.end(), s.begin(),::tolower ); std::transform( s.begin(), s.end(), s.begin(),::tolower );
if (s.compare("summoningsickness") == 0) {
summoningSickness = 1;
continue;
}
switch(state){ switch(state){
case -1: case -1:
if (s.compare("[init]") == 0) state++; if (s.compare("[init]") == 0) state++;