Update /new.
This commit is contained in:
@@ -1180,7 +1180,25 @@ TapsAndHolds=TapsAndHolds
|
||||
Voltage=Voltage
|
||||
MinMidiNote=MinMidiNote
|
||||
MaxMidiNote=MaxMidiNote
|
||||
|
||||
Lifts=Lifts
|
||||
Fakes=Fakes
|
||||
[RadarCategoryShort]
|
||||
Air=A
|
||||
Chaos=C
|
||||
Freeze=F
|
||||
Hands=Hands
|
||||
Holds=Holds
|
||||
Jumps=Jumps
|
||||
Mines=Mines
|
||||
Rolls=Rolls
|
||||
Stream=S
|
||||
Taps=Taps
|
||||
TapsAndHolds=Taps
|
||||
Voltage=V
|
||||
MinMidiNote=Min
|
||||
MaxMidiNote=Max
|
||||
Lifts=Lifts
|
||||
Fakes=Fakes
|
||||
[RageInput]
|
||||
No input devices were loaded.=No input devices were loaded.
|
||||
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
[Global]
|
||||
FallbackTheme=default
|
||||
|
||||
# Now you can edit or add things. ##############################################
|
||||
# Now you can edit or add things. ##############################################
|
||||
[ScreenEdit]
|
||||
EditModifiers="midi-note"
|
||||
+11
-9
@@ -2,8 +2,12 @@ local t = LoadFallbackB();
|
||||
--
|
||||
t[#t+1] = StandardDecorationFromFileOptional("BannerFrame","BannerFrame");
|
||||
t[#t+1] = StandardDecorationFromFileOptional("BPMDisplay","BPMDisplay");
|
||||
t[#t+1] = StandardDecorationFromFileOptional("TimeDisplay","TimeDisplay");
|
||||
t[#t+1] = StandardDecorationFromFileOptional("StageDisplay","StageDisplay");
|
||||
-- StepsDisplay
|
||||
t[#t+1] = StandardDecorationFromFileOptional("SortDisplay","SortDisplay");
|
||||
t[#t+1] = StandardDecorationFromFileOptional("DifficultyList","DifficultyList");
|
||||
|
||||
-- StepsDisplay creator
|
||||
local function CreateStepsDisplay( _pn )
|
||||
local function set(self, _pn)
|
||||
self:SetFromGameState( _pn);
|
||||
@@ -23,13 +27,6 @@ local function CreateStepsDisplay( _pn )
|
||||
|
||||
return t;
|
||||
end
|
||||
-- Create Background For Each Player
|
||||
--[[ for pn in ivalues(PlayerNumber) do
|
||||
local MetricsName = "PlayerFrame" .. PlayerNumberToString(pn)
|
||||
t[#t+1] = LoadActor(THEME:GetPathG(Var "LoadingScreen","PlayerFrame")) .. {
|
||||
InitCommand=function(self) self:player(pn); self:name(MetricsName); ActorUtil.LoadAllCommandsAndSetXY(self,Var "LoadingScreen"); end;
|
||||
};
|
||||
end ]]
|
||||
-- Create StepsDisplay for each player
|
||||
for pn in ivalues(PlayerNumber) do
|
||||
local MetricsName = "StepsDisplay" .. PlayerNumberToString(pn);
|
||||
@@ -37,5 +34,10 @@ for pn in ivalues(PlayerNumber) do
|
||||
InitCommand=function(self) self:player(pn); self:name(MetricsName); ActorUtil.LoadAllCommandsAndSetXY(self,Var "LoadingScreen"); end;
|
||||
};
|
||||
end
|
||||
|
||||
-- Create PaneDisplay for each player
|
||||
t[#t+1] = StandardDecorationFromFileOptional("PaneDisplay","PaneDisplay");
|
||||
--[[ for pn in ivalues(PlayerNumber) do
|
||||
local MetricsName = "PaneDisplay" .. PlayerNumberToString(pn);
|
||||
t[#t+1] = StandardDecorationFromFileOptional(MetricsName,"PaneDisplay",PlayerNumber);
|
||||
end ]]
|
||||
return t;
|
||||
@@ -41,7 +41,7 @@ return Def.ActorFrame {
|
||||
-- BPM Multiple Warning
|
||||
Def.Quad {
|
||||
Name="BPMFlag";
|
||||
InitCommand=cmd(x,-32;y,4;basezoomx,24;basezoomy,4;fadeleft,0.2;faderight,0.2;diffuse,ThemeColor.Primary;thump,1;effectclock,'beatnooffset');
|
||||
InitCommand=cmd(x,32;y,-8;basezoomx,24;basezoomy,4;fadeleft,0.2;faderight,0.2;diffuse,ThemeColor.Primary;thump,1;effectclock,'beatnooffset');
|
||||
SingleBPMCommand=cmd(finishtweening;decelerate,0.1;zoom,0;zoomx,8;diffusealpha,0);
|
||||
MultipleBPMCommand=cmd(finishtweening;smooth,0.05;zoom,1;diffusealpha,1;);
|
||||
};
|
||||
@@ -56,7 +56,7 @@ return Def.ActorFrame {
|
||||
Name="BPMText";
|
||||
File=THEME:GetPathF("Common","Normal");
|
||||
InitCommand=cmd(Load,"RollingNumbersBPMDisplay");
|
||||
OnCommand=cmd(horizalign,left;x,-16);
|
||||
OnCommand=cmd(horizalign,left;x,-46;y,6;zoom,0.75;maxwidth,92/0.75;);
|
||||
BeginCommand=cmd(playcommand,"Set");
|
||||
CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
|
||||
SetCommand=function(self)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
return Def.StepsDisplayList {
|
||||
Name="StepsDisplayListRow";
|
||||
CursorP1 = Def.ActorFrame {};
|
||||
CursorP2 = Def.ActorFrame {};
|
||||
CursorP1Frame = Def.Actor {};
|
||||
CursorP2Frame = Def.Actor {};
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
local t = Def.ActorFrame {};
|
||||
-- Background
|
||||
t[#t+1] = Def.ActorFrame { Name="Background";
|
||||
Def.Quad {
|
||||
InitCommand=cmd(zoomto,320+8,96;diffuse,ThemeColor.Secondary);
|
||||
};
|
||||
};
|
||||
-- Radar Text
|
||||
local function RadarLabel( rc )
|
||||
local t = Def.ActorFrame {};
|
||||
--
|
||||
t[#t+1] = LoadFont("Common Normal") .. {
|
||||
Text=string.upper(THEME:GetString("RadarCategoryShort",ToEnumShortString(rc)));
|
||||
InitCommand=cmd(shadowlength,1;zoom,0.675;horizalign,right);
|
||||
};
|
||||
--
|
||||
return t;
|
||||
end;
|
||||
--
|
||||
local function RadarItem( pn, rc )
|
||||
local t = Def.ActorFrame {};
|
||||
--
|
||||
local function GetRadarValue( _rc, _pn )
|
||||
if GAMESTATE:GetCurrentSteps( _pn ) then
|
||||
local Steps = GAMESTATE:GetCurrentSteps( _pn );
|
||||
local RadarValues = Steps:GetRadarValues( _pn );
|
||||
local ThisValue = RadarValues:GetValue( _rc );
|
||||
--
|
||||
return tonumber(ThisValue);
|
||||
else
|
||||
return 0;
|
||||
end;
|
||||
end;
|
||||
--
|
||||
t[#t+1] = LoadFont("Common Normal") .. {
|
||||
Text=string.format("%04i",GetRadarValue(rc,pn));
|
||||
InitCommand=cmd(shadowlength,1;x,128;zoom,0.675;diffuse,PlayerColor(pn);playcommand,"Set");
|
||||
SetCommand=function(self,params)
|
||||
if params.Player == pn then
|
||||
self:settextf("%04i",GetRadarValue(rc,pn));
|
||||
end;
|
||||
end;
|
||||
};
|
||||
--
|
||||
t.CurrentSongChangedMessageCommand=function(self) self:playcommand("Set"); end;
|
||||
t.CurrentCourseChangedMessageCommand=function(self) self:playcommand("Set"); end;
|
||||
t.CurrentTrailP1ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_1}); end;
|
||||
t.CurrentTrailP2ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_2}); end;
|
||||
t.CurrentStepsP1ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_1}); end;
|
||||
t.CurrentStepsP2ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_2}); end;
|
||||
--
|
||||
return t;
|
||||
end;
|
||||
--
|
||||
local function RadarPercent( pn, rc )
|
||||
local t = Def.ActorFrame {};
|
||||
--
|
||||
local function GetRadarValue( _rc, _pn )
|
||||
if GAMESTATE:GetCurrentSteps( _pn ) then
|
||||
local Steps = GAMESTATE:GetCurrentSteps( _pn );
|
||||
local RadarValues = Steps:GetRadarValues( _pn );
|
||||
local ThisValue = RadarValues:GetValue( _rc );
|
||||
--
|
||||
return tonumber(ThisValue);
|
||||
else
|
||||
return 0;
|
||||
end;
|
||||
end;
|
||||
--
|
||||
t[#t+1] = LoadFont("Common Normal") .. {
|
||||
Text=string.format("%03i%%",math.floor(GetRadarValue(rc,pn)*100));
|
||||
InitCommand=cmd(shadowlength,1;x,128;zoom,0.675;diffuse,PlayerColor(pn);playcommand,"Set");
|
||||
SetCommand=function(self,params)
|
||||
if params.Player == pn then
|
||||
self:settextf("%03i%%",math.floor(GetRadarValue(rc,pn)*100));
|
||||
end;
|
||||
end;
|
||||
};
|
||||
--
|
||||
t.CurrentSongChangedMessageCommand=function(self) self:playcommand("Set"); end;
|
||||
t.CurrentCourseChangedMessageCommand=function(self) self:playcommand("Set"); end;
|
||||
t.CurrentTrailP1ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_1}); end;
|
||||
t.CurrentTrailP2ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_2}); end;
|
||||
t.CurrentStepsP1ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_1}); end;
|
||||
t.CurrentStepsP2ChangedMessageCommand=function(self) self:playcommand("Set",{ Player = PLAYER_2}); end;
|
||||
--
|
||||
return t;
|
||||
end;
|
||||
--
|
||||
for index,rc in ipairs(RadarCategory) do
|
||||
if index > 5 then
|
||||
local VisualIndex = index-6
|
||||
local VertOffset = ( VisualIndex % 4 ) * 16;
|
||||
local HorizOffset = math.floor( (VisualIndex)/4 ) * 156;
|
||||
t[#t+1] = Def.ActorFrame {
|
||||
Name="RadarCategoryRow" .. tonumber(index-5);
|
||||
InitCommand=cmd(x,-96+HorizOffset;y,-10+VertOffset);
|
||||
--
|
||||
RadarLabel(rc);
|
||||
RadarItem(PLAYER_1, rc) .. { InitCommand=cmd(x,-96-8); };
|
||||
RadarItem(PLAYER_2, rc) .. { InitCommand=cmd(x,-64+4); };
|
||||
};
|
||||
end
|
||||
end;
|
||||
--
|
||||
for index,rc in ipairs(RadarCategory) do
|
||||
if index < 6 then
|
||||
local HorizOffset = (index-1) * 64;
|
||||
t[#t+1] = Def.ActorFrame {
|
||||
Name="RadarCategoryRow" .. tonumber(index-5);
|
||||
InitCommand=cmd(x,-148+HorizOffset;y,-33);
|
||||
--
|
||||
RadarLabel(rc);
|
||||
RadarPercent(PLAYER_1, rc) .. { InitCommand=cmd(x,-104;y,-7); };
|
||||
RadarPercent(PLAYER_2, rc) .. { InitCommand=cmd(x,-104;y,7); };
|
||||
};
|
||||
end
|
||||
end;
|
||||
--
|
||||
--[[ for index,rc in ipairs(RadarCategory) do
|
||||
if index > 5 then
|
||||
t[#t+1] = LoadFont("Common Normal") .. { Text=ToEnumShortString(rc); InitCommand=cmd(zoom,0.5;shadowlength,1;y,(index-5)*10); };
|
||||
end
|
||||
end; ]]
|
||||
return t
|
||||
@@ -1,17 +0,0 @@
|
||||
return Def.ActorFrame {
|
||||
CurrentSongChangedMessageCommand=function(self)
|
||||
self:aux(0);
|
||||
self:playcommand( GAMESTATE:GetCurrentSong():GetTimingData():HasBPMChanges() and "MultipleBPM" or "SingleBPM" );
|
||||
end;
|
||||
-- BPM Background
|
||||
Def.Quad {
|
||||
Name="BPMBackground";
|
||||
InitCommand=cmd(zoomto,96,32;diffuse,ThemeColor.Secondary;shadowlength,2;shadowcolor,Color.Alpha(ColorDarkTone(ThemeColor.Primary),0.95));
|
||||
};
|
||||
-- BPM Label
|
||||
LoadFont("Common Normal") .. {
|
||||
Name="BPMLabel";
|
||||
Text="Time";
|
||||
InitCommand=cmd(x,-32;y,-8;zoom,0.5);
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
return Def.ActorFrame {
|
||||
-- Time Background
|
||||
Def.Quad {
|
||||
Name="SortBackground";
|
||||
InitCommand=cmd(zoomto,96,32;diffuse,ThemeColor.Secondary;shadowlength,2;shadowcolor,Color.Alpha(ColorDarkTone(ThemeColor.Primary),0.95));
|
||||
};
|
||||
-- Time Label
|
||||
LoadFont("Common Normal") .. {
|
||||
Name="SortLabel";
|
||||
Text="SORT";
|
||||
InitCommand=cmd(x,-32;y,-8;zoom,0.5);
|
||||
};
|
||||
-- Time Text
|
||||
LoadFont("Common Normal") .. {
|
||||
Name="SortText";
|
||||
OnCommand=cmd(horizalign,left;x,-46;y,6;zoom,0.75;maxwidth,92/0.75;);
|
||||
BeginCommand=cmd(playcommand,"Set");
|
||||
SortOrderChangedMessageCommand=cmd(playcommand,"Set";);
|
||||
SetCommand=function(self)
|
||||
local s = SortOrderToLocalizedString( GAMESTATE:GetSortOrder() );
|
||||
-- reset numbers
|
||||
self:settext(s);
|
||||
end;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
return Def.ActorFrame {
|
||||
-- Time Background
|
||||
Def.Quad {
|
||||
Name="TimeBackground";
|
||||
InitCommand=cmd(zoomto,96,32;diffuse,ThemeColor.Secondary;shadowlength,2;shadowcolor,Color.Alpha(ColorDarkTone(ThemeColor.Primary),0.95));
|
||||
};
|
||||
-- Time Label
|
||||
LoadFont("Common Normal") .. {
|
||||
Name="TimeLabel";
|
||||
Text="TIME";
|
||||
InitCommand=cmd(x,-32;y,-8;zoom,0.5);
|
||||
};
|
||||
-- Time Text
|
||||
LoadFont("Common Normal") .. {
|
||||
Name="BPMText";
|
||||
OnCommand=cmd(horizalign,left;x,-46;y,6;zoom,0.75;maxwidth,92/0.75;);
|
||||
BeginCommand=cmd(playcommand,"Set");
|
||||
CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
|
||||
SetCommand=function(self)
|
||||
Song = GAMESTATE:GetCurrentSong();
|
||||
Time = Song:GetStepsSeconds() or 0;
|
||||
Minutes = math.floor( Time / 60 );
|
||||
Seconds = tonumber(Time) - tonumber(Minutes*60);
|
||||
-- reset numbers
|
||||
self:settextf("%02i:%02i",Minutes,Seconds);
|
||||
end;
|
||||
};
|
||||
};
|
||||
@@ -2,11 +2,11 @@ local t = Def.ActorFrame {};
|
||||
local function UpdateTriangleFrame(self)
|
||||
local curBPS = GAMESTATE:GetSongBPS() and GAMESTATE:GetSongBPS() or 1;
|
||||
local c = self:GetChildren();
|
||||
local auxRate = 6;
|
||||
local auxRate = 3;
|
||||
--
|
||||
c.TriangleFrame:aux( math.mod( c.TriangleFrame:getaux() + ( curBPS * auxRate ), 360) );
|
||||
c.TriangleFrame:rotationz( c.TriangleFrame:GetRotationZ() + ( curBPS * 1.5 ) );
|
||||
c.TriangleFrame:zoom( 1.125 - ((c.TriangleFrame:getaux() / 360) * 0.5) );
|
||||
c.TriangleFrame:rotationz( c.TriangleFrame:GetRotationZ() + ( curBPS * 0.75 ) );
|
||||
c.TriangleFrame:zoom( 1.125 - ((c.TriangleFrame:getaux() / 360) * 0.35) );
|
||||
-- c.TriangleFrame:x( math.cos( math.rad(c.TriangleFrame:getaux()) ) * 8 );
|
||||
-- c.TriangleFrame:y(math.sin( math.rad(c.TriangleFrame:getaux()) ) * 8);
|
||||
end;
|
||||
|
||||
@@ -10,7 +10,7 @@ local t = Def.ActorFrame {};
|
||||
t[#t+1] = Def.ActorFrame {
|
||||
LoadActor(THEME:GetPathB("_frame","3x3"),"rounded black",160,20);
|
||||
LoadFont("Common Normal") .. {
|
||||
Text=curStage .. " (" .. curStageIndex .. ")";
|
||||
Text=StageToLocalizedString( curStage ) .. " Stage (" .. curStageIndex .. ")";
|
||||
InitCommand=cmd(zoom,0.75;y,-2;shadowlength,1;
|
||||
diffuse,StageToColor(curStage);
|
||||
diffusetopedge,ColorLightTone(StageToColor(curStage));
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
return Def.Quad {};
|
||||
+95
-3
@@ -51,6 +51,24 @@ BPMDisplayY=SCREEN_CENTER_Y-128-40
|
||||
BPMDisplayOnCommand=draworder,115
|
||||
BPMDisplayOffCommand=
|
||||
#
|
||||
ShowTimeDisplay=true
|
||||
TimeDisplayX=SCREEN_CENTER_X-256+96+4
|
||||
TimeDisplayY=SCREEN_CENTER_Y-128-40
|
||||
TimeDisplayOnCommand=draworder,115;
|
||||
TimeDisplayOffCommand=
|
||||
#
|
||||
ShowSortDisplay=true
|
||||
SortDisplayX=SCREEN_CENTER_X-256+96+96+8
|
||||
SortDisplayY=SCREEN_CENTER_Y-128-40
|
||||
SortDisplayOnCommand=draworder,115;
|
||||
SortDisplayOffCommand=
|
||||
#
|
||||
ShowDifficultyList=true
|
||||
DifficultyListX=SCREEN_CENTER_X-128-64-64-32;
|
||||
DifficultyListY=SCREEN_CENTER_Y-96-32-4;
|
||||
DifficultyListOnCommand=draworder,115;
|
||||
DifficultyListOffCommand=
|
||||
#
|
||||
StepsDisplayP1X=SCREEN_CENTER_X-160
|
||||
StepsDisplayP1Y=SCREEN_CENTER_Y+184
|
||||
StepsDisplayP1OnCommand=draworder,155;
|
||||
@@ -61,6 +79,24 @@ StepsDisplayP2Y=SCREEN_CENTER_Y+184
|
||||
StepsDisplayP2OnCommand=draworder,155;
|
||||
StepsDisplayP2OffCommand=
|
||||
#
|
||||
ShowPaneDisplay=true
|
||||
PaneDisplayX=SCREEN_CENTER_X-128-32+4
|
||||
PaneDisplayY=SCREEN_CENTER_Y
|
||||
PaneDisplayOnCommand=
|
||||
PaneDisplayOffCommand=
|
||||
#
|
||||
ShowPaneDisplayP1=true
|
||||
PaneDisplayP1X=
|
||||
PaneDisplayP1Y=
|
||||
PaneDisplayP1OnCommand=
|
||||
PaneDisplayP1OffCommand=
|
||||
#
|
||||
ShowPaneDisplayP2=true
|
||||
PaneDisplayP2X=
|
||||
PaneDisplayP2Y=
|
||||
PaneDisplayP2OnCommand=
|
||||
PaneDisplayP2OffCommand=
|
||||
#
|
||||
PlayerFrameP1X=SCREEN_CENTER_X-160
|
||||
PlayerFrameP1Y=SCREEN_CENTER_Y+184
|
||||
PlayerFrameP1OnCommand=draworder,155;diffuse,PlayerColor(PLAYER_1);
|
||||
@@ -75,8 +111,8 @@ TextFormat="%04.0f"
|
||||
ApproachSeconds=0.25
|
||||
Commify=false
|
||||
LeadingZeroMultiplyColor=color("#777777FF")
|
||||
[RollingNumbersSongTime]
|
||||
TextFormat="%02i:02i"
|
||||
[RollingNumbersTimeDisplay]
|
||||
TextFormat="%02f:02f"
|
||||
ApproachSeconds=0.25
|
||||
Commify=false
|
||||
LeadingZeroMultiplyColor=color("#777777FF")
|
||||
@@ -205,7 +241,63 @@ ShowStepsType=false
|
||||
StepsTypeX=-20-32
|
||||
StepsTypeY=7
|
||||
StepsTypeOnCommand=zoom,0.45
|
||||
|
||||
[DifficultyList]
|
||||
ItemsSpacingY=16
|
||||
NumShownItems=5
|
||||
[StepsDisplayListRow]
|
||||
# TODO: Make this use DifficultyList?
|
||||
CapitalizeDifficultyNames=false
|
||||
NumShownItems=5
|
||||
ItemsSpacingY=16
|
||||
MoveCommand=
|
||||
FrameX=
|
||||
FrameY=
|
||||
FrameOnCommand=zoomto,60,14;
|
||||
FrameOffCommand=
|
||||
FrameSetCommand=%function(self,param) \
|
||||
if param.CustomDifficulty then \
|
||||
self:diffuse(ColorMidTone( CustomDifficultyToColor(param.CustomDifficulty) )); \
|
||||
else \
|
||||
self:diffuse(color('1,1,1,1')); \
|
||||
end; \
|
||||
end;
|
||||
#
|
||||
NumTicks=10
|
||||
MaxTicks=10
|
||||
#
|
||||
ShowMeter=true
|
||||
MeterX=0
|
||||
MeterOnCommand=zoom,0.75;
|
||||
MeterSetCommand=%function(self,param) \
|
||||
if param.CustomDifficulty then \
|
||||
self:diffuse(CustomDifficultyToColor(param.CustomDifficulty)); \
|
||||
self:shadowcolor(CustomDifficultyToDarkColor(param.CustomDifficulty)); \
|
||||
end; \
|
||||
end;
|
||||
#
|
||||
ShowDescription=false
|
||||
DescriptionX=0
|
||||
DescriptionOnCommand=0
|
||||
DescriptionSetCommand=%function(self,param) \
|
||||
if self:GetText() == "" then \
|
||||
self:settext("Edit"); \
|
||||
end; \
|
||||
if param.CustomDifficulty then \
|
||||
self:diffuse(CustomDifficultyToColor(param.CustomDifficulty)); \
|
||||
self:shadowcolor(CustomDifficultyToDarkColor(param.CustomDifficulty)); \
|
||||
end; \
|
||||
end;
|
||||
#
|
||||
ShowAutogen=false
|
||||
AutogenX=0
|
||||
AutogenY=0
|
||||
AutogenOnCommand=
|
||||
#
|
||||
ShowStepsType=false
|
||||
StepsTypeX=0
|
||||
StepsTypeY=0
|
||||
StepsTypeOnCommand=
|
||||
StepsTypeSetCommand=
|
||||
[ScreenGameplay]
|
||||
LifeP1OnCommand=draworder,105
|
||||
LifeP2OnCommand=draworder,105
|
||||
|
||||
Reference in New Issue
Block a user