Improved AI: now it can plays cards using alternative cost too, fixed thisturn restriction in some primitives.
This commit is contained in:
@@ -4462,7 +4462,8 @@ toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Bellowing Elk
|
||||
auto=aslongas(other creature[fresh]|mybattlefield) trample && indestructible
|
||||
auto=if thisturn(creature|mybattlefield)~morethan~1 then transforms((,newability[trample],newability[indestructible])) ueot
|
||||
auto=@movedTo(other creature|myBattlefield):transforms((,newability[trample],newability[indestructible])) ueot
|
||||
text=As long as you had another creature enter the battlefield under your control this turn, Bellowing Elk has trample and indestructible.
|
||||
mana={3}{G}
|
||||
type=Creature
|
||||
@@ -9218,7 +9219,7 @@ type=Land
|
||||
[card]
|
||||
name=Cleaving Reaper
|
||||
abilities=flying,trample
|
||||
autograveyard=@movedto(*[angel;berserker]|mybattlefield):transforms((,newability[{L:3}:name(Move back to hand) moveto(myhand)])) ueot
|
||||
autograveyard={L:3}:restriction{thisturn(*[angel;berserker]|mybattlefield)~morethan~0} name(Move back to hand) moveto(myhand)
|
||||
text=Flying, trample -- Pay 3 life: Return Cleaving Reaper from your graveyard to your hand. Activate this ability only if you had an Angel or Berserker enter the battlefield under your control this turn.
|
||||
mana={3}{B}{B}
|
||||
type=Creature
|
||||
@@ -10066,7 +10067,7 @@ type=Instant
|
||||
[card]
|
||||
name=Confounding Conundrum
|
||||
auto=draw:1 controller
|
||||
auto=@movedTo(land|opponentBattlefield) restriction{type(land[fresh]|opponentBattlefield)~morethan~1}:ability$!name(Move to hand) moveTo(ownerHand) notatarget(land|myBattlefield)!$ opponent
|
||||
auto=@movedTo(land|opponentBattlefield) restriction{thisturn(land|opponentbattlefield)~morethan~1}:ability$!name(Move to hand) moveTo(ownerHand) notatarget(land|myBattlefield)!$ opponent
|
||||
text=When Confounding Conundrum enters the battlefield, draw a card. -- Whenever a land enters the battlefield under an opponent's control, if that player had another land enter the battlefield under their control this turn, they return a land they control to its owner's hand.
|
||||
mana={1}{U}
|
||||
type=Enchantment
|
||||
@@ -35371,6 +35372,7 @@ toughness=1
|
||||
[/card]
|
||||
[card]
|
||||
name=Nimble Trapfinder
|
||||
auto=if thisturn(creature[cleric;rogue;warrior;wizard]|mybattlefield)~morethan~1 then transforms((,newability[unblockable])) ueot
|
||||
auto=@movedTo(other creature[cleric;rogue;warrior;wizard]|myBattlefield):all(this) transforms((,newability[unblockable])) ueot
|
||||
auto=@each my combatbegins:if compare(calculateparty)~equalto~4 then name(creatures get draw card on damage) name(creatures get draw card on damage) all(creature|myBattlefield) transforms((,newability[@combatdamagefoeof(player) from(this):draw:1 controller],newability[@combatdamageof(player) from(this):draw:1 controller])) ueot
|
||||
text=Nimble Trapfinder can't be blocked if you had another Cleric, Rogue, Warrior, or Wizard enter the battlefield under your control this turn. -- At the beginning of combat on your turn, if you have a full party, creatures you control gain "Whenever this creature deals combat damage to a player, draw a card" until end of turn.
|
||||
@@ -43605,7 +43607,8 @@ toughness=2
|
||||
[/card]
|
||||
[card]
|
||||
name=Saddled Rimestag
|
||||
auto=aslongas(creature[fresh]|mybattlefield) 2/2
|
||||
auto=if thisturn(creature|mybattlefield)~morethan~1 then 2/2 ueot
|
||||
auto=@movedto(other creature|myBattlefield):2/2 ueot
|
||||
text=Saddled Rimestag gets +2/+2 as long as you had another creature enter the battlefield under your control this turn.
|
||||
mana={1}{G}
|
||||
type=Snow Creature
|
||||
@@ -45115,8 +45118,8 @@ type=Instant
|
||||
[card]
|
||||
name=Searing Blaze
|
||||
target=player
|
||||
auto=if type(land[fresh]|mybattlefield)~lessthan~1 then damage:1 && damage:1 target(creature|targetedpersonsBattlefield)
|
||||
auto=if type(land[fresh]|mybattlefield)~morethan~0 then damage:3 && damage:3 target(creature|targetedpersonsBattlefield)
|
||||
auto=if thisturn(land|mybattlefield)~lessthan~1 then damage:1 && damage:1 target(creature|targetedpersonsBattlefield)
|
||||
auto=if thisturn(land|mybattlefield)~morethan~0 then damage:3 && damage:3 target(creature|targetedpersonsBattlefield)
|
||||
text=Searing Blaze deals 1 damage to target player and 1 damage to target creature that player controls. -- Landfall — If you had a land enter the battlefield under your control this turn, Searing Blaze deals 3 damage to that player and 3 damage to that creature instead.
|
||||
mana={R}{R}
|
||||
type=Instant
|
||||
|
||||
@@ -142,6 +142,7 @@ toughness=5
|
||||
name=Abolish
|
||||
target=artifact,enchantment
|
||||
other={D(plains|myhand)} name(Discard a Plains)
|
||||
otherrestriction=type(plains|myhand)~morethan~0
|
||||
auto=destroy
|
||||
text=You may discard a Plains card rather than pay Abolish's mana cost. -- Destroy target artifact or enchantment.
|
||||
mana={1}{W}{W}
|
||||
@@ -8609,7 +8610,7 @@ type=Artifact
|
||||
name=Baloth Cage Trap
|
||||
auto=token(Beast,Creature Beast,4/4,green)
|
||||
other={1}{G}
|
||||
otherrestriction=type(artifact[fresh]|opponentbattlefield)~morethan~0
|
||||
otherrestriction=thisturn(artifact|opponentbattlefield)~morethan~0
|
||||
text=If an opponent had an artifact enter the battlefield under his or her control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost. -- Put a 4/4 green Beast creature token onto the battlefield.
|
||||
mana={3}{G}{G}
|
||||
type=Instant
|
||||
@@ -50816,7 +50817,7 @@ toughness=1
|
||||
name=Groundswell
|
||||
target=creature
|
||||
auto=2/2
|
||||
auto=aslongas(land[fresh]|mybattlefield) 2/2
|
||||
auto=if thisturn(land|mybattlefield)~morethan~0 then 2/2
|
||||
text=Target creature gets +2/+2 until end of turn. -- Landfall - If you had a land enter the battlefield under your control this turn, that creature gets +4/+4 until end of turn instead.
|
||||
mana={G}
|
||||
type=Instant
|
||||
@@ -65765,7 +65766,7 @@ target=<2>land
|
||||
auto=destroy
|
||||
auto=damage:4 all(creature)
|
||||
other={3}{R}{R}
|
||||
otherrestriction=type(land[fresh]|opponentbattlefield)~morethan~1
|
||||
otherrestriction=thisturn(land|opponentbattlefield)~morethan~1
|
||||
text=If an opponent had two or more lands enter the battlefield under his or her control this turn, you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost. -- Destroy two target lands. Lavaball Trap deals 4 damage to each creature.
|
||||
mana={6}{R}{R}
|
||||
type=Instant
|
||||
@@ -77563,7 +77564,7 @@ text=Whenever you cast an artifact spell, you may pay {1}. If you do, put a 1/1
|
||||
[card]
|
||||
name=Mysteries of the Deep
|
||||
auto=draw:2
|
||||
auto=aslongas(land[fresh]|mybattlefield) draw:1
|
||||
auto=if thisturn(land|mybattlefield)~morethan~0 then draw:1
|
||||
text=Draw two cards. -- Landfall - If you had a land enter the battlefield under your control this turn, draw three cards instead.
|
||||
mana={4}{U}
|
||||
type=Instant
|
||||
@@ -81091,7 +81092,7 @@ type=Legendary Enchantment
|
||||
[card]
|
||||
name=Oath of Chandra
|
||||
auto=damage:3 target(creature|opponentbattlefield)
|
||||
auto=@each endofturn:if type(planeswalker[fresh]|mybattlefield)~morethan~0 then damage:2 opponent
|
||||
auto=@each endofturn restriction{thisturn(planeswalker|mybattlefield)~morethan~0}:damage:2 opponent
|
||||
text=When Oath of Chandra enters the battlefield, it deals 3 damage to target creature an opponent controls. -- At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, Oath of Chandra deals 2 damage to each opponent.
|
||||
mana={1}{R}
|
||||
type=Legendary Enchantment
|
||||
@@ -85238,7 +85239,7 @@ target=<upto:2>creature
|
||||
auto=tap
|
||||
auto=frozen
|
||||
other={U}
|
||||
otherrestriction=type(creature[green&fresh]|opponentbattlefield)~morethan~0
|
||||
otherrestriction=thisturn(creature[green]|mybattlefield)~morethan~0
|
||||
text=If an opponent had a green creature enter the battlefield under his or her control this turn, you may pay {U} rather than pay Permafrost Trap's mana cost. -- Tap up to two target creatures. Those creatures don't untap during their controller's next untap step.
|
||||
mana={2}{U}{U}
|
||||
type=Instant
|
||||
@@ -94205,7 +94206,7 @@ toughness=2
|
||||
name=Rest for the Weary
|
||||
target=player
|
||||
auto=life:4
|
||||
auto=aslongas(land[fresh]|mybattlefield) life:4
|
||||
auto=if thisturn(land|mybattlefield)~morethan~0 then life:4
|
||||
text=Target player gains 4 life. -- Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead.
|
||||
mana={1}{W}
|
||||
type=Instant
|
||||
@@ -122089,7 +122090,7 @@ toughness=4
|
||||
name=Tomb Hex
|
||||
target=creature
|
||||
auto=-2/-2
|
||||
auto=aslongas(land[fresh]|mybattlefield) -2/-2
|
||||
auto=if thisturn(land|mybattlefield)~morethan~0 then -2/-2
|
||||
text=Target creature gets -2/-2 until end of turn. -- Landfall - If you had a land enter the battlefield under your control this turn, that creature gets -4/-4 until end of turn instead.
|
||||
mana={2}{B}
|
||||
type=Instant
|
||||
@@ -124579,7 +124580,7 @@ subtype=Plains Island
|
||||
[/card]
|
||||
[card]
|
||||
name=Tunnel Ignus
|
||||
auto=@movedto(land|opponentbattlefield) restriction{type(land[fresh]|opponentbattlefield)~morethan~1}:damage:3 opponent
|
||||
auto=@movedto(land|opponentbattlefield) restriction{thisturn(land|opponentbattlefield)~morethan~1}:damage:3 opponent
|
||||
text=Whenever a land enters the battlefield under an opponent's control, if that player had another land enter the battlefield under his or her control this turn, Tunnel Ignus deals 3 damage to that player.
|
||||
mana={1}{R}
|
||||
type=Creature
|
||||
@@ -133164,7 +133165,7 @@ name=Whiplash Trap
|
||||
target=<2>creature
|
||||
auto=moveTo(ownerhand)
|
||||
other={U}
|
||||
otherrestriction=type(creature[fresh]|battlefield)~morethan~1
|
||||
otherrestriction=thisturn(creature|opponentbattlefield)~morethan~1
|
||||
text=If an opponent had two or more creatures enter the battlefield under his or her control this turn, you may pay {U} rather than pay Whiplash Trap's mana cost. -- Return two target creatures to their owners' hands.
|
||||
mana={3}{U}{U}
|
||||
type=Instant
|
||||
|
||||
@@ -93,6 +93,7 @@ class AIPlayerBaka: public AIPlayer{
|
||||
|
||||
virtual AIStats * getStats();
|
||||
|
||||
bool payAlternative;
|
||||
MTGCardInstance * nextCardToPlay;
|
||||
MTGCardInstance * activateCombo();
|
||||
TargetChooser * GetComboTc(GameObserver * observer, TargetChooser * tc = NULL);
|
||||
|
||||
@@ -2746,6 +2746,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
cd.init();
|
||||
cd.setType(type);
|
||||
card = NULL;
|
||||
payAlternative = false;
|
||||
gotPayments = vector<MTGAbility*>();
|
||||
//canplayfromgraveyard
|
||||
while ((card = cd.nextmatch(game->graveyard, card)))
|
||||
@@ -2828,10 +2829,21 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
int currentCost = card->getManaCost()->getConvertedCost();
|
||||
int hasX = card->getManaCost()->hasX();
|
||||
gotPayments.clear();
|
||||
if((!pMana->canAfford(card->getManaCost(),0) || card->getManaCost()->getKicker()))
|
||||
gotPayments = canPayMana(card,card->getManaCost(),card->has(Constants::ANYTYPEOFMANA));
|
||||
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
|
||||
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(card->getManaCost(),card->has(Constants::ANYTYPEOFMANA))))
|
||||
ManaCost* manaToPay = card->getManaCost();
|
||||
if(hasFlashback && !card->has(Constants::CANPLAYFROMGRAVEYARD) && !card->has(Constants::TEMPFLASHBACK) && !card->getManaCost()->getKicker()){
|
||||
manaToPay = card->getManaCost()->getFlashback();
|
||||
gotPayments = canPayMana(card,manaToPay,card->has(Constants::ANYTYPEOFMANA));
|
||||
}
|
||||
if(hasRetrace && !card->has(Constants::CANPLAYFROMGRAVEYARD) && !card->has(Constants::TEMPFLASHBACK) && !card->getManaCost()->getKicker()){
|
||||
manaToPay = card->getManaCost()->getRetrace();
|
||||
gotPayments = canPayMana(card,manaToPay,card->has(Constants::ANYTYPEOFMANA));
|
||||
}
|
||||
else {
|
||||
if((!pMana->canAfford(card->getManaCost(),0) || card->getManaCost()->getKicker()))
|
||||
gotPayments = canPayMana(card,card->getManaCost(),card->has(Constants::ANYTYPEOFMANA));
|
||||
}
|
||||
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
|
||||
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(manaToPay,card->has(Constants::ANYTYPEOFMANA))))
|
||||
{
|
||||
TargetChooserFactory tcf(observer);
|
||||
TargetChooser * tc = tcf.createTargetChooser(card);
|
||||
@@ -3221,6 +3233,8 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
card = NULL; // fixed bug causing AI never play a card there are one or more cards in exile or other zones...
|
||||
while ((card = cd.nextmatch(game->hand, card)))
|
||||
{
|
||||
bool localpayAlternative = false;
|
||||
|
||||
if (!CanHandleCost(card->getManaCost(),card))
|
||||
continue;
|
||||
|
||||
@@ -3272,10 +3286,17 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
int currentCost = card->getManaCost()->getConvertedCost();
|
||||
int hasX = card->getManaCost()->hasX();
|
||||
gotPayments.clear();
|
||||
ManaCost* manaToPay = card->getManaCost();
|
||||
if((!pMana->canAfford(card->getManaCost(),0) || card->getManaCost()->getKicker()))
|
||||
gotPayments = canPayMana(card,card->getManaCost(),card->has(Constants::ANYTYPEOFMANA));
|
||||
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
|
||||
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(card->getManaCost(),card->has(Constants::ANYTYPEOFMANA))))
|
||||
if(card->getManaCost()->getAlternative() && !gotPayments.size() && !pMana->canAfford(card->getManaCost(),0) && !card->getManaCost()->getKicker()){ // Now AI can cast cards using alternative cost.
|
||||
localpayAlternative = true;
|
||||
manaToPay = card->getManaCost()->getAlternative();
|
||||
if(!pMana->canAfford(manaToPay,0))
|
||||
gotPayments = canPayMana(card,card->getManaCost()->getAlternative(),card->has(Constants::ANYTYPEOFMANA));
|
||||
}
|
||||
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
|
||||
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(manaToPay,card->has(Constants::ANYTYPEOFMANA))))
|
||||
{
|
||||
TargetChooserFactory tcf(observer);
|
||||
TargetChooser * tc = tcf.createTargetChooser(card);
|
||||
@@ -3353,12 +3374,34 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
}
|
||||
DebugTrace("Should I play from hand" << (card ? card->name : "Nothing" ) << "?" << endl
|
||||
<<"shouldPlayPercentage = "<< shouldPlayPercentage);
|
||||
if(card->getRestrictions().size())
|
||||
{
|
||||
AbilityFactory af(observer);
|
||||
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
|
||||
if(!canPlay)
|
||||
continue;
|
||||
if(localpayAlternative){
|
||||
if(card->getOtherRestrictions().size())
|
||||
{
|
||||
AbilityFactory af(observer);
|
||||
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getOtherRestrictions());
|
||||
if(!canPlay){
|
||||
localpayAlternative = false;
|
||||
canPlay = true;
|
||||
if(card->getRestrictions().size())
|
||||
canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions()); //Check if card can be casted at least with normal cost.
|
||||
}
|
||||
if(!canPlay)
|
||||
continue;
|
||||
}
|
||||
} else{
|
||||
if(card->getRestrictions().size())
|
||||
{
|
||||
AbilityFactory af(observer);
|
||||
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
|
||||
if(!canPlay && card->getManaCost()->getAlternative()){
|
||||
canPlay = true;
|
||||
if(card->getOtherRestrictions().size())
|
||||
canPlay = af.parseCastRestrictions(card,card->controller(),card->getOtherRestrictions()); //Check if card can be casted at least with other cost.
|
||||
if(canPlay) localpayAlternative = true;
|
||||
}
|
||||
if(!canPlay)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int randomChance = randomGenerator.random();
|
||||
int chance = randomChance % 100;
|
||||
@@ -3369,6 +3412,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
DebugTrace("shouldPlayPercentage was less than 10 this was a lottery roll on RNG");
|
||||
}
|
||||
nextCardToPlay = card;
|
||||
payAlternative = localpayAlternative;
|
||||
maxCost = currentCost;
|
||||
if (hasX)
|
||||
maxCost = pMana->getConvertedCost();
|
||||
@@ -3384,6 +3428,9 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
||||
if(!pMana->canAfford(nextCardToPlay->getManaCost()->getRetrace(),0))
|
||||
gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost()->getRetrace(),nextCardToPlay->has(Constants::ANYTYPEOFMANA));
|
||||
}
|
||||
} else if(payAlternative){
|
||||
if(!pMana->canAfford(nextCardToPlay->getManaCost()->getAlternative(),0)) // Now AI can cast cards using alternative cost.
|
||||
gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost()->getAlternative(),nextCardToPlay->has(Constants::ANYTYPEOFMANA));
|
||||
} else {
|
||||
if(!pMana->canAfford(nextCardToPlay->getManaCost(),0) || nextCardToPlay->getManaCost()->getKicker())
|
||||
gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost(),nextCardToPlay->has(Constants::ANYTYPEOFMANA));
|
||||
@@ -3547,11 +3594,36 @@ int AIPlayerBaka::computeActions()
|
||||
{
|
||||
if (ipotential)
|
||||
{
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay->has(Constants::ANYTYPEOFMANAABILITY),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
if(nextCardToPlay->currentZone == game->graveyard && !nextCardToPlay->has(Constants::CANPLAYFROMGRAVEYARD) && !nextCardToPlay->has(Constants::TEMPFLASHBACK)){ //Now AI can play cards with flashback and retrace costs.
|
||||
if(nextCardToPlay->getManaCost()->getFlashback()){
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost()->getFlashback(),nextCardToPlay->has(Constants::ANYTYPEOFMANA),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
}
|
||||
} else if(nextCardToPlay->getManaCost()->getRetrace()){
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost()->getRetrace(),nextCardToPlay->has(Constants::ANYTYPEOFMANA),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
}
|
||||
}
|
||||
} else if(payAlternative){ // Now AI can cast cards using alternative cost.
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost()->getAlternative(),nextCardToPlay->has(Constants::ANYTYPEOFMANA),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
}
|
||||
} else {
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay->has(Constants::ANYTYPEOFMANA),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef AI_CHANGE_TESTING
|
||||
@@ -3722,6 +3794,13 @@ int AIPlayerBaka::computeActions()
|
||||
gotPayments.clear();
|
||||
}
|
||||
}
|
||||
} else if(payAlternative){ // Now AI can cast cards using alternative cost.
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost()->getAlternative(),nextCardToPlay->has(Constants::ANYTYPEOFMANA),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
}
|
||||
} else {
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay->has(Constants::ANYTYPEOFMANA),nextCardToPlay,gotPayments))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user