- Added function skill_strip to handle stripping code. The RG strip skills and GS_DISARM use it now.
- Modified the strip-related status changes so they handle removing the equipped item instead of leaving it up to the skill-code. They return 0 when nothing could be stripped. - Cleaned some the MD_DETECTOR code. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9499 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
5b46682b66
commit
b8a2a5f905
@ -3,6 +3,9 @@ Date Added
|
|||||||
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
|
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
|
||||||
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
||||||
|
|
||||||
|
2006/12/14
|
||||||
|
* Cleaned up the strip code (GS_DISARM, rogue skills).
|
||||||
|
* Cleaned some the MD_DETECTOR code.
|
||||||
2006/12/13
|
2006/12/13
|
||||||
* Additional damage bonuses (True Sight, EDP, Assassin Link, Crusader Link,
|
* Additional damage bonuses (True Sight, EDP, Assassin Link, Crusader Link,
|
||||||
Card skill damage bonuses) are now applied independently of each other,
|
Card skill damage bonuses) are now applied independently of each other,
|
||||||
|
@ -375,11 +375,6 @@
|
|||||||
236,2000,0,0,120000:240000:360000:480000:600000,0
|
236,2000,0,0,120000:240000:360000:480000:600000,0
|
||||||
//-- AM_CP_HELM
|
//-- AM_CP_HELM
|
||||||
237,2000,0,0,120000:240000:360000:480000:600000,0
|
237,2000,0,0,120000:240000:360000:480000:600000,0
|
||||||
//==========================================
|
|
||||||
//-- AM_CALLHOMUNCULUS
|
|
||||||
243,0,0,0,0,0
|
|
||||||
//-- AM_REST
|
|
||||||
244,0,0,0,0,0
|
|
||||||
//-- AM_RESURRECTHOMUN
|
//-- AM_RESURRECTHOMUN
|
||||||
247,2000,0,0,0,0
|
247,2000,0,0,0,0
|
||||||
//==========================================
|
//==========================================
|
||||||
|
@ -6869,8 +6869,6 @@ int clif_guild_basicinfo(struct map_session_data *sd)
|
|||||||
strncpy((char*)WFIFOP(fd,94),msg_txt(299),20);
|
strncpy((char*)WFIFOP(fd,94),msg_txt(299),20);
|
||||||
|
|
||||||
WFIFOSET(fd,packet_len_table[WFIFOW(fd,0)]);
|
WFIFOSET(fd,packet_len_table[WFIFOW(fd,0)]);
|
||||||
// Found the appropriate packet field, testing for a trial period. [FlavioJS]
|
|
||||||
//clif_guild_emblem(sd,g); // Guild emblem vanish fix [Valaris]
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11823,13 +11821,6 @@ int clif_parse(int fd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sd = (TBL_PC *)session[fd]->session_data;
|
sd = (TBL_PC *)session[fd]->session_data;
|
||||||
|
|
||||||
if (sd && sd->fd != fd)
|
|
||||||
{ //FIXME: Temporal debug until a certain mysterious crash is fixed.
|
|
||||||
ShowError("Player's connection value is incorrect! %d != %d\n", sd->fd, fd);
|
|
||||||
sd->fd = fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session[fd]->eof) {
|
if (session[fd]->eof) {
|
||||||
if (sd) {
|
if (sd) {
|
||||||
if (sd->state.autotrade) {
|
if (sd->state.autotrade) {
|
||||||
|
@ -7815,7 +7815,7 @@ int buildin_homunculus_evolution(struct script_state *st)
|
|||||||
struct map_session_data *sd;
|
struct map_session_data *sd;
|
||||||
sd=script_rid2sd(st);
|
sd=script_rid2sd(st);
|
||||||
if ( sd->hd && sd->hd->homunculusDB->evo_class && sd->hd->homunculus.intimacy > 91000 ) {
|
if ( sd->hd && sd->hd->homunculusDB->evo_class && sd->hd->homunculus.intimacy > 91000 ) {
|
||||||
return merc_hom_evolution(sd->hd) ;
|
return !merc_hom_evolution(sd->hd) ;
|
||||||
}
|
}
|
||||||
clif_emotion(&sd->hd->bl, 4) ; //swt
|
clif_emotion(&sd->hd->bl, 4) ; //swt
|
||||||
return 0;
|
return 0;
|
||||||
|
147
src/map/skill.c
147
src/map/skill.c
@ -1356,22 +1356,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
|
|||||||
rate = 3*skilllv;
|
rate = 3*skilllv;
|
||||||
if (sstatus->dex > tstatus->dex)
|
if (sstatus->dex > tstatus->dex)
|
||||||
rate += (sstatus->dex - tstatus->dex)/5;
|
rate += (sstatus->dex - tstatus->dex)/5;
|
||||||
|
skill_strip_equip(bl, EQP_WEAPON, rate, skilllv, skill_get_time(skillid,skilllv));
|
||||||
if (rand()%100 >= rate)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (dstsd) {
|
|
||||||
if (dstsd->equip_index[EQI_HAND_R]<0 ||
|
|
||||||
!dstsd->inventory_data[dstsd->equip_index[EQI_HAND_R]] ||
|
|
||||||
!(dstsd->unstripable_equip&EQP_WEAPON) ||
|
|
||||||
(tsc && tsc->data[SC_CP_WEAPON].timer != -1)
|
|
||||||
) //Fail
|
|
||||||
break;
|
|
||||||
pc_unequipitem(dstsd,dstsd->equip_index[EQI_HAND_R],3);
|
|
||||||
} else if (tstatus->mode&MD_BOSS ||
|
|
||||||
(tsc && tsc->data[SC_CP_WEAPON].timer != -1))
|
|
||||||
break;
|
|
||||||
sc_start(bl,SC_STRIPWEAPON,100,skilllv,skill_get_time(skillid,skilllv));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1721,6 +1706,36 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
|
|||||||
|
|
||||||
return where; //Return list of pieces broken.
|
return where; //Return list of pieces broken.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time)
|
||||||
|
{
|
||||||
|
struct status_change *sc;
|
||||||
|
const int pos[4] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM};
|
||||||
|
const int sc_atk[4] = {SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM};
|
||||||
|
const int sc_def[4] = {SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (rand()%100 >= rate)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sc = status_get_sc(bl);
|
||||||
|
if (!sc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(pos)/sizeof(pos[0]); i++) {
|
||||||
|
if (where&pos[i] && sc->data[sc_def[i]].timer != -1)
|
||||||
|
where&=~pos[i];
|
||||||
|
}
|
||||||
|
if (!where) return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(pos)/sizeof(pos[0]); i++) {
|
||||||
|
if (where&pos[i] && !sc_start(bl, sc_atk[i], 100, lv, time))
|
||||||
|
where&=~pos[i];
|
||||||
|
}
|
||||||
|
return where?1:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*=========================================================================
|
/*=========================================================================
|
||||||
Used to knock back players, monsters, traps, etc
|
Used to knock back players, monsters, traps, etc
|
||||||
If count&0xf00000, the direction is send in the 6th byte.
|
If count&0xf00000, the direction is send in the 6th byte.
|
||||||
@ -4429,106 +4444,32 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
|||||||
case RG_STRIPSHIELD:
|
case RG_STRIPSHIELD:
|
||||||
case RG_STRIPARMOR:
|
case RG_STRIPARMOR:
|
||||||
case RG_STRIPHELM:
|
case RG_STRIPHELM:
|
||||||
case ST_FULLSTRIP: // Rewritten most of the code [DracoRPG]
|
case ST_FULLSTRIP:
|
||||||
{
|
i = 5+2*skilllv;
|
||||||
int strip_fix, equip = 0;
|
if (sstatus->dex > tstatus->dex)
|
||||||
int sclist[4] = {0,0,0,0};
|
i += (sstatus->dex - tstatus->dex)/5;
|
||||||
|
|
||||||
switch (skillid) {
|
switch (skillid) {
|
||||||
case RG_STRIPWEAPON:
|
case RG_STRIPWEAPON:
|
||||||
equip = EQP_WEAPON;
|
type = EQP_WEAPON;
|
||||||
break;
|
break;
|
||||||
case RG_STRIPSHIELD:
|
case RG_STRIPSHIELD:
|
||||||
equip = EQP_SHIELD;
|
type = EQP_SHIELD;
|
||||||
break;
|
break;
|
||||||
case RG_STRIPARMOR:
|
case RG_STRIPARMOR:
|
||||||
equip = EQP_ARMOR;
|
type = EQP_ARMOR;
|
||||||
break;
|
break;
|
||||||
case RG_STRIPHELM:
|
case RG_STRIPHELM:
|
||||||
equip = EQP_HELM;
|
type = EQP_HELM;
|
||||||
break;
|
break;
|
||||||
case ST_FULLSTRIP:
|
case ST_FULLSTRIP:
|
||||||
equip = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM;
|
type = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!clif_skill_nodamage(src,bl,skillid,skilllv,
|
||||||
strip_fix = sstatus->dex - tstatus->dex;
|
skill_strip_equip(bl, type, i, skilllv, skill_get_time(skillid,skilllv)))
|
||||||
if(strip_fix < 0)
|
&& sd)
|
||||||
strip_fix=0;
|
clif_skill_fail(sd,skillid,0,0); //Nothing stripped.
|
||||||
if (rand()%100 >= 5+2*skilllv+strip_fix/5)
|
|
||||||
{
|
|
||||||
if (sd)
|
|
||||||
clif_skill_fail(sd,skillid,0,0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (dstsd) {
|
|
||||||
for (i=0;i<EQI_MAX;i++) {
|
|
||||||
if (dstsd->equip_index[i]<0 || !dstsd->inventory_data[dstsd->equip_index[i]])
|
|
||||||
continue;
|
|
||||||
switch (i) {
|
|
||||||
case EQI_HAND_L: //Shield / left-hand weapon
|
|
||||||
if(dstsd->inventory_data[dstsd->equip_index[i]]->type == IT_ARMOR)
|
|
||||||
{ //Shield
|
|
||||||
if (equip&EQP_SHIELD &&
|
|
||||||
!(dstsd->unstripable_equip&EQP_SHIELD) &&
|
|
||||||
!(tsc && tsc->data[SC_CP_SHIELD].timer != -1)
|
|
||||||
){
|
|
||||||
sclist[1] = SC_STRIPSHIELD; // Okay, we found a shield to strip - It is really a shield, not a two-handed weapon or a left-hand weapon
|
|
||||||
pc_unequipitem(dstsd,dstsd->equip_index[i],3);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//Continue to weapon
|
|
||||||
case EQI_HAND_R:
|
|
||||||
if (equip&EQP_WEAPON &&
|
|
||||||
!(dstsd->unstripable_equip&EQP_WEAPON) &&
|
|
||||||
!(tsc && tsc->data[SC_CP_WEAPON].timer != -1)
|
|
||||||
) {
|
|
||||||
sclist[0] = SC_STRIPWEAPON; // Okay, we found a weapon to strip - It can be a right-hand, left-hand or two-handed weapon
|
|
||||||
pc_unequipitem(dstsd,dstsd->equip_index[i],3);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EQI_ARMOR: //Armor
|
|
||||||
if (equip &EQP_ARMOR &&
|
|
||||||
!(dstsd->unstripable_equip &EQP_ARMOR) &&
|
|
||||||
!(tsc && tsc->data[SC_CP_ARMOR].timer != -1)
|
|
||||||
) {
|
|
||||||
sclist[2] = SC_STRIPARMOR; // Okay, we found an armor to strip
|
|
||||||
pc_unequipitem(dstsd,dstsd->equip_index[i],3);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EQI_HEAD_TOP: //Helm
|
|
||||||
if (equip &EQP_HELM &&
|
|
||||||
!(dstsd->unstripable_equip &EQP_HELM) &&
|
|
||||||
!(tsc && tsc->data[SC_CP_HELM].timer != -1)
|
|
||||||
) {
|
|
||||||
sclist[3] = SC_STRIPHELM; // Okay, we found a helm to strip
|
|
||||||
pc_unequipitem(dstsd,dstsd->equip_index[i],3);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!(tstatus->mode&MD_BOSS)) {
|
|
||||||
if (equip&EQP_WEAPON && !(tsc && tsc->data[SC_CP_WEAPON].timer != -1))
|
|
||||||
sclist[0] = SC_STRIPWEAPON;
|
|
||||||
if (equip&EQP_SHIELD && !(tsc && tsc->data[SC_CP_SHIELD].timer != -1))
|
|
||||||
sclist[1] = SC_STRIPSHIELD;
|
|
||||||
if (equip&EQP_ARMOR && !(tsc && tsc->data[SC_CP_ARMOR].timer != -1))
|
|
||||||
sclist[2] = SC_STRIPARMOR;
|
|
||||||
if (equip&EQP_HELM && !(tsc && tsc->data[SC_CP_HELM].timer != -1))
|
|
||||||
sclist[3] = SC_STRIPHELM;
|
|
||||||
}
|
|
||||||
equip = 0; //Reuse equip to hold how many stats are invoked.
|
|
||||||
for (i=0;i<4;i++) {
|
|
||||||
if (sclist[i]) // Start the SC only if an equipment was stripped from this location
|
|
||||||
equip+=sc_start(bl,sclist[i],100,skilllv,skill_get_time(skillid,skilllv)+strip_fix/2);
|
|
||||||
}
|
|
||||||
if (equip)
|
|
||||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
|
||||||
else if (sd) //Nothing stripped.
|
|
||||||
clif_skill_fail(sd,skillid,0,0);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* PotionPitcher */
|
/* PotionPitcher */
|
||||||
case AM_BERSERKPITCHER:
|
case AM_BERSERKPITCHER:
|
||||||
|
@ -194,6 +194,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
|
|||||||
int skill_counter_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick);
|
int skill_counter_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick);
|
||||||
int skill_blown( struct block_list *src, struct block_list *target,int count);
|
int skill_blown( struct block_list *src, struct block_list *target,int count);
|
||||||
int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag);
|
int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag);
|
||||||
|
int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time);
|
||||||
// ƒ†ƒjƒbƒgƒXƒLƒ‹
|
// ƒ†ƒjƒbƒgƒXƒLƒ‹
|
||||||
struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag);
|
struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag);
|
||||||
struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
|
struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
|
||||||
|
@ -1106,8 +1106,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
|
|||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
//Check for chase-walk/hiding/cloaking opponents.
|
//Check for chase-walk/hiding/cloaking opponents.
|
||||||
if (tsc && tsc->option&hide_flag && !(status->mode&MD_BOSS) &&
|
if (tsc && tsc->option&hide_flag && !(status->mode&(MD_BOSS|MD_DETECTOR)))
|
||||||
!(status->mode&MD_DETECTOR))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -1136,19 +1135,17 @@ int status_check_visibility(struct block_list *src, struct block_list *target)
|
|||||||
switch (target->type)
|
switch (target->type)
|
||||||
{ //Check for chase-walk/hiding/cloaking opponents.
|
{ //Check for chase-walk/hiding/cloaking opponents.
|
||||||
case BL_PC:
|
case BL_PC:
|
||||||
{
|
if(tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) &&
|
||||||
if(tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) &&
|
!(status->mode&MD_BOSS) &&
|
||||||
!(status->mode&MD_BOSS) &&
|
(
|
||||||
(
|
((TBL_PC*)target)->special_state.perfect_hiding ||
|
||||||
((TBL_PC*)target)->special_state.perfect_hiding ||
|
!(status->mode&MD_DETECTOR)
|
||||||
!(status->mode&MD_DETECTOR)
|
))
|
||||||
))
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) &&
|
if (tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) &&
|
||||||
!(status->mode&MD_BOSS) && !(status->mode&MD_DETECTOR))
|
!(status->mode&(MD_BOSS|MD_DETECTOR)))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4646,6 +4643,10 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
|
|||||||
case SC_COMA:
|
case SC_COMA:
|
||||||
case SC_GRAVITATION:
|
case SC_GRAVITATION:
|
||||||
case SC_SUITON:
|
case SC_SUITON:
|
||||||
|
case SC_STRIPWEAPON:
|
||||||
|
case SC_STRIPSHIELD:
|
||||||
|
case SC_STRIPARMOR:
|
||||||
|
case SC_STRIPHELM:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4927,19 +4928,58 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SC_STRIPWEAPON:
|
case SC_STRIPWEAPON:
|
||||||
if (bl->type != BL_PC) //Watk reduction
|
if (sd) {
|
||||||
|
int i;
|
||||||
|
if(sd->unstripable_equip&EQP_WEAPON)
|
||||||
|
return 0;
|
||||||
|
i = sd->equip_index[EQI_HAND_L];
|
||||||
|
if (i>=0 && sd->inventory_data[i] &&
|
||||||
|
sd->inventory_data[i]->type == IT_WEAPON)
|
||||||
|
pc_unequipitem(sd,i,3); //L-hand weapon
|
||||||
|
|
||||||
|
i = sd->equip_index[EQI_HAND_R];
|
||||||
|
if (i<0 || !sd->inventory_data[i] ||
|
||||||
|
sd->inventory_data[i]->type != IT_WEAPON)
|
||||||
|
return 0;
|
||||||
|
pc_unequipitem(sd,i,3);
|
||||||
|
} else //Watk reduction
|
||||||
val2 = 5*val1;
|
val2 = 5*val1;
|
||||||
break;
|
break;
|
||||||
case SC_STRIPSHIELD:
|
case SC_STRIPSHIELD:
|
||||||
if (bl->type != BL_PC) //Def reduction
|
if (sd) {
|
||||||
|
int i;
|
||||||
|
if(sd->unstripable_equip&EQP_SHIELD)
|
||||||
|
return 0;
|
||||||
|
i = sd->equip_index[EQI_HAND_L];
|
||||||
|
if (i<0 || !sd->inventory_data[i] ||
|
||||||
|
sd->inventory_data[i]->type != IT_ARMOR)
|
||||||
|
return 0;
|
||||||
|
pc_unequipitem(sd,i,3);
|
||||||
|
} else //Def reduction
|
||||||
val2 = 3*val1;
|
val2 = 3*val1;
|
||||||
break;
|
break;
|
||||||
case SC_STRIPARMOR:
|
case SC_STRIPARMOR:
|
||||||
if (bl->type != BL_PC) //Vit reduction
|
if (sd) {
|
||||||
|
int i;
|
||||||
|
if(sd->unstripable_equip&EQP_ARMOR)
|
||||||
|
return 0;
|
||||||
|
i = sd->equip_index[EQI_ARMOR];
|
||||||
|
if (i<0 || !sd->inventory_data[i])
|
||||||
|
return 0;
|
||||||
|
pc_unequipitem(sd,i,3);
|
||||||
|
} else //Vit reduction
|
||||||
val2 = 8*val1;
|
val2 = 8*val1;
|
||||||
break;
|
break;
|
||||||
case SC_STRIPHELM:
|
case SC_STRIPHELM:
|
||||||
if (bl->type != BL_PC) //Int reduction
|
if (sd) {
|
||||||
|
int i;
|
||||||
|
if(sd->unstripable_equip&EQP_HELM)
|
||||||
|
return 0;
|
||||||
|
i = sd->equip_index[EQI_HEAD_TOP];
|
||||||
|
if (i<0 || !sd->inventory_data[i])
|
||||||
|
return 0;
|
||||||
|
pc_unequipitem(sd,i,3);
|
||||||
|
} else //Int reduction
|
||||||
val2 = 8*val1;
|
val2 = 8*val1;
|
||||||
break;
|
break;
|
||||||
case SC_AUTOSPELL:
|
case SC_AUTOSPELL:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user