- new Ability : ALifeGiver (bottle gnomes)
- Added a few cards from Tempest
- Hybrid mana fix for hybrid mana involving uncolored mana costs (see tests/generic/hybridmana2.txt - spectral possession)
- Fixed bugs with targetting for TargetAbilities
- Fixed multiple sacrifice abilities cost (Siege gang commander, see tests)
- Fixed a small font issue
This commit is contained in:
wagic.the.homebrew
2009-02-11 09:38:20 +00:00
parent 391bdaf0d8
commit 6d1d5d751a
22 changed files with 226 additions and 53 deletions

View File

@@ -40,6 +40,7 @@ toughness=4
[card] [card]
text=Plainswalk {2}{R}, Sacrifice Boggart Arsonists: Destroy target Scarecrow or Plains. text=Plainswalk {2}{R}, Sacrifice Boggart Arsonists: Destroy target Scarecrow or Plains.
auto={2}{R}{S}:destroy target(scarecrow,plains) auto={2}{R}{S}:destroy target(scarecrow,plains)
abilities=plainswalk
id=158684 id=158684
name=Boggart Arsonists name=Boggart Arsonists
rarity=C rarity=C

View File

@@ -27,6 +27,14 @@ mana={2}{R}{R}
type=Sorcery type=Sorcery
[/card] [/card]
[card] [card]
text={T}: Add {2} to your mana pool. Ancient Tomb deals 2 damage to you.
auto={T}: Add {2} && Damage 1 controller
id=4636
name=Ancient Tomb
rarity=U
type=Land
[/card]
[card]
text=Flying text=Flying
id=4861 id=4861
name=Armored Pegasus name=Armored Pegasus
@@ -283,6 +291,15 @@ mana={2}{U}{U}
type=Instant type=Instant
[/card] [/card]
[card] [card]
text=White creatures get -1/-1.
auto=lord(creature[white]) -1/-1
id=4658
name=Dread of Night
rarity=U
type=Enchantment
mana={B}
[/card]
[card]
text=Legendary Other Elf creatures have forestwalk. Other Elves have shroud. (They can't be the targets of spells or abilities.) text=Legendary Other Elf creatures have forestwalk. Other Elves have shroud. (They can't be the targets of spells or abilities.)
id=4757 id=4757
name=Eladamri, Lord of Leaves name=Eladamri, Lord of Leaves
@@ -619,6 +636,19 @@ toughness=1
abilities=Haste abilities=Haste
[/card] [/card]
[card] [card]
text={T}, Sacrifice Lotus Petal: Add one mana of any color to your mana pool.
auto={T},{S}:Add{G}
auto={T},{S}:Add{R}
auto={T},{S}:Add{U}
auto={T},{S}:Add{B}
auto={T},{S}:Add{W}
id=4614
name=Lotus Petal
rarity=C
type=Artifact
mana={0}
[/card]
[card]
id=4829 id=4829
name=Lowland Giant name=Lowland Giant
colour=Red colour=Red

View File

@@ -49,13 +49,7 @@ rarity=U
type=Enchantment type=Enchantment
mana={2}{R} mana={2}{R}
[/card] [/card]
[card]
text={T}: Add {2} to your mana pool. Ancient Tomb deals 2 damage to you.
id=4636
name=Ancient Tomb
rarity=U
type=Land
[/card]
[card] [card]
text=Flying Whenever Angelic Protector becomes the target of a spell or ability, Angelic Protector gets +0/+3 until end of turn. text=Flying Whenever Angelic Protector becomes the target of a spell or ability, Angelic Protector gets +0/+3 until end of turn.
id=4858 id=4858
@@ -696,14 +690,7 @@ power=0
subtype=Shapeshifter subtype=Shapeshifter
toughness=0 toughness=0
[/card] [/card]
[card]
text=White creatures get -1/-1.
id=4658
name=Dread of Night
rarity=U
type=Enchantment
mana={B}
[/card]
[card] [card]
text=Draw three cards, then put two cards from your hand both on top of your library or both on the bottom of your library. text=Draw three cards, then put two cards from your hand both on top of your library or both on the bottom of your library.
id=4696 id=4696
@@ -1515,14 +1502,7 @@ rarity=U
type=Sorcery type=Sorcery
mana={2}{U}{B} mana={2}{U}{B}
[/card] [/card]
[card]
text={T}, Sacrifice Lotus Petal: Add one mana of any color to your mana pool.
id=4614
name=Lotus Petal
rarity=C
type=Artifact
mana={0}
[/card]
[card] [card]
text= text=
id=4829 id=4829

