diff --git a/CHANGELOG.md b/CHANGELOG.md index e5a69f676..a0357250d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,11 @@ ## [master] (https://github.com/WagicProject/wagic/tree/master) +### 15/11/21 +- *Committed:* Fixed primitives, updated italian lang file, added a new setting to sort decks by creation date (by default they will be sorted by name), added new filters to match cards that don't contain a particular color or that are multicolored, fixed an issue when the transformation with uynt is triggered by instant/sorcery or by card that left the battlefield before the ability ending turn, fixed a rendering overlap on mana symbols in deck editor, fixed some crashes on ManaCost parser (e.g. Filter by mana producer). ([Vitty85](https://github.com/Vitty85)) + ### 14/11/21 -- *Committed:* Fixed "Mana Hellkite" and added its token primitive, fixed token in VOW set. ([Vitty85](https://github.com/Vitty85)) +- *Committed:* Fixed "Mana Hellkite" and added its token primitive, fixed token in VOW set. https://github.com/WagicProject/wagic/commit/2eed51dea6339a6c835f0fe89ddfe1caa61ddf1a ([Vitty85](https://github.com/Vitty85)) - *Committed:* Fixed primitives, improved background images management for game settings, deck selection, deck editor background, post-match credits, deck editor selection and trophies room (now it's possibile to randomly use up to 3 background images and if the chosen image is not available, it will be rendered the default one). https://github.com/WagicProject/wagic/commit/c55c9c25071af5e8a0d62d664b915e7edf1b9491 ([Vitty85](https://github.com/Vitty85)) diff --git a/projects/mtg/bin/Res/lang/it.txt b/projects/mtg/bin/Res/lang/it.txt index 087c189c1..a9a807ad3 100644 --- a/projects/mtg/bin/Res/lang/it.txt +++ b/projects/mtg/bin/Res/lang/it.txt @@ -873,8 +873,10 @@ Mute=Muto Misc=Altri Card Display Options=Opzioni di visualizzazione delle carte All Black Borders=Tutti i bordi neri +Show Borders=Mostra i bordi +Sort decks by date=Ordina i mazzi per data Show Tokens in Editor=Mostra i token nell'editor -Warning!!=Avvertimento!! +Warning!!!=Avvertimento!!! Show Large Images in Grid Deck View=Mostra immagini grandi nella vista a griglia Enable Prefetching=Abilita la pre-elaborazione @@ -953,7 +955,7 @@ Offer Choice=Offri la scelta Always Pay=Paga sempre #Comandi: -Key Bindings=Associazione dei comandi +Key Bindings=Comandi Load Defaults...=Caricare impostazioni di default... Press a key to associate.=Premere un tasto per associare. New binding...=Nuova associazione... @@ -996,6 +998,8 @@ Interrupt my abilities=Interrompi le mie abilita' Interrupt my spells=Interrompi i miei incantesimi Interrupt opponent's end of turn=Interrompi la fine del turno dell'avversario +Credits=Ringraziamenti + ########### # TROFEOS # ########### diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index a11ef4bbf..f7cd85825 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -3786,9 +3786,8 @@ name=Athreos, Shroud-Veiled abilities=indestructible auto=this(variable{orzhov}<7) transforms((removetypes,newability[becomes(Legendary Enchantment God)])) auto=this(variable{orzhov}>6) transforms((Legendary Enchantment Creature)) -auto=@each my endofturn:counter(0/0,1,Coin) target(other creature) -auto=@movedto(creature[counter{0/0,1,Coin}]|Graveyard):all(trigger[to]) moveTo(ownerBattlefield) oneshot -auto=@movedto(creature[counter{0/0,1,Coin}]|Exile):all(trigger[to]) moveTo(myBattlefield) oneshot +auto=@each my endofturn:counter(0/0,1,Coin) target(other creature|battlefield) +auto=@movedto(creature[counter{0/0.1.Coin}]|graveyard,exile):name(Return on battlefield) all(trigger[to]) name(Return on battlefield) moveTo(mybattlefield) text=Indestructible -- As long as your devotion to white and black is less than seven, Athreos isn't a creature. -- At the beginning of your end step, put a coin counter on another target creature. -- Whenever a creature with a coin counter on it dies or is put into exile, return that card to the battlefield under your control. mana={4}{W}{B} type=Legendary Enchantment Creature @@ -28843,7 +28842,7 @@ toughness=2 [card] name=Gilded Light abilities=cycling -auto=playershroud ueot +auto=all(*|myBattlefield) transforms((,newability[playershroud])) ueot autohand=__CYCLING__({2}) text=You gain shroud until end of turn. (You can't be the target of spells or abilities.) -- Cycling {2} ({2}, Discard this card: Draw a card.) mana={1}{W} @@ -31574,7 +31573,7 @@ abilities=trample auto=choice counter(1/1) auto=choice aslongas(creature|myBattlefield) haste auto=this(variable{controllerturn}) opponentshroud -auto=this(variable{controllerturn}) playershroud +auto=this(variable{controllerturn}) controllershroud text=Riot (This creature enters the battlefield with your choice of a +1/+1 counter or haste.) -- Trample -- As long as it's your turn, you and Gruul Spellbreaker have hexproof. mana={1}{R}{G} type=Creature @@ -31622,8 +31621,7 @@ toughness=2 [card] name=Guardian Archon abilities=flying -auto=name(Choose opponent) target(opponent) donothing -auto=this(cantargetcard(*[-effectactivated]) {0}:name(Gain protection) all(this) becomes(effectactivated) forever && target(*|mybattlefield) transforms((,newability[opponentshroud],newability[playershroud])) ueot +auto=this(cantargetcard(*[-effectactivated]) {0}:name(Gain protection) all(this) becomes(effectactivated) forever && target(*|mybattlefield) transforms((,newability[opponentshroud],newability[controllershroud])) ueot text=Flying -- As Guardian Archon enters the battlefield, secretly choose an opponent. -- Reveal the player you chose: You and target permanent you control each gain protection from the chosen player until end of turn. Activate only once. mana={4}{W}{W} type=Creature @@ -39039,7 +39037,7 @@ toughness=1 [/card] [card] name=Keen-Eared Sentry -abilities=playershroud +abilities=controllershroud auto=@counteradded(0/0,1,Explore) from(*[dungeon]|opponentcommandzone):transforms((,newability[nodngopp])) ueot text=You have hexproof. (You can't be the target of spells or abilities your opponents control.) -- Your opponents can't venture into the dungeon more than once each turn. mana={1}{W} @@ -40384,6 +40382,7 @@ toughness=4 [/card] [card] name=Krav, the Unredeemed +abilities=partner auto=may name(Put partner on your hand) moveto(myhand) target(Regna^ the Redeemer|mylibrary) auto={B}{S(creature|myBattlefield)}:name(Sacrifice 1 creature and target yourself) name(Sacrifice 1 creature and target yourself) all(this) counter(1/1,1) && life:1 controller && draw:1 controller auto={B}{S(creature|myBattlefield)}:name(Sacrifice 1 creature and target opponent) name(Sacrifice 1 creature and target opponent) all(this) counter(1/1,1) && life:1 opponent && draw:1 opponent @@ -41335,8 +41334,7 @@ toughness=3 [card] name=Lazotep Plating auto=_AMASS_(1) -auto=playershroud ueot -auto=all(creature|myBattlefield) opponentshroud +auto=all(*|myBattlefield) transforms((,newability[opponentshroud],newability[controllershroud])) ueot text=Amass 1. (Put a +1/+1 counter on an Army you control. If you don't control one, create a 0/0 black Zombie Army creature token first.) -- You and permanents you control gain hexproof until end of turn. (You and they can't be the targets of spells or abilities your opponents control.) mana={1}{U} type=Instant @@ -50594,8 +50592,8 @@ type=Artifact [/card] [card] name=Orbs of Warding -abilities=playershroud -auto=@damaged(controller) from(creature|battlefield):life:1 +abilities=controllershroud +auto=@damageof(player) from(creature|battlefield):name(Prevent 1 damage) life:1 controller text=You have hexproof. (You can't be the target of spells or abilities your opponents control.) -- If a creature would deal damage to you, prevent 1 of that damage. mana={5} type=Artifact @@ -54951,11 +54949,11 @@ auto={2}{T}{counter(0/0,1,brick)}:add{B} auto={2}{T}{counter(0/0,1,brick)}:add{W} auto={2}{T}{counter(0/0,1,brick)}:add{R} auto={2}{T}{counter(0/0,1,brick)}:add{U} -auto={T}{restriction type(this[counter(brick)>=3])~morethan~0}:add{G}{G}{G} -auto={T}{restriction type(this[counter(brick)>=3])~morethan~0}:add{B}{B}{B} -auto={T}{restriction type(this[counter(brick)>=3])~morethan~0}:add{W}{W}{W} -auto={T}{restriction type(this[counter(brick)>=3])~morethan~0}:add{R}{R}{R} -auto={T}{restriction type(this[counter(brick)>=3])~morethan~0}:add{U}{U}{U} +auto=this(counter{0/0.1.brick}>=3) {T}:add{G}{G}{G} +auto=this(counter{0/0.1.brick}>=3) {T}:add{B}{B}{B} +auto=this(counter{0/0.1.brick}>=3) {T}:add{W}{W}{W} +auto=this(counter{0/0.1.brick}>=3) {T}:add{R}{R}{R} +auto=this(counter{0/0.1.brick}>=3) {T}:add{U}{U}{U} text={2}, {T}: Add one mana of any color to your mana pool. Put a brick counter on Pyramid of the Pantheon. -- {T}: Add three mana of any one color to your mana pool. Activate this ability only if there are three or more brick counters on Pyramid of the Pantheon. mana={1} type=Artifact @@ -83188,7 +83186,8 @@ toughness=3 [card] name=Zara, Renegade Recruiter abilities=flying -auto=_ATTACKING_reveal:type:*:opponenthand revealzone(opponenthand) optionone name(Reveal) target(creature|reveal) moveto(mybattlefield) and!( transforms((,newability[ninjutsu],newability[phaseaction[endofturn] moveto(ownerhand) all(this)])) forever )! optiononeend optiontwo all(*|reveal) moveto(opponenthand) optiontwoend revealend +aicode=activate target(creature|opponenthand) moveto(mybattlefield) and!( transforms((,newability[ninjutsu],newability[phaseaction[endofturn once sourceinplay] moveto(ownerhand)])) forever )! +auto=_ATTACKING_reveal:type:*:opponenthand revealzone(opponenthand) optionone name(Reveal) target(creature|reveal) moveto(mybattlefield) and!( transforms((,newability[ninjutsu],newability[phaseaction[endofturn] moveto(ownerhand)])) forever )! optiononeend optiontwo all(*|reveal) moveto(opponenthand) optiontwoend revealend text=Flying -- Whenever Zara, Renegade Recruiter attacks, look at defending player's hand. You may put a creature card from it onto the battlefield under your control tapped and attacking that player or a planeswalker they control. Return that creature to its owner's hand at the beginning of the next end step. mana={3}{U}{R} type=Legendary Creature diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index c4fd2cdc5..cfa3718b8 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -993,7 +993,7 @@ toughness=3 [/card] [card] name=Aegis of the Gods -abilities=playershroud +abilities=controllershroud text=You have hexproof. (You can't be the target of spells or abilities your opponents control.) mana={1}{W} type=Enchantment Creature @@ -82395,11 +82395,26 @@ type=Artifact [card] name=Oona, Queen of the Fae abilities=flying -auto={X}{UB}:name(green) target(opponent) reveal:x revealzone(targetedpersonslibrary) optionone all(*|reveal) moveto(exile) and!( if cantargetcard(*[green]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! optiononeend revealend -auto={X}{UB}:name(blue) target(opponent) reveal:x revealzone(targetedpersonslibrary) optionone all(*|reveal) moveto(exile) and!( if cantargetcard(*[blue]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! optiononeend revealend -auto={X}{UB}:name(red) target(opponent) reveal:x revealzone(targetedpersonslibrary) optionone all(*|reveal) moveto(exile) and!( if cantargetcard(*[red]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! optiononeend revealend -auto={X}{UB}:name(black) target(opponent) reveal:x revealzone(targetedpersonslibrary) optionone all(*|reveal) moveto(exile) and!( if cantargetcard(*[black]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! optiononeend revealend -auto={X}{UB}:name(white) target(opponent) reveal:x revealzone(targetedpersonslibrary) optionone all(*|reveal) moveto(exile) and!( if cantargetcard(*[white]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! optiononeend revealend +auto={1}{UB}:name(X=1) activatechooseacolor all(*[zpos<=1]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={2}{UB}:name(X=2) activatechooseacolor all(*[zpos<=2]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={3}{UB}:name(X=3) activatechooseacolor all(*[zpos<=3]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={4}{UB}:name(X=4) activatechooseacolor all(*[zpos<=4]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={5}{UB}:name(X=5) activatechooseacolor all(*[zpos<=5]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={6}{UB}:name(X=6) activatechooseacolor all(*[zpos<=6]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={7}{UB}:name(X=7) activatechooseacolor all(*[zpos<=7]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={8}{UB}:name(X=8) activatechooseacolor all(*[zpos<=8]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={9}{UB}:name(X=9) activatechooseacolor all(*[zpos<=9]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={10}{UB}:name(X=10) activatechooseacolor all(*[zpos<=10]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={11}{UB}:name(X=11) activatechooseacolor all(*[zpos<=11]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={12}{UB}:name(X=12) activatechooseacolor all(*[zpos<=12]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={13}{UB}:name(X=13) activatechooseacolor all(*[zpos<=13]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={14}{UB}:name(X=14) activatechooseacolor all(*[zpos<=14]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={15}{UB}:name(X=15) activatechooseacolor all(*[zpos<=15]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={16}{UB}:name(X=16) activatechooseacolor all(*[zpos<=16]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={17}{UB}:name(X=17) activatechooseacolor all(*[zpos<=7]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={18}{UB}:name(X=18) activatechooseacolor all(*[zpos<=18]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={19}{UB}:name(X=19) activatechooseacolor all(*[zpos<=19]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend +auto={20}{UB}:name(X=20) activatechooseacolor all(*[zpos<=20]|opponentLibrary) moveto(exile) and!( if cantargetcard(*[chosencolor]|*) then token(Faerie Rogue,Creature Faerie Rogue,1/1,flying,blue,black) )! activatechooseend text=Flying -- {X}{UB}: Choose a color. Target opponent exiles the top X cards of his or her library. For each card of the chosen color exiled this way, put a 1/1 blue and black Faerie Rogue creature token with flying onto the battlefield. mana={3}{UB}{UB}{UB} type=Legendary Creature @@ -105156,7 +105171,7 @@ type=Sorcery [/card] [card] name=Sigarda, Heron's Grace -abilities=flying,playershroud +abilities=flying,controllershroud auto=lord(human|mybattlefield) opponentshroud auto={2}{E(*|mygraveyard)}:token(Human Soldier,Creature Human Soldier,1/1,white) text=Flying -- You and Humans you control have hexproof. -- {2}, Exile a card from your graveyard: Put a 1/1 white Human Soldier creature token onto the battlefield. @@ -134991,7 +135006,7 @@ type=Enchantment [/card] [card] name=Witchbane Orb -abilities=playershroud +abilities=controllershroud auto=destroy all(mycurses) text=When Witchbane Orb enters the battlefield, destroy all Curses attached to you. -- You have hexproof. mana={4} diff --git a/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt b/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt index b78c0755c..505b22047 100644 --- a/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt +++ b/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt @@ -2809,7 +2809,7 @@ subtype=Teyo [/card] [card] name=Teyo, the Shieldmage -abilities=playershroud +abilities=controllershroud auto=counter(0/0,5,loyalty) auto={C(0/0,-2,Loyalty)}:name(-2: Create a 0/3 Wall with defender) create(Wall:Creature Wall:0/3:white:defender) text=You have hexproof. (You can't be the target of spells or abilities your opponents control.) -- -2: Create a 0/3 white Wall creature token with defender. diff --git a/projects/mtg/include/GameOptions.h b/projects/mtg/include/GameOptions.h index 10f66eced..97d8ff010 100644 --- a/projects/mtg/include/GameOptions.h +++ b/projects/mtg/include/GameOptions.h @@ -46,6 +46,7 @@ public: CHEATMODEAIDECK, SHOWBORDER, BLKBORDER, + SORTINGDECKS, SHOWTOKENS, SORTINGSETS, GDVLARGEIMAGE, diff --git a/projects/mtg/include/WFilter.h b/projects/mtg/include/WFilter.h index a7f57e8d3..4fe67d5d4 100644 --- a/projects/mtg/include/WFilter.h +++ b/projects/mtg/include/WFilter.h @@ -288,6 +288,29 @@ protected: int color; }; +/** + Matches a card that does not contain a particular color (inclusively). +*/ +class WCFilterNotColor: public WCardFilter +{ +public: + WCFilterNotColor(int _c) + { + color = _c; + } + ; + WCFilterNotColor(string arg); + bool isMatch(MTGCard * c); + string getCode(); + float filterFee() + { + return 0.2f; + } + ; +protected: + int color; +}; + /** Matches a card that is a particular color (exclusively). */ diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index b091612a5..7fe335d03 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -7782,9 +7782,8 @@ int ATransformer::addToGame() if(UYNT) { if(myCurrentTurn != 1000 && game->turn > myCurrentTurn && source->controller()->getId() == game->currentPlayer->getId()) - { return 1; - } + return 0; // Fixed an issue when the transformation with uynt is triggered by instant/sorcery or by card that left the battlefield before the ability ending turn. } return MTGAbility::testDestroy(); } @@ -7793,6 +7792,7 @@ int ATransformer::destroy() { if(aForever) return 0; + MTGCardInstance * _target = (MTGCardInstance *) target; if (_target) { diff --git a/projects/mtg/src/DeckView.cpp b/projects/mtg/src/DeckView.cpp index de674b049..e53dd2537 100644 --- a/projects/mtg/src/DeckView.cpp +++ b/projects/mtg/src/DeckView.cpp @@ -161,18 +161,18 @@ void DeckView::renderCard(int index, int alpha, bool asThumbnail, bool griddeckv if (last_user_activity < 3) { int fontAlpha = alpha; - float qtY = cardPosition.y - 135 * cardPosition.scale; - float qtX = cardPosition.x + 40 * cardPosition.scale; + float qtY = cardPosition.y - 115 * cardPosition.scale; + float qtX = cardPosition.x + 62 * cardPosition.scale; char buffer[4096]; sprintf(buffer, "x%i", deck()->count(cardPosition.card)); WFont * font = mFont; font->SetScale(1.4f); font->SetColor(ARGB(fontAlpha/2,0,0,0)); - JRenderer::GetInstance()->FillRect(qtX, qtY, font->GetStringWidth(buffer) + 6, 18, ARGB(fontAlpha/2,0,0,0)); - JRenderer::GetInstance()->DrawRect(qtX, qtY, font->GetStringWidth(buffer) + 6, 18, ARGB(fontAlpha/2,240,240,240)); - font->DrawString(buffer, qtX + 5, qtY + 3); + JRenderer::GetInstance()->FillRect(qtX, qtY, font->GetStringWidth(buffer) + 6, 15, ARGB(fontAlpha/2,0,0,0)); + JRenderer::GetInstance()->DrawRect(qtX, qtY, font->GetStringWidth(buffer) + 6, 15, ARGB(fontAlpha/2,240,240,240)); + font->DrawString(buffer, qtX + 5, qtY + 0); font->SetColor(ARGB(fontAlpha,255,255,255)); - font->DrawString(buffer, qtX + 4, qtY + 2); + font->DrawString(buffer, qtX + 4, qtY - 1); font->SetColor(ARGB(255,255,255,255)); font->SetScale(1.0f); } diff --git a/projects/mtg/src/GameOptions.cpp b/projects/mtg/src/GameOptions.cpp index 091370851..cd023edf9 100644 --- a/projects/mtg/src/GameOptions.cpp +++ b/projects/mtg/src/GameOptions.cpp @@ -22,6 +22,7 @@ const string Options::optionNames[] = { "cheatmodedecks", "ShowBorder", "BlackBorder", + "SortDecksByDate", "ShowTokens", "SortingSets", "GDVLargeImages", diff --git a/projects/mtg/src/GameState.cpp b/projects/mtg/src/GameState.cpp index c5dac25d7..57e290666 100644 --- a/projects/mtg/src/GameState.cpp +++ b/projects/mtg/src/GameState.cpp @@ -94,10 +94,13 @@ vector GameState::BuildDeckList(const string& path, const string } meta = NULL; } + // Now decks can be sorted by name or by creation date. + if(!options[Options::SORTINGDECKS].number) + std::sort(retList.begin(), retList.end(), sortByName); // Ordered by name from A to Z. + else + std::reverse(retList.begin(), retList.end()); // Ordered by creation date from the last to the first one (e.g. we consider deck2.txt newer than deck1.txt). - std::sort(retList.begin(), retList.end(), sortByName); return retList; - } // build a menu with the given deck list and return a vector of the deck ids created. diff --git a/projects/mtg/src/GameStateDeckViewer.cpp b/projects/mtg/src/GameStateDeckViewer.cpp index 18c747235..5e70538dc 100644 --- a/projects/mtg/src/GameStateDeckViewer.cpp +++ b/projects/mtg/src/GameStateDeckViewer.cpp @@ -893,9 +893,9 @@ void GameStateDeckViewer::renderOnScreenBasicInfo() float w = mFont->GetStringWidth(buffer); PIXEL_TYPE backupColor = mFont->GetColor(); - renderer->FillRoundRect(SCREEN_WIDTH - (w + 27), y + 5, w + 10, 15, 5, ARGB(hudAlpha/2,0,0,0)); + renderer->FillRoundRect(SCREEN_WIDTH - (w + 27), y, w + 5, 4, 5, ARGB(hudAlpha/2,0,0,0)); mFont->SetColor(ARGB(hudAlpha,255,255,255)); - mFont->DrawString(buffer, SCREEN_WIDTH - 22, y + 15, JGETEXT_RIGHT); + mFont->DrawString(buffer, SCREEN_WIDTH - 20, y + 1, JGETEXT_RIGHT); mFont->SetColor(backupColor); if (mView->filter() != 0) renderer->RenderQuad(mIcons[mView->filter() - 1].get(), SCREEN_WIDTH - 10, y + 15, 0.0f, 0.5, 0.5); diff --git a/projects/mtg/src/GameStateOptions.cpp b/projects/mtg/src/GameStateOptions.cpp index 8722ad448..599468e56 100644 --- a/projects/mtg/src/GameStateOptions.cpp +++ b/projects/mtg/src/GameStateOptions.cpp @@ -63,6 +63,8 @@ void GameStateOptions::Start() optionsList->Add(NEW OptionInteger(Options::SHOWBORDER, "Show Borders")); //black border optionsList->Add(NEW OptionInteger(Options::BLKBORDER, "All Black Borders")); + //Sort deck by date + optionsList->Add(NEW OptionInteger(Options::SORTINGDECKS, "Sort decks by date")); //show tokens in editor optionsList->Add(NEW OptionInteger(Options::SHOWTOKENS, "Show Tokens in Editor")); WDecoStyled * wMisc = NEW WDecoStyled(NEW WGuiHeader("Warning!!!")); diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index 2e8199bc0..24dca6ec7 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -266,6 +266,8 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan case 'p' : { SAFE_DELETE(tc); + if (value.find("power") != string::npos) // Fix to avoid crash on ManaCost parse (e.g. Filter by mana producer). + break; size_t start = value.find("("); size_t end = value.rfind(")"); string manaType = value.substr(start + 1, end - start - 1); @@ -298,6 +300,8 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan break; case 'c': //Counters or cycle { + if (value.find("compare(") != string::npos) // Fix to avoid crash on ManaCost parse (e.g. Filter by mana producer). + break; if (value.find("convoke") != string::npos) { if (!tc) diff --git a/projects/mtg/src/WFilter.cpp b/projects/mtg/src/WFilter.cpp index 38f894dfc..4d94cf8dc 100644 --- a/projects/mtg/src/WFilter.cpp +++ b/projects/mtg/src/WFilter.cpp @@ -12,10 +12,12 @@ WCFilterFactory* WCFilterFactory::GetInstance() if (!me) me = NEW WCFilterFactory(); return me; } + void WCFilterFactory::Destroy() { SAFE_DELETE(me); } + size_t WCFilterFactory::findNext(string src, size_t start, char open, char close) { int num = 0; @@ -30,6 +32,7 @@ size_t WCFilterFactory::findNext(string src, size_t start, char open, char close } return string::npos; } + WCardFilter * WCFilterFactory::Construct(string src) { size_t x = 0; @@ -152,6 +155,8 @@ WCardFilter * WCFilterFactory::Terminal(string src, string arg) return NEW WCFilterRarity(arg); else if (type == "c" || type == "color") return NEW WCFilterColor(arg); + else if (type == "nc" || type == "ncolor") + return NEW WCFilterNotColor(arg); else if (type == "xc" || type == "xcolor") return NEW WCFilterOnlyColor(arg); else if (type == "s" || type == "set") @@ -172,6 +177,7 @@ WCardFilter * WCFilterFactory::Terminal(string src, string arg) return NEW WCFilterNULL(); } + //WCFilterLetter WCFilterLetter::WCFilterLetter(string arg) { @@ -180,6 +186,7 @@ WCFilterLetter::WCFilterLetter(string arg) else alpha = tolower(arg[0]); } + bool WCFilterLetter::isMatch(MTGCard * c) { if (!c || !c->data) return false; @@ -188,12 +195,14 @@ bool WCFilterLetter::isMatch(MTGCard * c) if (s[0] == alpha || (alpha == '#' && (isdigit(s[0]) || ispunct(s[0])))) return true; return false; } + string WCFilterLetter::getCode() { char buf[24]; sprintf(buf, "alpha:%c;", alpha); return buf; } + //WCFilterSet WCFilterSet::WCFilterSet(string arg) { @@ -208,7 +217,6 @@ string WCFilterSet::getCode() sprintf(buf, "set:%s;", setName.c_str()); return buf; } -; //WCFilterColor bool WCFilterColor::isMatch(MTGCard * c) @@ -216,15 +224,16 @@ bool WCFilterColor::isMatch(MTGCard * c) if (!c || !c->data) return false; return (c->data->hasColor(color)); } + string WCFilterColor::getCode() { char buf[12]; char c = '?'; - if (color < 0 || color >= Constants::NB_Colors) c = Constants::MTGColorChars[color]; + if (color >= 0 && color < Constants::NB_Colors) c = Constants::MTGColorChars[color]; sprintf(buf, "color:%c;", c); return buf; } -; + WCFilterColor::WCFilterColor(string arg) { color = -1; @@ -238,6 +247,57 @@ WCFilterColor::WCFilterColor(string arg) } } } + +//WCFilterNotColor +bool WCFilterNotColor::isMatch(MTGCard * c) +{ + if (!c || !c->data) return false; + if(color == -1){ // Only multicolored cards + for (int i = 1; i < 6; i++){ + if(c->data->hasColor(i)){ + for (int j = i+1; j < 6; j++){ + if(c->data->hasColor(j)) + return true; + } + } + } + return false; + } else if(color == 0){ // Not colorless cards + for (int i = 1; i < 6; i++){ + if(c->data->hasColor(i)) + return true; + } + return false; + } else + return !(c->data->hasColor(color)); +} + +string WCFilterNotColor::getCode() +{ + char buf[12]; + char c = '?'; + if (color >= 0 && color < Constants::NB_Colors) + c = Constants::MTGColorChars[color]; + else if (color < 0) + c = 'm'; + sprintf(buf, "ncolor:%c;", c); + return buf; +} + +WCFilterNotColor::WCFilterNotColor(string arg) +{ + color = -1; + char c = tolower(arg[0]); + for (int i = 0; i < Constants::NB_Colors; i++) + { + if (Constants::MTGColorChars[i] == c) + { + color = i; + break; + } + } +} + //WCFilterOnlyColor bool WCFilterOnlyColor::isMatch(MTGCard * c) { @@ -249,14 +309,16 @@ bool WCFilterOnlyColor::isMatch(MTGCard * c) } return (c->data->hasColor(color)); } + string WCFilterOnlyColor::getCode() { char buf[12]; char c = '?'; - if (color < 0 || color >= Constants::NB_Colors) c = Constants::MTGColorChars[color]; + if (color >= 0 && color < Constants::NB_Colors) c = Constants::MTGColorChars[color]; sprintf(buf, "xcolor:%c;", c); return buf; } + //WCFilterProducesColor bool WCFilterProducesColor::isMatch(MTGCard * c) { @@ -271,23 +333,27 @@ bool WCFilterProducesColor::isMatch(MTGCard * c) return true; //Retrieve non basic Mana abilities - string s = c->data->magicText; - size_t t = s.find("add{"); - while (t != string::npos) - { - s = s.substr(t + 3); - ManaCost * mc = ManaCost::parseManaCost(s); - if (mc->hasColor(color) > 0) + vector rows = split(c->data->magicText, '\n'); // Now the parser analyze the full card text row by row to avoid fake color matches. + for(size_t j = 0; j < rows.size(); j++){ + string s = rows[j]; + size_t t = s.find("add{"); + while (t != string::npos) { - bMatch = true; + s = s.substr(t + 3); + ManaCost * mc = ManaCost::parseManaCost(s); + if (mc->hasColor(color) > 0) + { + bMatch = true; + SAFE_DELETE(mc); + break; + } SAFE_DELETE(mc); - break; + t = s.find("add{"); } - SAFE_DELETE(mc); - t = s.find("add"); } return bMatch; } + string WCFilterProducesColor::getCode() { char buf[12]; @@ -296,11 +362,13 @@ string WCFilterProducesColor::getCode() sprintf(buf, "produces:%c;", c); return buf; } + //WCFilterNumeric WCFilterNumeric::WCFilterNumeric(string arg) { number = atoi(arg.c_str()); } + //WCFilterCMC bool WCFilterCMC::isMatch(MTGCard * c) { @@ -315,30 +383,35 @@ string WCFilterCMC::getCode() sprintf(buf, "cmc:%i;", number); return buf; } + //WCFilterPower bool WCFilterPower::isMatch(MTGCard * c) { if (!c || !c->data) return false; return (c->data->getPower() == number); } + string WCFilterPower::getCode() { char buf[64]; sprintf(buf, "power:%i;", number); return buf; } + //WCFilterPower bool WCFilterToughness::isMatch(MTGCard * c) { if (!c || !c->data) return false; return (c->data->getToughness() == number); } + string WCFilterToughness::getCode() { char buf[64]; sprintf(buf, "toughness:%i;", number); return buf; } + //WCFilterRarity float WCFilterRarity::filterFee() { @@ -355,12 +428,14 @@ float WCFilterRarity::filterFee() } return 0.0f; } + bool WCFilterRarity::isMatch(MTGCard * c) { if (!c || !c->data) return false; if (rarity == 'A') return true; //A for "Any" or "All" return (c->getRarity() == rarity); } + string WCFilterRarity::getCode() { char buf[64]; @@ -393,7 +468,7 @@ string WCFilterRarity::getCode() sprintf(buf, "rarity:%s;", rarities[x]); return buf; } -; + WCFilterRarity::WCFilterRarity(string arg) { rarity = -1; @@ -412,6 +487,7 @@ WCFilterRarity::WCFilterRarity(string arg) } rarity = 'A'; } + //WCFilterAbility bool WCFilterAbility::isMatch(MTGCard * c) { @@ -433,6 +509,7 @@ WCFilterAbility::WCFilterAbility(string arg) } ability = -1; } + string WCFilterAbility::getCode() { char buf[64]; @@ -440,7 +517,6 @@ string WCFilterAbility::getCode() sprintf(buf, "ability:%s;", Constants::MTGBasicAbilities[ability]); return buf; } -; float WCFilterAbility::filterFee() { @@ -487,22 +563,26 @@ float WCFilterAbility::filterFee() } return 0.0f; } + //WCFilterType bool WCFilterType::isMatch(MTGCard * c) { return c->data->hasType(type.c_str()); } + string WCFilterType::getCode() { char buf[4068]; sprintf(buf, "type:%s;", type.c_str()); return buf; } + //Misc. filter code float WCFilterAND::filterFee() { return lhs->filterFee() + rhs->filterFee(); } + float WCFilterOR::filterFee() { float lFee = lhs->filterFee(); @@ -511,12 +591,14 @@ float WCFilterOR::filterFee() return lFee; return rFee; } + string WCFilterNOT::getCode() { char buf[4068]; sprintf(buf, "{%s}", kid->getCode().c_str()); return buf; } + string WCFilterGROUP::getCode() { char buf[4068]; @@ -530,6 +612,7 @@ string WCFilterAND::getCode() sprintf(buf, "%s&%s", lhs->getCode().c_str(), rhs->getCode().c_str()); return buf; } + string WCFilterOR::getCode() { char buf[4068]; @@ -543,4 +626,3 @@ bool WCFilterOR::isMatch(MTGCard *c) if (rhs->isMatch(c)) return true; return false; } -; diff --git a/projects/mtg/src/WGui.cpp b/projects/mtg/src/WGui.cpp index 2249d311c..e73ffecb2 100644 --- a/projects/mtg/src/WGui.cpp +++ b/projects/mtg/src/WGui.cpp @@ -2186,6 +2186,13 @@ void WGuiFilterItem::updateValue() mParent->addArg("Exclusively Black", "xc:b;"); mParent->addArg("Exclusively Red", "xc:r;"); mParent->addArg("Exclusively Green", "xc:g;"); + mParent->addArg("Not White", "nc:w;"); + mParent->addArg("Not Blue", "nc:u;"); + mParent->addArg("Not Black", "nc:b;"); + mParent->addArg("Not Red", "nc:r;"); + mParent->addArg("Not Green", "nc:g;"); + mParent->addArg("Not Colorless", "nc:x;"); + mParent->addArg("Only Multicolored", "nc:m;"); } else if (filterType == FILTER_PRODUCE) {