Erwan
- introducing "grade" system for cards - Fixed a few typos in _cards.dat
This commit is contained in:
@@ -247,7 +247,7 @@ mana={1}{W}{B}{R}
|
|||||||
type=Enchantment
|
type=Enchantment
|
||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
Whenever Flowstone Charger attacks, it gets +3/-3 until end of turn.
|
text=Whenever Flowstone Charger attacks, it gets +3/-3 until end of turn.
|
||||||
id=19117
|
id=19117
|
||||||
name=Flowstone Charger
|
name=Flowstone Charger
|
||||||
rarity=U
|
rarity=U
|
||||||
@@ -567,7 +567,7 @@ power=2
|
|||||||
toughness=2
|
toughness=2
|
||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
text=Domain — All creatures get -1/-1 until end of turn for each basic land type among lands you control.
|
text=Domain �EAll creatures get -1/-1 until end of turn for each basic land type among lands you control.
|
||||||
auto=aslongas(swamp|myBattlefield) lord(creature) -1/-1
|
auto=aslongas(swamp|myBattlefield) lord(creature) -1/-1
|
||||||
auto=aslongas(mountain|myBattlefield) lord(creature) -1/-1
|
auto=aslongas(mountain|myBattlefield) lord(creature) -1/-1
|
||||||
auto=aslongas(forest|myBattlefield) lord(creature) -1/-1
|
auto=aslongas(forest|myBattlefield) lord(creature) -1/-1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
p[meta]
|
[meta]
|
||||||
author=Wagic Team
|
author=Wagic Team
|
||||||
year=1998
|
year=1998
|
||||||
block=Portal
|
block=Portal
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ alias=1156
|
|||||||
name=Drain Life
|
name=Drain Life
|
||||||
mana={X}{1}{B}
|
mana={X}{1}{B}
|
||||||
type=Sorcery
|
type=Sorcery
|
||||||
|
grade=Borderline (can use non black mana)
|
||||||
[/card]
|
[/card]
|
||||||
[card]
|
[card]
|
||||||
name=Forest
|
name=Forest
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public:
|
|||||||
REVERSETRIGGERS,
|
REVERSETRIGGERS,
|
||||||
DISABLECARDS,
|
DISABLECARDS,
|
||||||
INTERRUPT_SECONDS,
|
INTERRUPT_SECONDS,
|
||||||
|
MAX_GRADE,
|
||||||
//My interrupts
|
//My interrupts
|
||||||
INTERRUPTMYSPELLS,
|
INTERRUPTMYSPELLS,
|
||||||
INTERRUPTMYABILITIES,
|
INTERRUPTMYABILITIES,
|
||||||
@@ -159,6 +160,15 @@ private:
|
|||||||
OptionManaDisplay();
|
OptionManaDisplay();
|
||||||
static OptionManaDisplay mDef;
|
static OptionManaDisplay mDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OptionMaxGrade: public EnumDefinition {
|
||||||
|
public:
|
||||||
|
static EnumDefinition * getInstance() {return &mDef;};
|
||||||
|
private:
|
||||||
|
OptionMaxGrade();
|
||||||
|
static OptionMaxGrade mDef;
|
||||||
|
};
|
||||||
|
|
||||||
class OptionDifficulty: public EnumDefinition {
|
class OptionDifficulty: public EnumDefinition {
|
||||||
public:
|
public:
|
||||||
enum { NORMAL = 0, HARD = 1, HARDER = 2, EVIL = 3};
|
enum { NORMAL = 0, HARD = 1, HARDER = 2, EVIL = 3};
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ class MTGAllCards {
|
|||||||
private:
|
private:
|
||||||
MTGCard * tempCard; //used by parser
|
MTGCard * tempCard; //used by parser
|
||||||
CardPrimitive * tempPrimitive; //used by parser
|
CardPrimitive * tempPrimitive; //used by parser
|
||||||
|
int currentGrade; //used by Parser (we don't want an additional attribute for the primitives for that as it is only used at load time)
|
||||||
protected:
|
protected:
|
||||||
int conf_read_mode;
|
int conf_read_mode;
|
||||||
int colorsCount[Constants::MTG_NB_COLORS];
|
int colorsCount[Constants::MTG_NB_COLORS];
|
||||||
@@ -113,7 +114,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
int processConfLine(string s, MTGCard* card, CardPrimitive * primitive);
|
int processConfLine(string s, MTGCard* card, CardPrimitive * primitive);
|
||||||
bool addCardToCollection(MTGCard * card, int setId);
|
bool addCardToCollection(MTGCard * card, int setId);
|
||||||
bool addPrimitive(CardPrimitive * primitive, MTGCard * card = NULL);
|
CardPrimitive * addPrimitive(CardPrimitive * primitive, MTGCard * card = NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,12 @@ class Constants
|
|||||||
MENU_FONT = 1,
|
MENU_FONT = 1,
|
||||||
MAGIC_FONT = 2,
|
MAGIC_FONT = 2,
|
||||||
OPTION_FONT = 1,
|
OPTION_FONT = 1,
|
||||||
|
|
||||||
|
GRADE_SUPPORTED = 1,
|
||||||
|
GRADE_BORDERLINE = 2,
|
||||||
|
GRADE_CRAPPY = 3,
|
||||||
|
GRADE_UNSUPPORTED = 4,
|
||||||
|
GRADE_DANGEROUS = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
static char MTGColorChars[];
|
static char MTGColorChars[];
|
||||||
|
|||||||
@@ -440,15 +440,15 @@ class OptionInteger:public OptionItem{
|
|||||||
int value; //Current value.
|
int value; //Current value.
|
||||||
int defValue; //Default value.
|
int defValue; //Default value.
|
||||||
string strDefault; //What to call the default value.
|
string strDefault; //What to call the default value.
|
||||||
int maxValue, increment;
|
int maxValue, increment, minValue;
|
||||||
|
|
||||||
OptionInteger(int _id, string _displayValue, int _maxValue = 1, int _increment = 1, int _defV = 0, string _sDef = "");
|
OptionInteger(int _id, string _displayValue, int _maxValue = 1, int _increment = 1, int _defV = 0, string _sDef = "", int _minValue = 0);
|
||||||
|
|
||||||
virtual void Reload() {if(id != INVALID_OPTION) value = options[id].number;};
|
virtual void Reload() {if(id != INVALID_OPTION) value = options[id].number;};
|
||||||
virtual bool Changed() {return value != options[id].number;};
|
virtual bool Changed() {return value != options[id].number;};
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
virtual void setData();
|
virtual void setData();
|
||||||
virtual void updateValue(){value+=increment; if (value>maxValue) value=0;};
|
virtual void updateValue(){value+=increment; if (value>maxValue) value=minValue;};
|
||||||
};
|
};
|
||||||
|
|
||||||
class OptionSelect:public OptionItem{
|
class OptionSelect:public OptionItem{
|
||||||
|
|||||||
@@ -112,11 +112,12 @@ void GameApp::Create()
|
|||||||
manaIcons[Constants::MTG_COLOR_LAND] = resources.RetrieveQuad("menuicons.png", 2 + 5*36, 38, 32, 32, "c_land",RETRIEVE_MANAGE);
|
manaIcons[Constants::MTG_COLOR_LAND] = resources.RetrieveQuad("menuicons.png", 2 + 5*36, 38, 32, 32, "c_land",RETRIEVE_MANAGE);
|
||||||
manaIcons[Constants::MTG_COLOR_ARTIFACT] = resources.RetrieveQuad("menuicons.png", 2 + 6*36, 38, 32, 32, "c_artifact",RETRIEVE_MANAGE);
|
manaIcons[Constants::MTG_COLOR_ARTIFACT] = resources.RetrieveQuad("menuicons.png", 2 + 6*36, 38, 32, 32, "c_artifact",RETRIEVE_MANAGE);
|
||||||
|
|
||||||
|
|
||||||
for (int i = sizeof(manaIcons)/sizeof(manaIcons[0]) - 1; i >= 0; --i) manaIcons[i]->SetHotSpot(16,16);
|
for (int i = sizeof(manaIcons)/sizeof(manaIcons[0]) - 1; i >= 0; --i) manaIcons[i]->SetHotSpot(16,16);
|
||||||
|
|
||||||
resources.RetrieveTexture("back.jpg",RETRIEVE_MANAGE);
|
resources.RetrieveTexture("back.jpg",RETRIEVE_MANAGE);
|
||||||
JQuad * jq = resources.RetrieveQuad("back.jpg", 0, 0, 0, 0, "back",RETRIEVE_MANAGE);
|
JQuad * jq = resources.RetrieveQuad("back.jpg", 0, 0, 0, 0, "back",RETRIEVE_MANAGE);
|
||||||
jq->SetHotSpot(jq->mWidth/2, jq->mHeight/2);
|
if (jq) jq->SetHotSpot(jq->mWidth/2, jq->mHeight/2);
|
||||||
|
|
||||||
resources.RetrieveTexture("back_thumb.jpg",RETRIEVE_MANAGE);
|
resources.RetrieveTexture("back_thumb.jpg",RETRIEVE_MANAGE);
|
||||||
resources.RetrieveQuad("back_thumb.jpg", 0, 0, MTG_MINIIMAGE_WIDTH, MTG_MINIIMAGE_HEIGHT, "back_thumb",RETRIEVE_MANAGE);
|
resources.RetrieveQuad("back_thumb.jpg", 0, 0, MTG_MINIIMAGE_WIDTH, MTG_MINIIMAGE_HEIGHT, "back_thumb",RETRIEVE_MANAGE);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const char * Options::optionNames[] = {
|
|||||||
"reverse_triggers",
|
"reverse_triggers",
|
||||||
"disable_cards",
|
"disable_cards",
|
||||||
"interruptSeconds",
|
"interruptSeconds",
|
||||||
|
"maxGrade",
|
||||||
"interruptMySpells",
|
"interruptMySpells",
|
||||||
"interruptMyAbilities",
|
"interruptMyAbilities",
|
||||||
//General interrupts
|
//General interrupts
|
||||||
@@ -291,6 +292,10 @@ int GameOptions::load(){
|
|||||||
// (PSY) Make sure that cheatmode is switched off for ineligible profiles:
|
// (PSY) Make sure that cheatmode is switched off for ineligible profiles:
|
||||||
if(options[Options::ACTIVE_PROFILE].str != SECRET_PROFILE)
|
if(options[Options::ACTIVE_PROFILE].str != SECRET_PROFILE)
|
||||||
(*this)[Options::CHEATMODE].number = 0;
|
(*this)[Options::CHEATMODE].number = 0;
|
||||||
|
|
||||||
|
//Default values. Anywhere else to put those ?
|
||||||
|
if (! (*this)[Options::MAX_GRADE].number) (*this)[Options::MAX_GRADE].number = Constants::GRADE_BORDERLINE;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int GameOptions::save(){
|
int GameOptions::save(){
|
||||||
@@ -356,6 +361,11 @@ GameOption * GameOptions::get(int optionID) {
|
|||||||
goEnum->def = OptionManaDisplay::getInstance();
|
goEnum->def = OptionManaDisplay::getInstance();
|
||||||
go = goEnum;
|
go = goEnum;
|
||||||
break;
|
break;
|
||||||
|
case Options::MAX_GRADE:
|
||||||
|
goEnum = NEW GameOptionEnum();
|
||||||
|
goEnum->def = OptionMaxGrade::getInstance();
|
||||||
|
go = goEnum;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if(x >= Options::BEGIN_AWARDS)
|
if(x >= Options::BEGIN_AWARDS)
|
||||||
go = NEW GameOptionAward();
|
go = NEW GameOptionAward();
|
||||||
@@ -694,6 +704,15 @@ bool GameOptionEnum::read(string input){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Enum Definitions
|
//Enum Definitions
|
||||||
|
OptionMaxGrade OptionMaxGrade::mDef;
|
||||||
|
OptionMaxGrade::OptionMaxGrade(){
|
||||||
|
mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_SUPPORTED, "1 - 100% Supported"));
|
||||||
|
mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_BORDERLINE, "2 - Borderline (99% OK)"));
|
||||||
|
mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_CRAPPY, "3 - Crappy (bugs)"));
|
||||||
|
mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_UNSUPPORTED, "4 - Unsupported"));
|
||||||
|
mDef.values.push_back(EnumDefinition::assoc(Constants::GRADE_DANGEROUS, "5 - Dangerous (risk of crash)"));
|
||||||
|
|
||||||
|
};
|
||||||
OptionClosedHand OptionClosedHand::mDef;
|
OptionClosedHand OptionClosedHand::mDef;
|
||||||
OptionClosedHand::OptionClosedHand(){
|
OptionClosedHand::OptionClosedHand(){
|
||||||
mDef.values.push_back(EnumDefinition::assoc(INVISIBLE, "invisible"));
|
mDef.values.push_back(EnumDefinition::assoc(INVISIBLE, "invisible"));
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum ENUM_DUEL_STATE
|
enum ENUM_DUEL_STATEseems
|
||||||
{
|
{
|
||||||
DUEL_STATE_START,
|
DUEL_STATE_START,
|
||||||
DUEL_STATE_END,
|
DUEL_STATE_END,
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ void GameStateOptions::Start()
|
|||||||
optionsList->Add(NEW WGuiButton(NEW WGuiHeader("New Profile"),-102,4,this));
|
optionsList->Add(NEW WGuiButton(NEW WGuiHeader("New Profile"),-102,4,this));
|
||||||
optionsTabs->Add(optionsList);
|
optionsTabs->Add(optionsList);
|
||||||
|
|
||||||
|
optionsList = NEW WGuiList("Advanced");
|
||||||
|
optionsList->Add(NEW WGuiHeader("Advanced Options"));
|
||||||
|
optionsList->Add(NEW WDecoEnum(NEW OptionInteger(Options::MAX_GRADE,"Cards grade(restart)",Constants::GRADE_DANGEROUS,1,Constants::GRADE_BORDERLINE,"",Constants::GRADE_SUPPORTED)));
|
||||||
|
optionsTabs->Add(optionsList);
|
||||||
|
|
||||||
optionsList = NEW WGuiList("Credits");
|
optionsList = NEW WGuiList("Credits");
|
||||||
optionsList->failMsg = "";
|
optionsList->failMsg = "";
|
||||||
optionsTabs->Add(optionsList);
|
optionsTabs->Add(optionsList);
|
||||||
|
|||||||
@@ -72,6 +72,32 @@ int MTGAllCards::processConfLine(string s, MTGCard *card, CardPrimitive * primit
|
|||||||
primitive->setColor(value,1);
|
primitive->setColor(value,1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'g': //grade
|
||||||
|
{
|
||||||
|
switch(value[0]) {
|
||||||
|
case 'S':
|
||||||
|
case 's':
|
||||||
|
currentGrade = Constants::GRADE_SUPPORTED;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
case 'b':
|
||||||
|
currentGrade = Constants::GRADE_BORDERLINE;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
case 'c':
|
||||||
|
currentGrade = Constants::GRADE_CRAPPY;
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
case 'u':
|
||||||
|
currentGrade = Constants::GRADE_UNSUPPORTED;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
case 'd':
|
||||||
|
currentGrade = Constants::GRADE_DANGEROUS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'k': //kicker
|
case 'k': //kicker
|
||||||
if(!primitive) primitive = NEW CardPrimitive();
|
if(!primitive) primitive = NEW CardPrimitive();
|
||||||
std::transform( value.begin(), value.end(), value.begin(),::tolower );
|
std::transform( value.begin(), value.end(), value.begin(),::tolower );
|
||||||
@@ -99,7 +125,10 @@ int MTGAllCards::processConfLine(string s, MTGCard *card, CardPrimitive * primit
|
|||||||
case 'p':
|
case 'p':
|
||||||
if(key.compare("primitive")==0){
|
if(key.compare("primitive")==0){
|
||||||
if(!card) card = NEW MTGCard();
|
if(!card) card = NEW MTGCard();
|
||||||
card->setPrimitive(primitives[value]);
|
map<string,CardPrimitive *>::iterator it = primitives.find(value);
|
||||||
|
if (it != primitives.end()) {
|
||||||
|
card->setPrimitive(it->second);
|
||||||
|
}
|
||||||
} else { //power
|
} else { //power
|
||||||
if(!primitive) primitive = NEW CardPrimitive();
|
if(!primitive) primitive = NEW CardPrimitive();
|
||||||
primitive->setPower (atoi(value.c_str()));
|
primitive->setPower (atoi(value.c_str()));
|
||||||
@@ -286,6 +315,11 @@ bool MTGAllCards::addCardToCollection(MTGCard * card, int setId){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Don't add cards that don't have a primitive
|
||||||
|
if (!card->data){
|
||||||
|
SAFE_DELETE(card);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ids.push_back(newId);
|
ids.push_back(newId);
|
||||||
|
|
||||||
collection[newId] = card; //Push card into collection.
|
collection[newId] = card; //Push card into collection.
|
||||||
@@ -299,7 +333,13 @@ bool MTGAllCards::addCardToCollection(MTGCard * card, int setId){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MTGAllCards::addPrimitive(CardPrimitive * primitive, MTGCard * card){
|
CardPrimitive * MTGAllCards::addPrimitive(CardPrimitive * primitive, MTGCard * card){
|
||||||
|
int maxGrade = options[Options::MAX_GRADE].number;
|
||||||
|
if (!maxGrade) maxGrade = Constants::GRADE_BORDERLINE;
|
||||||
|
if (currentGrade >maxGrade) {
|
||||||
|
SAFE_DELETE(primitive);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
string key;
|
string key;
|
||||||
if (card) {
|
if (card) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@@ -314,9 +354,9 @@ bool MTGAllCards::addPrimitive(CardPrimitive * primitive, MTGCard * card){
|
|||||||
OutputDebugString("MTGDECK: primitives conflict:");
|
OutputDebugString("MTGDECK: primitives conflict:");
|
||||||
OutputDebugString(key.c_str());
|
OutputDebugString(key.c_str());
|
||||||
OutputDebugString("\n");
|
OutputDebugString("\n");
|
||||||
SAFE_DELETE(primitive);
|
|
||||||
#endif
|
#endif
|
||||||
return false;
|
SAFE_DELETE(primitive);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
//translate cards text
|
//translate cards text
|
||||||
Translator * t = Translator::GetInstance();
|
Translator * t = Translator::GetInstance();
|
||||||
@@ -331,7 +371,7 @@ bool MTGAllCards::addPrimitive(CardPrimitive * primitive, MTGCard * card){
|
|||||||
if (primitive->hasType(Subtypes::TYPE_ARTIFACT)) primitive->setColor(Constants::MTG_COLOR_ARTIFACT);
|
if (primitive->hasType(Subtypes::TYPE_ARTIFACT)) primitive->setColor(Constants::MTG_COLOR_ARTIFACT);
|
||||||
|
|
||||||
primitives[key] = primitive;
|
primitives[key] = primitive;
|
||||||
return true;
|
return primitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MTGAllCards::readConfLine(std::ifstream &file, int set_id){
|
int MTGAllCards::readConfLine(std::ifstream &file, int set_id){
|
||||||
@@ -344,6 +384,7 @@ int MTGAllCards::readConfLine(std::ifstream &file, int set_id){
|
|||||||
switch(conf_read_mode) {
|
switch(conf_read_mode) {
|
||||||
case MTGAllCards::READ_ANYTHING:
|
case MTGAllCards::READ_ANYTHING:
|
||||||
if (s[0] == '['){
|
if (s[0] == '['){
|
||||||
|
currentGrade = Constants::GRADE_SUPPORTED; //default value
|
||||||
if(s[1] == 'm'){ //M for metadata.
|
if(s[1] == 'm'){ //M for metadata.
|
||||||
conf_read_mode = MTGAllCards::READ_METADATA;
|
conf_read_mode = MTGAllCards::READ_METADATA;
|
||||||
}
|
}
|
||||||
@@ -363,10 +404,10 @@ int MTGAllCards::readConfLine(std::ifstream &file, int set_id){
|
|||||||
case MTGAllCards::READ_CARD:
|
case MTGAllCards::READ_CARD:
|
||||||
if (s[0] == '[' && s[1] == '/'){
|
if (s[0] == '[' && s[1] == '/'){
|
||||||
conf_read_mode = MTGAllCards::READ_ANYTHING;
|
conf_read_mode = MTGAllCards::READ_ANYTHING;
|
||||||
if (tempPrimitive) addPrimitive (tempPrimitive,tempCard);
|
if (tempPrimitive) tempPrimitive = addPrimitive (tempPrimitive,tempCard);
|
||||||
if (tempCard){
|
if (tempCard){
|
||||||
addCardToCollection(tempCard, set_id);
|
|
||||||
if (tempPrimitive) tempCard->setPrimitive(tempPrimitive);
|
if (tempPrimitive) tempCard->setPrimitive(tempPrimitive);
|
||||||
|
addCardToCollection(tempCard, set_id);
|
||||||
}
|
}
|
||||||
tempCard = NULL;
|
tempCard = NULL;
|
||||||
tempPrimitive = NULL;
|
tempPrimitive = NULL;
|
||||||
|
|||||||
@@ -100,10 +100,11 @@ void OptionInteger::Render(){
|
|||||||
mFont->DrawString(buf,width -10 ,y,JGETEXT_RIGHT);
|
mFont->DrawString(buf,width -10 ,y,JGETEXT_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionInteger::OptionInteger(int _id, string _displayValue, int _maxValue, int _increment, int _defV, string _sDef): OptionItem(_id, _displayValue){
|
OptionInteger::OptionInteger(int _id, string _displayValue, int _maxValue, int _increment, int _defV, string _sDef, int _minValue): OptionItem(_id, _displayValue){
|
||||||
defValue = _defV;
|
defValue = _defV;
|
||||||
strDefault = _sDef;
|
strDefault = _sDef;
|
||||||
maxValue = _maxValue;
|
maxValue = _maxValue;
|
||||||
|
minValue = _minValue;
|
||||||
increment = _increment;
|
increment = _increment;
|
||||||
value = ::options[id].number;
|
value = ::options[id].number;
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user