Stats Tab: Use function pointers for general stat items.

This commit is contained in:
Mari the Deer 2024-06-12 21:35:03 +02:00
commit 6985a6e230
2 changed files with 223 additions and 97 deletions

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r1131 \cu(Wed May 29 12:16:06 CEST 2024)\c-";
SWWM_SHORTVER="\cw1.3pre r1131 \cu(2024-05-29 12:16:06)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r1132 \cu(Wed Jun 12 21:35:03 CEST 2024)\c-";
SWWM_SHORTVER="\cw1.3pre r1132 \cu(2024-06-12 21:35:03)\c-";

View file

@ -27,6 +27,40 @@ Class DemolitionistStatsTab : DemolitionistMenuTab
lwidth += 16; // account for padding of 8px on each side
stats = Demolitionist(players[consoleplayer].mo)?Demolitionist(players[consoleplayer].mo).mystats:null;
if ( !stats ) return Super.Init(master);
// the general stats are always the same in the same order, so init them all here in one go
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATUPTIME",stats,stat_uptime));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATONFOOT",stats,stat_onfoot));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATFLIGHT",stats,stat_flight));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATSWIM",stats,stat_swim));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATTELE",stats,stat_tele));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATBOOST",stats,stat_boost));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATDASH",stats,stat_dash));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATSTOMP",stats,stat_stomp));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATFUEL",stats,stat_fuel));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATSPEED",stats,stat_speed));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATAIRTIME",stats,stat_airtime));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATPARRY",stats,stat_parry));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATPPARRY",stats,stat_pparry));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATWPONCH",stats,stat_wponch));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATBUSTS",stats,stat_busts));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATBUTTS",stats,stat_butts));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATPATS",stats,stat_pats));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATKISS",stats,stat_kiss));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATFRIENDS",stats,stat_friends));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATITEMS",stats,stat_items));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATSECRETS",stats,stat_secrets));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATKILLS",stats,stat_kills));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATDEATHS",stats,stat_deaths));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATDDEALT",stats,stat_ddealt));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATDTAKEN",stats,stat_dtaken));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATTDEALT",stats,stat_tdealt));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATTTAKEN",stats,stat_ttaken));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATMKILL",stats,stat_mkill));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATSKILL",stats,stat_skill));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATFAVWEAP",stats,stat_favweap));
lists[0].items.Push(new("DemolitionistMenuStatItem").Init(master,"$SWWM_STATHISCORE",stats,stat_hiscore));
for ( int i=0; i<lists[0].items.Size(); i++ )
lists[0].items[i].ypos = i*16;
// because these types of stats don't actually change while the menu is open, we can initialize their lists ONLY ONCE here
foreach ( s:stats.lstats )
lists[2].items.Push(new("DemolitionistMenuMapStatItem").Init(master,s));
@ -182,6 +216,158 @@ Class DemolitionistStatsTab : DemolitionistMenuTab
qsort_achievements(a,p+1,h);
}
// BEGIN stat functions
static ui string stat_uptime( SWWMStats s )
{
int thour = ((level.totaltime-s.lastspawn)/(3600*GameTicRate));
int tmin = ((level.totaltime-s.lastspawn)/(60*GameTicRate))%60;
int tsec = ((level.totaltime-s.lastspawn)/GameTicRate)%60;
return String.Format("%02d\cu:\c-%02d\cu:\c-%02d",thour,tmin,tsec);
}
static ui string stat_onfoot( SWWMStats s )
{
if ( s.grounddist > 32000. )
return String.Format("%g\cu%s\c-",s.grounddist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
return String.Format("%g\cu%s\c-",s.grounddist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
}
static ui string stat_flight( SWWMStats s )
{
if ( s.airdist > 32000. )
return String.Format("%g\cu%s\c-",s.airdist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
return String.Format("%g\cu%s\c-",s.airdist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
}
static ui string stat_swim( SWWMStats s )
{
if ( s.swimdist > 32000. )
return String.Format("%g\cu%s\c-",s.swimdist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
return String.Format("%g\cu%s\c-",s.swimdist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
}
static ui string stat_tele( SWWMStats s )
{
if ( s.teledist > 32000. )
return String.Format("%g\cu%s\c-",s.teledist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
return String.Format("%g\cu%s\c-",s.teledist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
}
static ui string stat_boost( SWWMStats s )
{
return String.Format("%d",s.boostcount);
}
static ui string stat_dash( SWWMStats s )
{
return String.Format("%d",s.dashcount);
}
static ui string stat_stomp( SWWMStats s )
{
return String.Format("%d",s.stompcount);
}
static ui string stat_fuel( SWWMStats s )
{
return String.Format("%g\cu%s\c-",s.fuelusage,StringTable.Localize("$SWWM_UNIT_LITER"));
}
static ui string stat_speed( SWWMStats s )
{
return String.Format("%g\cu%s\c-",(s.topspeed*3600.*GameTicRate)/32000.,StringTable.Localize("$SWWM_UNIT_KPH"));
}
static ui string stat_airtime( SWWMStats s )
{
int thour = (s.airtime/(3600*GameTicRate));
int tmin = (s.airtime/(60*GameTicRate))%60;
int tsec = (s.airtime/GameTicRate)%60;
return String.Format("%02d\cu:\c-%02d\cu:\c-%02d",thour,tmin,tsec);
}
static ui string stat_parry( SWWMStats s )
{
return String.Format("%d",s.parries);
}
static ui string stat_pparry( SWWMStats s )
{
return String.Format("%d",s.pparries);
}
static ui string stat_wponch( SWWMStats s )
{
return String.Format("%d",s.wponch);
}
static ui string stat_busts( SWWMStats s )
{
return String.Format("%d",s.busts);
}
static ui string stat_butts( SWWMStats s )
{
return String.Format("%d",s.buttslams);
}
static ui string stat_pats( SWWMStats s )
{
return String.Format("%d",s.pats);
}
static ui string stat_kiss( SWWMStats s )
{
return String.Format("%d",s.smooch);
}
static ui string stat_friends( SWWMStats s )
{
return String.Format("%d",s.befriend);
}
static ui string stat_items( SWWMStats s )
{
return String.Format("%d",s.items);
}
static ui string stat_secrets( SWWMStats s )
{
return String.Format("%d",s.secrets);
}
static ui string stat_kills( SWWMStats s )
{
return String.Format("%d",s.kills);
}
static ui string stat_deaths( SWWMStats s )
{
return String.Format("%d",s.deaths);
}
static ui string stat_ddealt( SWWMStats s )
{
if ( s.hdamagedealt > 0 )
return String.Format("%d%09d",s.hdamagedealt,s.damagedealt);
return String.Format("%d",s.damagedealt);
}
static ui string stat_dtaken( SWWMStats s )
{
if ( s.hdamagetaken > 0 )
return String.Format("%d%09d",s.hdamagetaken,s.damagetaken);
return String.Format("%d",s.damagetaken);
}
static ui string stat_tdealt( SWWMStats s )
{
return String.Format("%d",s.topdealt);
}
static ui string stat_ttaken( SWWMStats s )
{
return String.Format("%d",s.toptaken);
}
static ui string stat_mkill( SWWMStats s )
{
return String.Format("%d",s.mkill);
}
static ui string stat_skill( SWWMStats s )
{
return String.Format("%d",s.skill);
}
static ui string stat_favweap( SWWMStats s )
{
if ( s.favweapon == -1 ) return "N/A";
if ( s.wstats[s.favweapon].w == 'SWWMWeapon' ) return StringTable.Localize("$SWWM_YOURSELF");
if ( s.wstats[s.favweapon].w == 'SWWMGesture' ) return StringTable.Localize("$SWWM_DOKIDOKI");
if ( s.wstats[s.favweapon].w == 'SWWMItemGesture' ) return StringTable.Localize("$T_FROGGY");
if ( s.wstats[s.favweapon].w == 'Weapon' ) return StringTable.Localize("$SWWM_GRAVKILL");
if ( s.wstats[s.favweapon].w == 'DoomWeapon' ) return StringTable.Localize("$SWWM_PARRYKILL");
let def = GetDefaultByType(s.wstats[s.favweapon].w);
return def.GetTag();
}
static ui string stat_hiscore( SWWMStats s )
{
return String.Format("\cu¥\c-%09d",s.hiscore);
}
// END stat functions
override void Ticker()
{
if ( !stats ) return;
@ -191,102 +377,8 @@ Class DemolitionistStatsTab : DemolitionistMenuTab
switch ( section )
{
case 0:
if ( lists[0].items.Size() == 0 ) // allocate first
{
for ( int i=0; i<31; i++ )
{
let li = new("DemolitionistMenuListItem").Init(master,"");
li.ypos = i*16;
lists[0].items.Push(li);
}
}
// not much to do here, they update themselves and are left-aligned
maxofs[0] = int(16*lists[0].items.Size()-(master.ws.y-46));
// oof
int thour = ((level.totaltime-stats.lastspawn)/(3600*GameTicRate));
int tmin = ((level.totaltime-stats.lastspawn)/(60*GameTicRate))%60;
int tsec = ((level.totaltime-stats.lastspawn)/GameTicRate)%60;
str = String.Format("\cx%s\c-%02d\cu:\c-%02d\cu:\c-%02d",StringTable.Localize("$SWWM_STATUPTIME"),thour,tmin,tsec);
lists[0].items[0].label = str;
if ( stats.grounddist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATONFOOT"),stats.grounddist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATONFOOT"),stats.grounddist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
lists[0].items[1].label = str;
if ( stats.airdist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFLIGHT"),stats.airdist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFLIGHT"),stats.airdist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
lists[0].items[2].label = str;
if ( stats.swimdist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSWIM"),stats.swimdist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSWIM"),stats.swimdist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
lists[0].items[3].label = str;
if ( stats.teledist > 32000. ) str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATTELE"),stats.teledist/32000.,StringTable.Localize("$SWWM_UNIT_KILOMETER"));
else str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATTELE"),stats.teledist/32.,StringTable.Localize("$SWWM_UNIT_METER"));
lists[0].items[4].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATBOOST"),stats.boostcount);
lists[0].items[5].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDASH"),stats.dashcount);
lists[0].items[6].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSTOMP"),stats.stompcount);
lists[0].items[7].label = str;
str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFUEL"),stats.fuelusage,StringTable.Localize("$SWWM_UNIT_LITER"));
lists[0].items[8].label = str;
str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSPEED"),(stats.topspeed*3600.*GameTicRate)/32000.,StringTable.Localize("$SWWM_UNIT_KPH"));
lists[0].items[9].label = str;
thour = (stats.airtime/(3600*GameTicRate));
tmin = (stats.airtime/(60*GameTicRate))%60;
tsec = (stats.airtime/GameTicRate)%60;
str = String.Format("\cx%s\c-%02d\cu:\c-%02d\cu:\c-%02d",StringTable.Localize("$SWWM_STATAIRTIME"),thour,tmin,tsec);
lists[0].items[10].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATPARRY"),stats.parries);
lists[0].items[11].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATPPARRY"),stats.pparries);
lists[0].items[12].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATWPONCH"),stats.wponch);
lists[0].items[13].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATBUSTS"),stats.busts);
lists[0].items[14].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATBUTTS"),stats.buttslams);
lists[0].items[15].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATPATS"),stats.pats);
lists[0].items[16].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATKISS"),stats.smooch);
lists[0].items[17].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATFRIENDS"),stats.befriend);
lists[0].items[18].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATITEMS"),stats.items);
lists[0].items[19].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSECRETS"),stats.secrets);
lists[0].items[20].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATKILLS"),stats.kills);
lists[0].items[21].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDEATHS"),stats.deaths);
lists[0].items[22].label = str;
if ( stats.hdamagedealt > 0 ) str = str = String.Format("\cx%s\c-%d%09d",StringTable.Localize("$SWWM_STATDDEALT"),stats.hdamagedealt,stats.damagedealt);
else str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDDEALT"),stats.damagedealt);
lists[0].items[23].label = str;
if ( stats.hdamagetaken > 0 ) str = String.Format("\cx%s\c-%d%09d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.hdamagetaken,stats.damagetaken);
else str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATDTAKEN"),stats.damagetaken);
lists[0].items[24].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATTDEALT"),stats.topdealt);
lists[0].items[25].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATTTAKEN"),stats.toptaken);
lists[0].items[26].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATMKILL"),stats.mkill);
lists[0].items[27].label = str;
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSKILL"),stats.skill);
lists[0].items[28].label = str;
str = String.Format("\cx%s\c-",StringTable.Localize("$SWWM_STATFAVWEAP"));
if ( stats.favweapon == -1 ) str = str.."N/A";
else if ( stats.wstats[stats.favweapon].w == 'SWWMWeapon' ) str = str..StringTable.Localize("$SWWM_YOURSELF");
else if ( stats.wstats[stats.favweapon].w == 'SWWMGesture' ) str = str..StringTable.Localize("$SWWM_DOKIDOKI");
else if ( stats.wstats[stats.favweapon].w == 'SWWMItemGesture' ) str = str..StringTable.Localize("$T_FROGGY");
else if ( stats.wstats[stats.favweapon].w == 'Weapon' ) str = str..StringTable.Localize("$SWWM_GRAVKILL");
else if ( stats.wstats[stats.favweapon].w == 'DoomWeapon' ) str = str..StringTable.Localize("$SWWM_PARRYKILL");
else
{
let def = GetDefaultByType(stats.wstats[stats.favweapon].w);
str = str..def.GetTag();
}
lists[0].items[29].label = str;
str = String.Format("\cx%s\cu¥\c-%09d",StringTable.Localize("$SWWM_STATHISCORE"),stats.hiscore);
lists[0].items[30].label = str;
break;
case 1:
// theoretically we can assume that the monster stats list will never shrink in the middle of gameplay, only grow
@ -521,6 +613,40 @@ Class DemolitionistStatsTab : DemolitionistMenuTab
}
}
// general stat item
Class DemolitionistMenuStatItem : DemolitionistMenuListItem
{
SWWMStats s;
Function<ui string(SWWMStats)> fn;
String txt;
DemolitionistMenuStatItem Init( DemolitionistMenu master, String label, SWWMStats s, Function<ui string(SWWMStats)> fn )
{
Super.Init(master,label);
self.s = s;
self.fn = fn;
return self;
}
override int GetWidth()
{
String str = String.Format("%s%s",label,txt);
return master.mSmallFont.StringWidth(str);
}
override void Ticker()
{
// call update fn
txt = fn.call(s);
}
override void Drawer( Vector2 pos, bool selected )
{
String str = String.Format("\cx%s\c-%s",label,txt);
Screen.DrawText(master.mSmallFont,Font.CR_WHITE,master.origin.x+pos.x,master.origin.y+pos.y,str,DTA_VirtualWidthF,master.ss.x,DTA_VirtualHeightF,master.ss.y,DTA_KeepRatio,true);
}
}
// monster kill stat item
Class DemolitionistMenuKillItem : DemolitionistMenuListItem
{