View File

@@ -5,6 +5,7 @@ generic/first_strike.txt
generic/first_strike2.txt generic/first_strike2.txt
generic/first_strike3.txt generic/first_strike3.txt
generic/hybrid_mana.txt generic/hybrid_mana.txt
generic/hybrid_mana_2.txt
generic/legendary.txt generic/legendary.txt
generic/persist.txt generic/persist.txt
generic/wither.txt generic/wither.txt
@@ -18,6 +19,8 @@ animate_dead2.txt
ardakar_wastes.txt ardakar_wastes.txt
ascendant_evincar.txt ascendant_evincar.txt
ascendant_evincar2.txt ascendant_evincar2.txt
bottle_gnomes.txt
boggart_arsonists.txt
brass_man.txt brass_man.txt
castle.txt castle.txt
celestial_purge.txt celestial_purge.txt
@@ -52,9 +55,11 @@ nantuko_husk.txt
orcish_lumberjack.txt orcish_lumberjack.txt
paralysis.txt paralysis.txt
paralysis2.txt paralysis2.txt
protomatter_powder.txt
resurrection.txt resurrection.txt
rootwalla.txt rootwalla.txt
royal_assassin.txt royal_assassin.txt
siege_gang_commander.txt
shivan_hellkite.txt shivan_hellkite.txt
shock.txt shock.txt
spark_elemental.txt spark_elemental.txt

View File

@@ -0,0 +1,19 @@
# {2}{R}, Sacrifice Boggart Arsonists: Destroy target Scarecrow or Plains.
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:158684
manapool:{2}{R}
[PLAYER2]
inplay:154395
[DO]
158684
154395
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:158684
manapool:{0}
[PLAYER2]
graveyard:154395
[END]

View File

@@ -0,0 +1,15 @@
#Do we get 3 life when sacrificing bottle gnomes ?
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:129495
[PLAYER2]
[DO]
129495
[ASSERT]
FIRSTMAIN
[PLAYER1]
life:23
graveyard:129495
[PLAYER2]
[END]

View File

@@ -1,4 +1,5 @@
#Composite golem sacrifice ability subject to summoning Sickness ? #Composite golem sacrifice ability subject to summoning Sickness ?
# Sacrifice composite Golem : Add {W}{U}{B}{R}{G}
SummoningSickness SummoningSickness
[INIT] [INIT]
FIRSTMAIN FIRSTMAIN

View File

@@ -0,0 +1,18 @@
#Testing Hybrid Mana
# Spectral possession: text=({2W} can be paid with any two mana or with {W}. This card's converted mana cost is 6.) Put three 1/1 white Spirit creature tokens with flying into play.
[INIT]
FIRSTMAIN
[PLAYER1]
hand:152070
manapool:{W}{W}{W}
[PLAYER2]
[DO]
152070
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:152070
inplay:-152070,-152070,-152070
manapool:{0}
[PLAYER2]
[END]

View File

@@ -0,0 +1,19 @@
#text={4}{W}, {T}, Sacrifice Protomatter Powder: Return target artifact card from your graveyard to play.
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:174833
graveyard:1099
manapool:{4}{W}
[PLAYER2]
[DO]
174833
1099
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:174833
manapool:{0}
inplay:1099
[PLAYER2]
[END]

View File

@@ -0,0 +1,25 @@
#TestingSiege-Gang Commander Sacrifice goblin ability
#text=When Siege-Gang Commander comes into play, put three 1/1 red Goblin creature tokens into play. {1}{R}, Sacrifice a Goblin: Siege-Gang Commander deals 2 damage to target creature or player.
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:130539,130378,129578
manapool:{2}{R}{R}
[PLAYER2]
inplay:129586,129600
[DO]
130539
129586
129578
130539
129600
130378
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:130378,129578
inplay:130539,-130539,-130539,-130539
manapool:{0}
[PLAYER2]
graveyard:129586,129600
[END]

