308 lines
11 KiB
Text
308 lines
11 KiB
Text
// dedicated achievement browser
|
|
|
|
Class SWWMAchievementMenu : GenericMenu
|
|
{
|
|
// since this is a unique menu, we don't need a descriptor,
|
|
// so put everything in here
|
|
TextureID AchievementUnknown, SelectBox, BaseBox;
|
|
bool ShouldObscure;
|
|
SWWMStaticHandler hnd;
|
|
Array<SWWMAchievementInfo> mItems;
|
|
String mTitle;
|
|
int mSelected, mBaseY, mRows;
|
|
int ofs, maxofs; // physical scroll offset, and offset limit
|
|
int completed, incomplete, total;
|
|
Font mSmallFont, mTinyFont;
|
|
|
|
override void Init( Menu parent )
|
|
{
|
|
Super.Init(parent);
|
|
mTitle = StringTable.Localize("$SWWM_ATITLE");
|
|
mSelected = 0;
|
|
hnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler"));
|
|
if ( !hnd ) ThrowAbortException("SWWMStaticHandler not found???");
|
|
mItems.Copy(hnd.achievementinfo);
|
|
total = mItems.Size();
|
|
bool dohide = (swwm_filterachievements==2);
|
|
for ( int i=0; i<mItems.Size(); i++ )
|
|
{
|
|
String key = mItems[i].basename;
|
|
// cache state/progress
|
|
mItems[i].state = hnd.achievementstate.At(key).ToInt();
|
|
if ( mItems[i].maxval )
|
|
mItems[i].val = hnd.achievementprogress.At(key).ToInt();
|
|
// check if we need to hide it
|
|
if ( (key == "everything") && !mItems[i].state )
|
|
{
|
|
mItems.Delete(i);
|
|
i--;
|
|
continue;
|
|
}
|
|
if ( !dohide || mItems[i].state || (mItems[i].maxval && mItems[i].val) ) continue;
|
|
mItems.Delete(i);
|
|
i--;
|
|
}
|
|
ShouldObscure = (swwm_filterachievements==1);
|
|
AchievementUnknown = TexMan.CheckForTexture("graphics/Achievements/HiddenAchievement.png",TexMan.Type_Any);
|
|
SelectBox = TexMan.CheckForTexture("graphics/Achievements/SelectAchievement.png",TexMan.Type_Any);
|
|
BaseBox = TexMan.CheckForTexture("graphics/Achievements/NoAchievement.png",TexMan.Type_Any);
|
|
mSmallFont = Font.GetFont('TewiFontOutline');
|
|
mTinyFont = Font.GetFont('MiniwiFontOutline');
|
|
}
|
|
|
|
override void Ticker()
|
|
{
|
|
// recalculate counters
|
|
completed = 0;
|
|
incomplete = 0;
|
|
for ( int i=0; i<mItems.Size(); i++ )
|
|
{
|
|
if ( !!(hnd.achievementstate.At(mItems[i].basename).ToInt()) ) completed++;
|
|
else if ( mItems[i].maxval && mItems[i].val ) incomplete++;
|
|
}
|
|
// calculate how many rows to display
|
|
int realh = (Screen.GetHeight()/CleanYFac_1)-160;
|
|
int rows = int(ceil(mItems.Size()/12.));
|
|
mRows = min(rows,realh/40);
|
|
mBaseY = (Screen.GetHeight()-mRows*40*CleanYFac_1)/2;
|
|
maxofs = max(0,rows-mRows);
|
|
}
|
|
|
|
int DrawCaption()
|
|
{
|
|
// let the delegate do all the work
|
|
let fnt = menuDelegate.PickFont(BigFont);
|
|
if ( fnt && (mTitle.Length() > 0) )
|
|
return menuDelegate.DrawCaption(mtitle,fnt,0,true);
|
|
return 0;
|
|
}
|
|
|
|
void DrawTooltip( int y )
|
|
{
|
|
// detailed achievement information
|
|
let a = mItems[mSelected];
|
|
bool completed = !!a.state;
|
|
bool hasprogress = (a.maxval && a.val);
|
|
String str = StringTable.Localize("$SWWM_ACHIEVEMENT_"..a.basename.."_TAG");
|
|
if ( !completed && !hasprogress && ShouldObscure ) SWWMUtility.ObscureText(str,MenuTime()/3);
|
|
int xx = (Screen.GetWidth()-mSmallFont.StringWidth(str)*CleanXFac_1)/2;
|
|
int yy = y;
|
|
if ( !a.maxval || (ShouldObscure && !hasprogress) ) yy += ((mSmallFont.GetHeight()+2)*CleanYFac_1)/2;
|
|
Screen.DrawText(mSmallFont,completed?Font.CR_GREEN:Font.CR_DARKGRAY,xx,yy,str,DTA_CleanNoMove_1,true);
|
|
yy += (mSmallFont.GetHeight()+2)*CleanYFac_1;
|
|
str = a.hasformat?String.Format(StringTable.Localize("$SWWM_ACHIEVEMENT_"..a.basename.."_TXT"),SWWMUtility.ThousandsNum(a.maxval)):StringTable.Localize("$SWWM_ACHIEVEMENT_"..a.basename.."_TXT");
|
|
if ( !completed && !hasprogress && ShouldObscure ) SWWMUtility.ObscureText(str,(MenuTime()/3)+1);
|
|
xx = (Screen.GetWidth()-mTinyFont.StringWidth(str)*CleanXFac_1)/2;
|
|
Screen.DrawText(mTinyFont,completed?Font.CR_WHITE:Font.CR_BLACK,xx,yy,str,DTA_CleanNoMove_1,true);
|
|
if ( a.maxval && (!ShouldObscure || hasprogress) )
|
|
{
|
|
yy += (mTinyFont.GetHeight()+2)*CleanYFac_1;
|
|
int val = 0;
|
|
if ( a.bitfield )
|
|
{
|
|
for ( int i=0; i<a.maxval; i++ )
|
|
val += !!(a.val&(1<<i));
|
|
}
|
|
else val = a.val;
|
|
str = String.Format("%s / %s",SWWMUtility.ThousandsNum(val),SWWMUtility.ThousandsNum(a.maxval));
|
|
xx = (Screen.GetWidth()-mTinyFont.StringWidth(str)*CleanXFac_1)/2;
|
|
Screen.DrawText(mTinyFont,completed?Font.CR_GREEN:Font.CR_DARKGRAY,xx,yy,str,DTA_CleanNoMove_1,true);
|
|
}
|
|
}
|
|
|
|
void DrawFooter( int y )
|
|
{
|
|
int xx;
|
|
int yy = y;
|
|
String str;
|
|
if ( completed == total )
|
|
{
|
|
str = StringTable.Localize("$SWWM_AC_COMPLETE1");
|
|
xx = (Screen.GetWidth()-mSmallFont.StringWidth(str)*CleanXFac_1)/2;
|
|
Screen.DrawText(mSmallFont,Font.CR_FIRE,xx,yy,str,DTA_CleanNoMove_1,true,DTA_ColorOverlay,Color(int(64+64*sin(MSTimeF()/3.6)),255,255,255));
|
|
yy += mSmallFont.GetHeight()*CleanYFac_1;
|
|
// spanish hotfix needed
|
|
int gnd = players[consoleplayer].GetGender();
|
|
str = String.Format(StringTable.Localize("$SWWM_AC_COMPLETE2"),(gnd==1)?"a":"");
|
|
xx = (Screen.GetWidth()-mSmallFont.StringWidth(str)*CleanXFac_1)/2;
|
|
Screen.DrawText(mSmallFont,Font.CR_FIRE,xx,yy,str,DTA_CleanNoMove_1,true,DTA_ColorOverlay,Color(int(64+64*sin(MSTimeF()/3.6)),255,255,255));
|
|
return;
|
|
}
|
|
String str1 = StringTable.Localize("$SWWM_AC_UNLOCKED");
|
|
String str2 = StringTable.Localize("$SWWM_AC_INCOMPLETE");
|
|
String str3 = StringTable.Localize("$SWWM_AC_UNDISCOVERED");
|
|
int maxw = max(mSmallFont.StringWidth(str1),max(mSmallFont.StringWidth(str2),mSmallFont.StringWidth(str3)))+mSmallFont.StringWidth("000");
|
|
xx = (Screen.GetWidth()-maxw*CleanXFac_1)/2;
|
|
Screen.DrawText(mSmallFont,Font.CR_GREEN,xx,yy,str1,DTA_CleanNoMove_1,true);
|
|
yy += mSmallFont.GetHeight()*CleanYFac_1;
|
|
Screen.DrawText(mSmallFont,Font.CR_DARKGRAY,xx,yy,str2,DTA_CleanNoMove_1,true);
|
|
yy += mSmallFont.GetHeight()*CleanYFac_1;
|
|
Screen.DrawText(mSmallFont,Font.CR_DARKGRAY,xx,yy,str3,DTA_CleanNoMove_1,true);
|
|
yy = y;
|
|
str = String.Format("%d",completed);
|
|
xx = (Screen.GetWidth()+maxw*CleanXFac_1)/2-mSmallFont.StringWidth(str)*CleanXFac_1;
|
|
Screen.DrawText(mSmallFont,Font.CR_WHITE,xx,yy,str,DTA_CleanNoMove_1,true);
|
|
yy += mSmallFont.GetHeight()*CleanYFac_1;
|
|
str = String.Format("%d",incomplete);
|
|
xx = (Screen.GetWidth()+maxw*CleanXFac_1)/2-mSmallFont.StringWidth(str)*CleanXFac_1;
|
|
Screen.DrawText(mSmallFont,Font.CR_BLACK,xx,yy,str,DTA_CleanNoMove_1,true);
|
|
yy += mSmallFont.GetHeight()*CleanYFac_1;
|
|
str = String.Format("%d",total-(completed+incomplete));
|
|
xx = (Screen.GetWidth()+maxw*CleanXFac_1)/2-mSmallFont.StringWidth(str)*CleanXFac_1;
|
|
Screen.DrawText(mSmallFont,Font.CR_BLACK,xx,yy,str,DTA_CleanNoMove_1,true);
|
|
}
|
|
|
|
override bool MenuEvent( int mkey, bool fromcontroller )
|
|
{
|
|
int prevsel = mSelected;
|
|
switch( mkey )
|
|
{
|
|
case MKEY_Up:
|
|
if ( mSelected >= 12 ) mSelected -= 12;
|
|
break;
|
|
case MKEY_Down:
|
|
if ( mSelected < (mItems.Size()-12) ) mSelected += 12;
|
|
break;
|
|
case MKEY_Left:
|
|
if ( (mSelected%12) > 0 ) mSelected--;
|
|
break;
|
|
case MKEY_Right:
|
|
if ( ((mSelected%12) < 11) && (mSelected < mItems.Size()-1) ) mSelected++;
|
|
break;
|
|
case MKEY_PageUp:
|
|
if ( ofs > 0 ) MenuSound("menu/cursor");
|
|
ofs = max(0,ofs-1);
|
|
break;
|
|
case MKEY_PageDown:
|
|
if ( ofs < maxofs ) MenuSound("menu/cursor");
|
|
ofs = min(ofs+1,maxofs);
|
|
break;
|
|
default:
|
|
return Super.MenuEvent(mkey,fromcontroller);
|
|
}
|
|
if ( mSelected != prevsel )
|
|
{
|
|
MenuSound("menu/cursor");
|
|
// auto-scroll to selection
|
|
int irow = mSelected/12;
|
|
if ( irow < ofs ) ofs = max(0,irow);
|
|
else if ( irow >= (ofs+mRows) ) ofs = min(maxofs,(irow+1)-mRows);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
override bool OnUiEvent( UIEvent ev )
|
|
{
|
|
switch ( ev.type )
|
|
{
|
|
case UIEvent.Type_WheelDown:
|
|
MenuEvent(MKEY_PageDown,false);
|
|
return false;
|
|
case UIEvent.Type_WheelUp:
|
|
MenuEvent(MKEY_PageUp,false);
|
|
return false;
|
|
}
|
|
return Super.OnUiEvent(ev);
|
|
}
|
|
|
|
override bool MouseEvent( int type, int mx, int my )
|
|
{
|
|
bool res = Super.MouseEvent(type,mx,my);
|
|
if ( type != MOUSE_Click ) return res;
|
|
int xx, yy;
|
|
// first of all, check the scroll buttons
|
|
if ( maxofs > 0 )
|
|
{
|
|
xx = (Screen.GetWidth()+488*CleanXFac_1)/2;
|
|
yy = mBaseY;
|
|
if ( (mx >= xx) && (mx < xx+8*CleanXFac_1) && (my >= yy) && (my < yy+mRows*40*CleanYFac_1) )
|
|
{
|
|
if ( my < yy+mSmallFont.GetHeight()*CleanYFac_1 )
|
|
{
|
|
if ( ofs > 0 ) MenuSound("menu/cursor");
|
|
ofs = max(0,ofs-1);
|
|
return res;
|
|
}
|
|
yy += (mRows*40-mSmallFont.GetHeight())*CleanYFac_1;
|
|
if ( my >= yy )
|
|
{
|
|
if ( ofs < maxofs ) MenuSound("menu/cursor");
|
|
ofs = min(ofs+1,maxofs);
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
if ( (my < mBaseY) || (my >= mBaseY+mRows*40*CleanYFac_1) )
|
|
return res;
|
|
xx = (Screen.GetWidth()-480*CleanXFac_1)/2;
|
|
yy = mBaseY;
|
|
for ( int i=ofs*12; i<mItems.Size(); i++ )
|
|
{
|
|
int left = xx+4*CleanXFac_1;
|
|
int top = yy+4*CleanXFac_1;
|
|
int right = left+32*CleanXFac_1;
|
|
int bottom = top+32*CleanXFac_1;
|
|
if ( (mx >= left) && (mx < right) && (my >= top) && (my < bottom) )
|
|
{
|
|
if ( i != mSelected ) MenuSound("menu/cursor");
|
|
mSelected = i;
|
|
return res;
|
|
}
|
|
xx += 40*CleanXFac_1;
|
|
if ( !((i+1)%12) )
|
|
{
|
|
xx = (Screen.GetWidth()-480*CleanXFac_1)/2;
|
|
yy += 40*CleanYFac_1;
|
|
}
|
|
if ( yy >= mBaseY+mRows*40*CleanYFac_1 ) break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
override void Drawer()
|
|
{
|
|
Super.Drawer();
|
|
DrawCaption();
|
|
DrawTooltip(mBaseY-40*CleanYFac_1);
|
|
// draw scroll buttons (if any)
|
|
int xx, yy;
|
|
if ( maxofs > 0 )
|
|
{
|
|
xx = (Screen.GetWidth()+488*CleanXFac_1)/2;
|
|
yy = mBaseY;
|
|
Screen.DrawText(mSmallFont,(ofs>0)?Font.CR_GREEN:Font.CR_DARKGREEN,xx*CleanXFac_1,yy*CleanYFac_1,(ofs>0)?"▲":"△",DTA_CleanNoMove_1,true);
|
|
yy += (mRows*40-mSmallFont.GetHeight())*CleanYFac_1;
|
|
Screen.DrawText(mSmallFont,(ofs<maxofs)?Font.CR_GREEN:Font.CR_DARKGREEN,xx*CleanXFac_1,yy*CleanYFac_1,(ofs<maxofs)?"▼":"▽",DTA_CleanNoMove_1,true);
|
|
}
|
|
xx = (Screen.GetWidth()-480*CleanXFac_1)/2;
|
|
yy = int(mBaseY);
|
|
int i;
|
|
for ( i=ofs*12; i<mItems.Size(); i++ )
|
|
{
|
|
if ( (yy+40*CleanYFac_1 >= mBaseY) && (yy < mBaseY+mRows*40*CleanYFac_1) )
|
|
{
|
|
let a = mItems[i];
|
|
bool completed = !!a.state;
|
|
bool hasprogress = (a.maxval && a.val);
|
|
Screen.DrawTexture(BaseBox,false,xx+5*CleanXFac_1,yy+5*CleanYFac_1,DTA_CleanNoMove_1,true,DTA_FillColor,(!completed&&!hasprogress&&ShouldObscure)?Color(8,8,8):Color(16,16,16));
|
|
Screen.DrawTexture((!completed&&!hasprogress&&ShouldObscure)?AchievementUnknown:a.icon,false,xx+4*CleanXFac_1,yy+4*CleanYFac_1,DTA_CleanNoMove_1,true,DTA_Desaturate,(!completed)*255,DTA_ColorOverlay,completed?Color(0,0,0,0):(hasprogress||!ShouldObscure)?Color(96,0,0,0):Color(192,0,0,0));
|
|
if ( mSelected == i ) Screen.DrawTexture(SelectBox,false,xx,yy,DTA_CleanNoMove_1,true);
|
|
}
|
|
xx += 40*CleanXFac_1;
|
|
if ( !((i+1)%12) )
|
|
{
|
|
xx = (Screen.GetWidth()-480*CleanXFac_1)/2;
|
|
yy += 40*CleanYFac_1;
|
|
}
|
|
if ( yy >= mBaseY+mRows*40*CleanYFac_1 ) break;
|
|
}
|
|
if ( yy < mBaseY+mRows*40*CleanYFac_1 ) while ( i%12 )
|
|
{
|
|
Screen.DrawTexture(BaseBox,false,xx+5*CleanXFac_1,yy+5*CleanYFac_1,DTA_CleanNoMove_1,true,DTA_FillColor,Color(8,8,8));
|
|
Screen.DrawTexture(BaseBox,false,xx+4*CleanXFac_1,yy+4*CleanYFac_1,DTA_CleanNoMove_1,true);
|
|
xx += 40*CleanXFac_1;
|
|
i++;
|
|
}
|
|
DrawFooter(mBaseY+(mRows*40+8)*CleanYFac_1);
|
|
}
|
|
}
|