动画相对移动模式
This commit is contained in:
parent
a1ffc89164
commit
c5600f78d1
@ -2582,33 +2582,33 @@ return code;
|
|||||||
*/;
|
*/;
|
||||||
|
|
||||||
animatemove_s
|
animatemove_s
|
||||||
: '移动正在播放的帧动画/特效 编号'IntString'目标像素x'PosString'y'PosString'移动时长'PosString'移动模式'MoveMode2_List? '(仅可对有编号的非跟随勇士帧动画/特效使用)'
|
: '移动正在播放的帧动画/特效 编号'IntString'目标像素x'PosString'y'PosString Absolute_List'移动时长'PosString'移动模式'MoveMode2_List? '(仅可对有编号的非跟随勇士帧动画/特效使用)'
|
||||||
|
|
||||||
/* animatemove_s
|
/* animatemove_s
|
||||||
tooltip : animateloop:调整正在播放的帧动画(循环)
|
tooltip : animateloop:调整正在播放的帧动画(循环)
|
||||||
helpUrl : /_docs/#/instruction
|
helpUrl : /_docs/#/instruction
|
||||||
default : [0,0,0,1000,'']
|
default : [0,0,0,false,1000,'']
|
||||||
previewBlock : true
|
previewBlock : true
|
||||||
colour : this.imageColor
|
colour : this.imageColor
|
||||||
IntString_0 = IntString_0 ? (', "id": '+IntString_0+'') : ''
|
IntString_0 = IntString_0 ? (', "id": '+IntString_0+'') : ''
|
||||||
MoveMode2_List_0=MoveMode2_List_0?(', "style": "'+MoveMode2_List_0+'"') : ''
|
MoveMode2_List_0=MoveMode2_List_0?(', "style": "'+MoveMode2_List_0+'"') : ''
|
||||||
var code = '{"type": "animatemove"'+IntString_0+',"px":'+PosString_0+',"py":'+PosString_1+',"time":'+PosString_2+MoveMode2_List_0+'},\n';
|
var code = '{"type": "animatemove"'+IntString_0+',"px":'+PosString_0+',"py":'+PosString_1+',"relative":'+Absolute_List_0+',"time":'+PosString_2+MoveMode2_List_0+'},\n';
|
||||||
return code;
|
return code;
|
||||||
*/;
|
*/;
|
||||||
|
|
||||||
|
|
||||||
moveAnimate_s
|
moveAnimate_s
|
||||||
: '移动正在播放的帧动画/特效 编号'IntString'目标像素x'PosString'y'PosString'移动时长'PosString'移动模式'MoveMode2_List? '(仅可对有编号的非跟随勇士动画使用)'
|
: '移动正在播放的帧动画/特效 编号'IntString'目标像素x'PosString'y'PosString Absolute_List'移动时长'PosString'移动模式'MoveMode2_List? '(仅可对有编号的非跟随勇士动画使用)'
|
||||||
|
|
||||||
/* moveAnimate_s
|
/* moveAnimate_s
|
||||||
tooltip : animateloop:调整正在播放的帧动画(循环)
|
tooltip : animateloop:调整正在播放的帧动画(循环)
|
||||||
helpUrl : /_docs/#/instruction
|
helpUrl : /_docs/#/instruction
|
||||||
default : [0,0,0,1000,'']
|
default : [0,0,0,false,1000,'']
|
||||||
previewBlock : true
|
previewBlock : true
|
||||||
colour : this.soundColor
|
colour : this.soundColor
|
||||||
IntString_0 = IntString_0 ? (', "id": '+IntString_0+'') : ''
|
IntString_0 = IntString_0 ? (', "id": '+IntString_0+'') : ''
|
||||||
MoveMode2_List_0=MoveMode2_List_0?(', "style": "'+MoveMode2_List_0+'"') : ''
|
MoveMode2_List_0=MoveMode2_List_0?(', "style": "'+MoveMode2_List_0+'"') : ''
|
||||||
var code = '{"type": "moveAnimate"'+IntString_0+',"px":'+PosString_0+',"py":'+PosString_1+',"time":'+PosString_2+MoveMode2_List_0+'},\n';
|
var code = '{"type": "moveAnimate"'+IntString_0+',"px":'+PosString_0+',"py":'+PosString_1+',"relative":'+Absolute_List_0+',"time":'+PosString_2+MoveMode2_List_0+'},\n';
|
||||||
return code;
|
return code;
|
||||||
*/;
|
*/;
|
||||||
|
|
||||||
@ -4700,6 +4700,10 @@ B_1_List
|
|||||||
: '不改变'|'设为粗体'|'取消粗体'
|
: '不改变'|'设为粗体'|'取消粗体'
|
||||||
/*B_1_List ['null','true','false']*/;
|
/*B_1_List ['null','true','false']*/;
|
||||||
|
|
||||||
|
Absolute_List
|
||||||
|
:'绝对模式'|'相对模式'
|
||||||
|
/*Absolute_List ['false','true']*/;
|
||||||
|
|
||||||
Bg_Fg_List
|
Bg_Fg_List
|
||||||
: '背景层'|'前景层'
|
: '背景层'|'前景层'
|
||||||
/*Bg_Fg_List ['bg','fg']*/;
|
/*Bg_Fg_List ['bg','fg']*/;
|
||||||
|
@ -1266,6 +1266,7 @@ MotaActionParser = function () {
|
|||||||
data.id||0,
|
data.id||0,
|
||||||
data.px||0,
|
data.px||0,
|
||||||
data.py||0,
|
data.py||0,
|
||||||
|
data.relative,
|
||||||
data.time||0,
|
data.time||0,
|
||||||
data.style||"",
|
data.style||"",
|
||||||
this.next]);
|
this.next]);
|
||||||
@ -1276,9 +1277,11 @@ MotaActionParser = function () {
|
|||||||
data.px||0,
|
data.px||0,
|
||||||
data.py||0,
|
data.py||0,
|
||||||
data.time||0,
|
data.time||0,
|
||||||
|
data.relative,
|
||||||
data.style||"",
|
data.style||"",
|
||||||
this.next]);
|
this.next]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "animatereverse":
|
case "animatereverse":
|
||||||
this.next = MotaActionBlocks["animatereverse_s"].xmlText([
|
this.next = MotaActionBlocks["animatereverse_s"].xmlText([
|
||||||
data.id||"",
|
data.id||"",
|
||||||
|
@ -89,16 +89,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
core.doAction();
|
core.doAction();
|
||||||
});
|
});
|
||||||
core.registerEvent("animatemove", function (data) {
|
core.registerEvent("animatemove", function (data) {
|
||||||
core.animatemove(data.id, data.px, data.py, data.time, data.style);
|
core.animatemove(data.id, data.px, data.py, data.relative, data.time, data.style);
|
||||||
|
|
||||||
core.doAction();
|
core.doAction();
|
||||||
});
|
});
|
||||||
core.registerEvent("moveAnimate", function (data) {
|
core.registerEvent("moveAnimate", function (data) {
|
||||||
core.maps.moveAnimate(data.id, data.px, data.py, data.time, data.style);
|
core.maps.moveAnimate(data.id, data.px, data.py, data.relative, data.time, data.style);
|
||||||
|
|
||||||
core.doAction();
|
core.doAction();
|
||||||
});
|
});
|
||||||
|
|
||||||
core.registerEvent("animateloop", function (data) {
|
core.registerEvent("animateloop", function (data) {
|
||||||
core.animateloop(data.id, data.loop);
|
core.animateloop(data.id, data.loop);
|
||||||
|
|
||||||
@ -25643,7 +25642,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
const { Transition, linear, bezier, circle, hyper, trigo, power, inverseTrigo, shake, sleep } = core.plugin.animate;
|
const { Transition, linear, bezier, circle, hyper, trigo, power, inverseTrigo, shake, sleep } = core.plugin.animate;
|
||||||
//////移动动画//////
|
//////移动动画//////
|
||||||
const tran = new Transition();
|
const tran = new Transition();
|
||||||
maps.prototype.moveAnimate = function (id, px, py, time, style) {
|
maps.prototype.moveAnimate = function (id, px, py, relative, time, style) {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
core.status.animateObjs.forEach(v => {
|
core.status.animateObjs.forEach(v => {
|
||||||
if (v.id === id) {
|
if (v.id === id) {
|
||||||
@ -25658,6 +25657,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
} else if (style === "center") {
|
} else if (style === "center") {
|
||||||
tran.mode(trigo('sin', "center"))
|
tran.mode(trigo('sin', "center"))
|
||||||
}
|
}
|
||||||
|
if (relative) { tran.relative() } else { tran.absolute() }
|
||||||
tran.time(time)
|
tran.time(time)
|
||||||
tran.value[v.id + v.name + "x"] = px
|
tran.value[v.id + v.name + "x"] = px
|
||||||
tran.value[v.id + v.name + "y"] = py
|
tran.value[v.id + v.name + "y"] = py
|
||||||
@ -25750,7 +25750,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
}
|
}
|
||||||
animate.se = animate.se || {};
|
animate.se = animate.se || {};
|
||||||
if (typeof animate.se == 'string') animate.se = { 1: animate.se };
|
if (typeof animate.se == 'string') animate.se = { 1: animate.se };
|
||||||
tran.mode(linear()).time(1)
|
tran.mode(linear()).time(1).absolute()
|
||||||
tran.value[id + name + "x"] = centerX
|
tran.value[id + name + "x"] = centerX
|
||||||
tran.value[id + name + "y"] = centerY
|
tran.value[id + name + "y"] = centerY
|
||||||
var id = setTimeout(null);
|
var id = setTimeout(null);
|
||||||
@ -25789,7 +25789,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
if (typeof animate.se == 'string') animate.se = { 1: animate.se };
|
if (typeof animate.se == 'string') animate.se = { 1: animate.se };
|
||||||
|
|
||||||
var id = id || setTimeout(null);
|
var id = id || setTimeout(null);
|
||||||
tran.mode(linear()).time(1)
|
tran.mode(linear()).time(1).absolute()
|
||||||
if (!hero) tran.value[id + name + "x"] = centerX
|
if (!hero) tran.value[id + name + "x"] = centerX
|
||||||
if (!hero) tran.value[id + name + "y"] = centerY
|
if (!hero) tran.value[id + name + "y"] = centerY
|
||||||
if (hero) core.status.animateObjs.push({
|
if (hero) core.status.animateObjs.push({
|
||||||
@ -25933,5 +25933,293 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
|||||||
core.clearMap('animate');
|
core.clearMap('animate');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"帧动画(游戏画面)": null
|
"帧动画(游戏画面)": function () {
|
||||||
|
// 在此增加新插件
|
||||||
|
// 在此增加新插件
|
||||||
|
const animate3 = document.createElement("canvas"); //画布设置
|
||||||
|
animate3.style.zIndex = 71;
|
||||||
|
animate3.id = "animate3";
|
||||||
|
animate3.classList.add("gameCanvas", "anti-aliasing");
|
||||||
|
animate3.style.display = "block";
|
||||||
|
animate3.width = 416;
|
||||||
|
animate3.height = 416;
|
||||||
|
animate3.style.width = core.__PIXELS__ * core.domStyle.scale + "px";
|
||||||
|
animate3.style.height = core.__PIXELS__ * core.domStyle.scale + "px";
|
||||||
|
main.dom.animate3 = animate3;
|
||||||
|
const anctx = animate3.getContext("2d");
|
||||||
|
|
||||||
|
main.dom.gameDraw.appendChild(animate3);
|
||||||
|
|
||||||
|
core.plugin.playing = new Set();
|
||||||
|
const { Transition, linear, bezier, circle, hyper, trigo, power, inverseTrigo, shake, sleep } = core.plugin.animate;
|
||||||
|
const tran = new Transition();
|
||||||
|
this.animatemove = function (id, px, py, relative, time, style) {
|
||||||
|
if (!id) return
|
||||||
|
core.plugin.playing.forEach(v => {
|
||||||
|
if (v.id === id) {
|
||||||
|
if (v.hero) return
|
||||||
|
if (!style) tran.mode(linear())
|
||||||
|
else if (style === "in") {
|
||||||
|
tran.mode(trigo('sin', "in"))
|
||||||
|
} else if (style === "out") {
|
||||||
|
tran.mode(trigo('sin', "out"))
|
||||||
|
} else if (style === "in-out") {
|
||||||
|
tran.mode(trigo('sin', "in-out"))
|
||||||
|
} else if (style === "center") {
|
||||||
|
tran.mode(trigo('sin', "center"))
|
||||||
|
}
|
||||||
|
if (relative) { tran.relative() } else { tran.absolute() }
|
||||||
|
tran.time(time)
|
||||||
|
tran.value[v.id + v.name + "x"] = px
|
||||||
|
tran.value[v.id + v.name + "y"] = py
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.setanimate = function (
|
||||||
|
name,
|
||||||
|
px,
|
||||||
|
py,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
allFarme,
|
||||||
|
imageList,
|
||||||
|
soundList
|
||||||
|
) {
|
||||||
|
const data = {
|
||||||
|
px: px,
|
||||||
|
py: py,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
allFarme: allFarme,
|
||||||
|
imageList: imageList,
|
||||||
|
soundList: soundList,
|
||||||
|
};
|
||||||
|
core.setFlag("animate_" + name, data);
|
||||||
|
};
|
||||||
|
this.deleteanimate = function (name) {
|
||||||
|
core.setFlag("animate_" + name);
|
||||||
|
};
|
||||||
|
let thistime = 0;
|
||||||
|
this.playanimate = function (name, id, x, y, hero, scalex, scaley, loop, reverse) {
|
||||||
|
if (!id) id = setTimeout(null)
|
||||||
|
tran.mode(linear()).time(1).absolute()
|
||||||
|
if (!hero) tran.value[id + name + "x"] = x
|
||||||
|
if (!hero) tran.value[id + name + "y"] = y
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
hero: hero,
|
||||||
|
scalex: scalex,
|
||||||
|
scaley: scaley,
|
||||||
|
start: 0,
|
||||||
|
pause: false,
|
||||||
|
loop: loop,
|
||||||
|
reverse: reverse,
|
||||||
|
pausetime: 0,
|
||||||
|
farme: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
core.plugin.playing.add(data);
|
||||||
|
return id
|
||||||
|
};
|
||||||
|
this.animateloop = function (id, loop) {
|
||||||
|
core.plugin.playing.forEach(v => {
|
||||||
|
if (!id || v.id === id) v.loop = loop
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.animatereverse = function (id, reverse) {
|
||||||
|
core.plugin.playing.forEach(v => {
|
||||||
|
if (!id || v.id === id) {
|
||||||
|
const data = flags["animate_" + v.name]
|
||||||
|
if (reverse && !v.reverse) v.start -= (data.allFarme - v.farme * 2) * (1000 / 60)
|
||||||
|
if (!reverse && v.reverse) v.start -= (v.farme * 2 - data.allFarme) * (1000 / 60)
|
||||||
|
v.reverse = reverse
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.animatepause = function (id, pause) {
|
||||||
|
core.plugin.playing.forEach(v => {
|
||||||
|
if (!id || v.id === id) v.pause = pause
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.animateclear = function (id) {
|
||||||
|
core.plugin.playing.forEach(v => {
|
||||||
|
if (!id || v.id === id) core.plugin.playing.delete(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
core.registerAnimationFrame("animateonmap", true, function (timestamp) {
|
||||||
|
let frametime = timestamp - thistime
|
||||||
|
thistime = timestamp;
|
||||||
|
|
||||||
|
|
||||||
|
core.clearMap(anctx);
|
||||||
|
core.plugin.playing.forEach((one) => {
|
||||||
|
const data = flags["animate_" + one.name];
|
||||||
|
if (!data) {
|
||||||
|
core.plugin.playing.delete(one);
|
||||||
|
} else {
|
||||||
|
if (one.start === 0) one.start = thistime
|
||||||
|
if (one.pause) one.pausetime += frametime
|
||||||
|
one.farme = Math.floor((thistime - one.start - one.pausetime) / (1000 / 60))
|
||||||
|
|
||||||
|
if (one.reverse) one.farme = data.allFarme - one.farme
|
||||||
|
if ((!one.reverse && one.farme > data.allFarme) || (one.reverse && one.farme < 0)) {
|
||||||
|
if (one.loop) {
|
||||||
|
if (one.reverse) {
|
||||||
|
one.farme = data.allFarme
|
||||||
|
one.start = thistime
|
||||||
|
one.pausetime = 0
|
||||||
|
} else {
|
||||||
|
one.start = thistime
|
||||||
|
one.farme = 0
|
||||||
|
one.pausetime = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((!one.reverse && one.farme > data.allFarme) || (one.reverse && one.farme < 0)) {
|
||||||
|
delete tran.value[one.id + one.name + "x"]
|
||||||
|
delete tran.value[one.id + one.name + "y"]
|
||||||
|
core.plugin.playing.delete(one)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data.imageList.forEach(function (image) {
|
||||||
|
if (
|
||||||
|
one.farme >= (image.beforefarme ?? 0) &&
|
||||||
|
one.farme <= (image.afterfarme ?? data.allFarme)
|
||||||
|
) {
|
||||||
|
|
||||||
|
const img = core.material.images.images?.[image.image];
|
||||||
|
if (img) {
|
||||||
|
const gla = image.globalAlpha ?? 100;
|
||||||
|
const agla = image.aglobalAlpha ?? gla,
|
||||||
|
beforefarme = image.beforefarme ?? 0;
|
||||||
|
const afterfarme = image.afterfarme ?? data.allFarme;
|
||||||
|
|
||||||
|
anctx.globalAlpha =
|
||||||
|
(gla +
|
||||||
|
((agla - gla) * (one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1)) /
|
||||||
|
100;
|
||||||
|
|
||||||
|
const cx =
|
||||||
|
(image.cx ?? 0) +
|
||||||
|
(((image.acx ?? 0) - (image.cx ?? 0)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
cy =
|
||||||
|
(image.cy ?? 0) +
|
||||||
|
(((image.acy ?? 0) - (image.cy ?? 0)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
cw =
|
||||||
|
(image.cw ?? img.width) +
|
||||||
|
(((image.acw ?? img.width) - (image.cw ?? img.width)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
ch =
|
||||||
|
(image.ch ?? img.height) +
|
||||||
|
(((image.acw ?? img.height) - (image.cw ?? img.height)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
x =
|
||||||
|
(image.x ?? 0) +
|
||||||
|
(((image.ax ?? 0) - (image.x ?? 0)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
y =
|
||||||
|
(image.y ?? 0) +
|
||||||
|
(((image.ay ?? 0) - (image.y ?? 0)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
w =
|
||||||
|
(image.w ?? img.width) +
|
||||||
|
(((image.aw ?? img.width) - (image.w ?? img.width)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
h =
|
||||||
|
(image.h ?? img.height) +
|
||||||
|
(((image.aw ?? img.height) - (image.w ?? img.height)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1),
|
||||||
|
angle =
|
||||||
|
(Math.PI *
|
||||||
|
((image.angle ?? 0) +
|
||||||
|
(((image.aangle ?? 0) - (image.angle ?? 0)) *
|
||||||
|
(one.farme - beforefarme)) /
|
||||||
|
(afterfarme - beforefarme || 1))) /
|
||||||
|
180;
|
||||||
|
|
||||||
|
if (one.hero) {
|
||||||
|
let sx, sy;
|
||||||
|
if (core.status.heroMoving < 0) {
|
||||||
|
sx = 0;
|
||||||
|
sy = 0;
|
||||||
|
} else {
|
||||||
|
sx =
|
||||||
|
core.utils.scan[core.status.hero.loc.direction].x *
|
||||||
|
4 *
|
||||||
|
core.status.heroMoving;
|
||||||
|
sy =
|
||||||
|
core.utils.scan[core.status.hero.loc.direction].y *
|
||||||
|
4 *
|
||||||
|
core.status.heroMoving;
|
||||||
|
}
|
||||||
|
const herox = core.status.hero.loc.x * 32 + 16 + sx;
|
||||||
|
const heroy = core.status.hero.loc.y * 32 + 16 + sy;
|
||||||
|
core.drawImage(
|
||||||
|
anctx,
|
||||||
|
img,
|
||||||
|
cx,
|
||||||
|
cy,
|
||||||
|
cw,
|
||||||
|
ch,
|
||||||
|
herox + (x - data.px) * one.scalex,
|
||||||
|
heroy + (y - data.py) * one.scaley,
|
||||||
|
w * one.scalex,
|
||||||
|
h * one.scaley,
|
||||||
|
angle
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
core.drawImage(
|
||||||
|
anctx,
|
||||||
|
img,
|
||||||
|
cx,
|
||||||
|
cy,
|
||||||
|
cw,
|
||||||
|
ch,
|
||||||
|
tran.value[one.id + one.name + "x"] + (x - data.px) * one.scalex,
|
||||||
|
tran.value[one.id + one.name + "y"] + (y - data.py) * one.scaley,
|
||||||
|
w * one.scalex,
|
||||||
|
h * one.scaley,
|
||||||
|
angle
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
data.soundList.forEach(function (sound) {
|
||||||
|
const lisen =
|
||||||
|
sound.sound &&
|
||||||
|
core.material.sounds[sound.sound] &&
|
||||||
|
core.musicStatus.soundStatus;
|
||||||
|
if (one.farme == sound.startfarme && lisen) {
|
||||||
|
if (sound.stopbefore) core.stopSound();
|
||||||
|
core.playSound(sound.sound);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user