Erwan
- Fixed a bug with Composite golem (and summoning sickness for Mana abilities in general) - Improved test suite speed
This commit is contained in:
@@ -21,6 +21,7 @@ ascendant_evincar2.txt
|
||||
brass_man.txt
|
||||
castle.txt
|
||||
circle_of_protection.txt
|
||||
composite_golem.txt
|
||||
control_magic.txt
|
||||
control_magic2.txt
|
||||
counsel_of_the_soratami.txt
|
||||
|
||||
16
projects/mtg/bin/Res/test/composite_golem.txt
Normal file
16
projects/mtg/bin/Res/test/composite_golem.txt
Normal file
@@ -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]
|
||||
@@ -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 */
|
||||
class ALifeLink:public MTGAbility{
|
||||
|
||||
@@ -12,10 +12,12 @@ class TargetChooser;
|
||||
class ManaCost;
|
||||
class MTGGameZone;
|
||||
class Player;
|
||||
class AManaProducer;
|
||||
|
||||
#include "ActionElement.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <hge/hgeparticle.h>
|
||||
using std::string;
|
||||
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"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,7 @@ class TestSuiteState{
|
||||
};
|
||||
class TestSuite{
|
||||
public:
|
||||
int summoningSickness;
|
||||
float timerLimit;
|
||||
int currentAction;
|
||||
TestSuiteState initState;
|
||||
|
||||
@@ -518,7 +518,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
|
||||
if (input->isNull()){
|
||||
SAFE_DELETE(input);
|
||||
}
|
||||
MTGAbility * a = NEW AManaProducer(id, target, output, input);
|
||||
MTGAbility * a = NEW AManaProducer(id, target, output, input,doTap);
|
||||
if (multi){
|
||||
multi->Add(a);
|
||||
}else{
|
||||
@@ -1973,3 +1973,181 @@ GenericTriggeredAbility::~GenericTriggeredAbility(){
|
||||
delete te;
|
||||
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;
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "../include/TestSuiteAI.h"
|
||||
#include "../include/config.h"
|
||||
#include "../include/MTGAbility.h"
|
||||
|
||||
#include <string>
|
||||
using std::string;
|
||||
@@ -45,7 +46,7 @@ int TestSuiteAI::Act(float dt){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
g->gameOver = NULL; // Prevent draw rule from losing the game
|
||||
timer+= dt;
|
||||
if (timer < suite->timerLimit) return 1;
|
||||
if (AManaProducer::currentlyTapping || timer < suite->timerLimit) return 1;
|
||||
timer = 0;
|
||||
|
||||
string action = suite->getNextAction();
|
||||
@@ -212,7 +213,7 @@ void TestSuite::initGame(){
|
||||
if (!timerLimit){
|
||||
timerLimit = 0.3;
|
||||
}else{
|
||||
timerLimit = 0.26;
|
||||
timerLimit = 0.1;
|
||||
}
|
||||
//Put the GameObserver in the initial state
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
@@ -237,7 +238,7 @@ void TestSuite::initGame(){
|
||||
Spell * spell = NEW Spell(card);
|
||||
p->game->putInZone(card, p->game->hand, p->game->stack);
|
||||
spell->resolve();
|
||||
card->summoningSickness = 0;
|
||||
if (!summoningSickness) card->summoningSickness = 0;
|
||||
delete spell;
|
||||
}else{
|
||||
if (!p->game->library->hasCard(card)){
|
||||
@@ -358,6 +359,7 @@ TestSuite::TestSuite(const char * filename){
|
||||
}
|
||||
|
||||
int TestSuite::loadNext(){
|
||||
summoningSickness = 0;
|
||||
if (!nbfiles) return 0;
|
||||
if (currentfile >= nbfiles) return 0;
|
||||
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[0] == '#') continue;
|
||||
std::transform( s.begin(), s.end(), s.begin(),::tolower );
|
||||
if (s.compare("summoningsickness") == 0) {
|
||||
summoningSickness = 1;
|
||||
continue;
|
||||
}
|
||||
switch(state){
|
||||
case -1:
|
||||
if (s.compare("[init]") == 0) state++;
|
||||
|
||||
Reference in New Issue
Block a user