View File

@@ -93,6 +93,28 @@ class ADrawer:public ActivatedAbility{
}; };
// Gives/Takes Life to controller of source
class ALifeGiver:public ActivatedAbility{
public:
int life;
ALifeGiver(int _id, MTGCardInstance * card,ManaCost * _cost, int _life, int _tap = 1):ActivatedAbility(_id, card,_cost,0,_tap),life(_life){
}
int resolve(){
source->controller()->life+=life;
return 1;
}
const char * getMenuText(){
if (life < 0) return "Lose life";
return "Gain life";
}
};
class ATokenCreator:public ActivatedAbility{ class ATokenCreator:public ActivatedAbility{
public: public:
list<int>abilities; list<int>abilities;

View File

@@ -437,7 +437,7 @@ class GameStateDeckViewer: public GameState, public JGuiListener
mFont->DrawString(buffer, SCREEN_WIDTH-120 , y); mFont->DrawString(buffer, SCREEN_WIDTH-120 , y);
if (colorFilter != ALL_COLORS){ if (colorFilter != ALL_COLORS){
sprintf(buffer2, "( %i)", myDeck->getCount(colorFilter)); sprintf(buffer2, "( %i)", myDeck->getCount(colorFilter));
mFont->DrawString(buffer2, SCREEN_WIDTH-55 , y); mFont->DrawString(buffer2, SCREEN_WIDTH-55 , y);
JRenderer::GetInstance()->RenderQuad(mIcons[colorFilter], SCREEN_WIDTH-42 , y + 6 , 0.0f,0.5,0.5); JRenderer::GetInstance()->RenderQuad(mIcons[colorFilter], SCREEN_WIDTH-42 , y + 6 , 0.0f,0.5,0.5);
} }

View File

@@ -58,6 +58,9 @@ class ManaCost{
int isPositive(); int isPositive();
ManaCost * Diff(ManaCost * _cost); ManaCost * Diff(ManaCost * _cost);
#ifdef WIN32
void Dump();
#endif
}; };
#endif #endif

View File

@@ -126,10 +126,7 @@ int ActionLayer::reactToTargetClick(Targetable * card){
int ActionLayer::isReactingToClick(MTGCardInstance * card){ int ActionLayer::isReactingToClick(MTGCardInstance * card){
int result = 0; int result = 0;
for (int i=0;i<mCount;i++){ if (isWaitingForAnswer()) return -1;
ActionElement * currentAction = (ActionElement *)mObjects[i];
if(currentAction->waitingForAnswer) return -1;
}
for (int i=0;i<mCount;i++){ for (int i=0;i<mCount;i++){

View File

@@ -43,6 +43,8 @@ int SacrificeCost::isPaymentSet(){
int SacrificeCost::doPay(){ int SacrificeCost::doPay(){
if(target){ if(target){
target->controller()->game->putInGraveyard(target); target->controller()->game->putInGraveyard(target);
target = NULL;
if (tc) tc->initTargets();
return 1; return 1;
} }
return 0; return 0;

View File

@@ -272,11 +272,9 @@ void GameObserver::stackObjectClicked(Interruptible * action){
} }
void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){ void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){
LOG("==GameObserver::cardClick");
if (card) {LOG(card->getName())};
Player * clickedPlayer = NULL; Player * clickedPlayer = NULL;
if (!card) clickedPlayer = ((Player *)object); if (!card) clickedPlayer = ((Player *)object);
if (targetChooser != NULL){ if (targetChooser){
int result; int result;
if (card) { if (card) {
if (card == cardWaitingForTargets){ if (card == cardWaitingForTargets){

View File

@@ -5,7 +5,7 @@
#include "../include/GameOptions.h" #include "../include/GameOptions.h"
#include "../include/GameApp.h" #include "../include/GameApp.h"
static const char* GAME_VERSION = "WTH?! 0.4.0 - by WilLoW"; static const char* GAME_VERSION = "WTH?! 0.4.1 - by WilLoW";
#define ALPHA_WARNING 0 #define ALPHA_WARNING 0
#define DEFAULT_ANGLE_MULTIPLIER 0.4 #define DEFAULT_ANGLE_MULTIPLIER 0.4

View File

@@ -373,7 +373,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
}else{ }else{
if (dryMode) return BAKA_EFFECT_BAD; if (dryMode) return BAKA_EFFECT_BAD;
if (tc){ if (tc){
game->addObserver(NEW ADestroyer(id, card,tc)); game->addObserver(NEW ADestroyer(id, card,tc,0,cost));
}else{ }else{
game->mLayers->stackLayer()->addPutInGraveyard(target); game->mLayers->stackLayer()->addPutInGraveyard(target);
} }
@@ -434,7 +434,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
if (!cost && !doTap){ if (!cost && !doTap){
card->controller()->life+=life; card->controller()->life+=life;
}else{ }else{
//TODO; game->addObserver(NEW ALifeGiver(id, card,cost, life, doTap));
} }
} }
result++; result++;
@@ -1699,7 +1699,10 @@ ActivatedAbility::~ActivatedAbility(){
if (cost) delete cost; if (cost) delete cost;
} }
// //The whole targetAbility mechanism is messed up, mainly because of its interactions with
// the ActionLayer, GameObserver, and parent class ActivatedAbility.
// Currently choosing a target is a complete different mechanism for put into play and for other abilities.
// It probably shouldn't be the case.
TargetAbility::TargetAbility(int id, MTGCardInstance * card, TargetChooser * _tc,ManaCost * _cost, int _playerturnonly,int tap):ActivatedAbility(id, card,_cost,_playerturnonly, tap){ TargetAbility::TargetAbility(int id, MTGCardInstance * card, TargetChooser * _tc,ManaCost * _cost, int _playerturnonly,int tap):ActivatedAbility(id, card,_cost,_playerturnonly, tap){
tc = _tc; tc = _tc;
@@ -1715,8 +1718,8 @@ void TargetAbility::Update(float dt){
if(mEngine->GetButtonClick(PSP_CTRL_CROSS)){ if(mEngine->GetButtonClick(PSP_CTRL_CROSS)){
waitingForAnswer = 0; waitingForAnswer = 0;
}else if(tc->targetsReadyCheck() == TARGET_OK_FULL){ }else if(tc->targetsReadyCheck() == TARGET_OK_FULL){
waitingForAnswer = 0; //waitingForAnswer = 0;
ActivatedAbility::reactToClick(source); //ActivatedAbility::reactToClick(source);
} }
} }
} }
@@ -1724,8 +1727,11 @@ void TargetAbility::Update(float dt){
int TargetAbility::reactToTargetClick(Targetable * object){ int TargetAbility::reactToTargetClick(Targetable * object){
if (object->typeAsTarget() == TARGET_CARD) return reactToClick((MTGCardInstance *)object); if (object->typeAsTarget() == TARGET_CARD) return reactToClick((MTGCardInstance *)object);
if (waitingForAnswer){ if (waitingForAnswer){
tc->toggleTarget(object); if (tc->toggleTarget(object) == TARGET_OK_FULL){
return 1; waitingForAnswer = 0;
return ActivatedAbility::reactToClick(source);
}
return 1;
} }
return 0; return 0;
} }
@@ -1740,12 +1746,17 @@ int TargetAbility::reactToClick(MTGCardInstance * card){
} }
}else{ }else{
if (card == source){ if (card == source){
if (tc->targetsReadyCheck() == TARGET_OK){ if (tc->targetsReadyCheck() == TARGET_OK || tc->targetsReadyCheck() == TARGET_OK_FULL){
waitingForAnswer = 0; waitingForAnswer = 0;
return ActivatedAbility::reactToClick(source); return ActivatedAbility::reactToClick(source);
} }
}else{ }else{
tc->toggleTarget(card); if (tc->toggleTarget(card) == TARGET_OK_FULL){
int result = ActivatedAbility::reactToClick(source);
if (result) waitingForAnswer = 0;
return result;
}
return 1; return 1;
} }
} }
@@ -1753,7 +1764,7 @@ int TargetAbility::reactToClick(MTGCardInstance * card){
} }
void TargetAbility::Render(){ void TargetAbility::Render(){
//TODO //TODO ?
} }

View File

@@ -21,6 +21,9 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card){
LOG("CANPUTINPLAY- correct time to play\n"); LOG("CANPUTINPLAY- correct time to play\n");
ManaCost * playerMana = player->getManaPool(); ManaCost * playerMana = player->getManaPool();
ManaCost * cost = card->getManaCost(); ManaCost * cost = card->getManaCost();
#ifdef WIN32
cost->Dump();
#endif
if (playerMana->canAfford(cost)){ if (playerMana->canAfford(cost)){
LOG("CANPUTINPLAY- ManaCost ok\n"); LOG("CANPUTINPLAY- ManaCost ok\n");
return 1; return 1;

View File

@@ -70,19 +70,19 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost){
int intvalue = atoi(value.c_str()); int intvalue = atoi(value.c_str());
int colors[2]; int colors[2];
int values[2]; int values[2];
if (!intvalue && value.size() > 1){ if (intvalue < 10 && value.size() > 1){
for (int i = 0; i < 2; i++){ for (int i = 0; i < 2; i++){
char c = value[i]; char c = value[i];
if (c >='0' && c <='9'){ if (c >='0' && c <='9'){
colors[i] = Constants::MTG_COLOR_ARTIFACT; colors[i] = Constants::MTG_COLOR_ARTIFACT;
values[i] = c - '0'; values[i] = c - '0';
}else{ }else{
for (int j = 0; j < Constants::MTG_NB_COLORS; j++){ for (int j = 0; j < Constants::MTG_NB_COLORS; j++){
if (c == Constants::MTGColorChars[j]){ if (c == Constants::MTGColorChars[j]){
colors[i] = j; colors[i] = j;
values[i] = 1; values[i] = 1;
} }
} }
} }
} }
manaCost->addHybrid(colors[0], values[0], colors[1], values[1]); manaCost->addHybrid(colors[0], values[0], colors[1], values[1]);
@@ -98,6 +98,7 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost){
break; break;
} }
} }
return manaCost; return manaCost;
} }
@@ -378,3 +379,25 @@ ManaCost * ManaCost::Diff(ManaCost * _cost){
return result; return result;
} }
#ifdef WIN32
void ManaCost::Dump(){
char buf[4096];
OutputDebugString("\n===ManaCost===\n");
for (int i=0; i<= Constants::MTG_NB_COLORS; i++){
if (cost[i]) {
sprintf(buf, "%c:%i - ", Constants::MTGColorChars[i],cost[i]);
OutputDebugString(buf);
}
}
for (int i=0; i< nbhybrids; i++){
ManaCostHybrid * h = hybrids[i];
sprintf(buf, "H:{%c:%i}/{%c:%i}", Constants::MTGColorChars[h->color1], h->value1, Constants::MTGColorChars[h->color2], h->value2);
OutputDebugString(buf);
}
OutputDebugString("\n=============\n");
}
#endif

View File

@@ -189,7 +189,7 @@ OutputDebugString("COLOR FOUND !!!");
typeName = typeName.substr(0,found); typeName = typeName.substr(0,found);
} }
//X targets allowed ? //X targets allowed ?
if (typeName.at(typeName.length()-1) == 's'){ if (typeName.at(typeName.length()-1) == 's' && !Subtypes::subtypesList->find(typeName)){
typeName = typeName.substr(0,typeName.length()-1); typeName = typeName.substr(0,typeName.length()-1);
maxtargets = -1; maxtargets = -1;
} }

View File

@@ -42,6 +42,7 @@ Interruptible * TestSuite::getActionByMTGId(int mtgid){
return NULL; return NULL;
} }
int TestSuiteAI::Act(float dt){ 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
@@ -211,7 +212,7 @@ void TestSuite::initGame(){
// or go faster when it comes to the whole test suite. // or go faster when it comes to the whole test suite.
//Warning, putting this value too low (< 0.25) will give unexpected results //Warning, putting this value too low (< 0.25) will give unexpected results
if (!timerLimit){ if (!timerLimit){
timerLimit = 0.3; timerLimit = 0.5;
}else{ }else{
timerLimit = 0.1; timerLimit = 0.1;
} }