Alternate HUD style partially implemented.

This commit is contained in:
Mari the Deer 2022-06-03 19:17:33 +02:00
commit 4e29d1c2fe
18 changed files with 913 additions and 30 deletions

View file

@ -88,7 +88,7 @@ Class SheenAmmo : SWWMAmmo
Inventory.Amount 1;
Inventory.MaxAmount 300;
Ammo.BackpackAmount 60;
Ammo.BackpackMaxAmount 1200;
Ammo.BackpackMaxAmount 900;
Ammo.DropAmount 3;
+FLOATBOB;
FloatBobStrength 0.25;
@ -323,7 +323,7 @@ Class RayBolt : MagAmmo
Inventory.Icon "graphics/HUD/Icons/A_RayBolt.png";
MagAmmo.ParentAmmo "RayAmmo";
MagAmmo.ClipSize 10;
Inventory.MaxAmount 15;
Inventory.MaxAmount 10;
+FLOATBOB;
FloatBobStrength 0.25;
}
@ -399,8 +399,8 @@ Class MisterRound : MagAmmo
MagAmmo.PickupTag "MRROUND";
Inventory.Icon "graphics/HUD/Icons/A_MRRound.png";
MagAmmo.ParentAmmo "MisterAmmo";
MagAmmo.ClipSize 30;
Inventory.MaxAmount 40;
MagAmmo.ClipSize 20;
Inventory.MaxAmount 20;
+FLOATBOB;
FloatBobStrength 0.25;
}
@ -471,7 +471,7 @@ Class MisterAmmo : SWWMAmmo
Inventory.Amount 1;
Inventory.MaxAmount 2;
Ammo.BackpackAmount 0;
Ammo.BackpackMaxAmount 6;
Ammo.BackpackMaxAmount 4;
Ammo.DropAmount 1;
SWWMAmmo.MagAmmoType "MisterRound";
+FLOATBOB;
@ -551,7 +551,7 @@ Class UltimatePod : MagAmmo
Inventory.Icon "graphics/HUD/Icons/A_UltimatePod.png";
MagAmmo.ParentAmmo "UltimateAmmo";
MagAmmo.ClipSize 4;
Inventory.MaxAmount 6;
Inventory.MaxAmount 4;
+FLOATBOB;
FloatBobStrength 0.25;
}

View file

@ -3,6 +3,8 @@ extend Class SWWMHandler
{
// for menu events
transient Array<MenuTransaction> checklist;
// for the compact hud
transient int WeaponFlash[10];
override void ConsoleProcess( ConsoleEvent e )
{
@ -617,6 +619,12 @@ extend Class SWWMHandler
}
else if ( e.Name ~== "swwmgamelore" )
SWWMLoreLibrary.Add(players[e.Args[0]],"Madcat");
else if ( e.Name ~== "swwmweaponreceive" )
{
if ( e.Args[1] != consoleplayer ) return;
if ( (e.Args[0] < 0) || (e.Args[0] > 9) ) return;
WeaponFlash[e.Args[0]] = gametic+25;
}
// cheats go here
else CheatEvent(e);
}

View file

@ -1,5 +1,820 @@
// TODO Alternate, more compact hud with full ammo listing
Class SWWMAltHud : AltHud
Class KeyGet
{
Class<Key> got;
int flashtime;
}
Enum EMiniHUDFontColor
{
MCR_DEMOHUD,
MCR_IBUKIHUD,
MCR_SAYAHUD,
MCR_KIRINHUD,
MCR_MARISAHUD,
MCR_VOIDHUD,
MCR_WHITE,
MCR_RED,
MCR_GREEN,
MCR_BLUE,
MCR_YELLOW,
MCR_CYAN,
MCR_PURPLE,
MCR_BRASS,
MCR_SILVER,
MCR_GOLD,
MCR_MANA,
MCR_CRIMSON,
MCR_ELDRITCH,
MCR_KINYLUM,
MCR_NOKRON,
MCR_NOKOROKINYLUM,
MCR_DEMOBLUE,
MCR_DEMOPINK,
MCR_FLASH,
MCR_REDFLASH,
NUM_MINIHUD_COLOR
};
extend Class SWWMStatusBar
{
TextureID AltStatusTex, AltWeaponTex, AltScoreTex, AltHealthTex[9],
AltFuelTex[2], AltDashTex, AltGenericAmmoTex[3], AltAmmoTex[3];
Font MiniHUDFont, MiniHUDFontOutline;
int mhudfontcol[NUM_MINIHUD_COLOR];
int PulsePhase; // for health pulsing
// for flashing some elements in the hud
Array<KeyGet> keyflash;
int oldkills, olditems, oldsecrets;
int oldtkills, oldtitems, oldtsecrets;
int killflash, itemflash, secretflash;
int tkillflash, titemflash, tsecretflash;
// top stuff colors
int tclabel, tcvalue, tcextra, tccompl, tcsucks;
String tclabel_s, tcextra_s;
int AmmoFlash[27]; // flash when new ammo is received
int AmmoOldAmounts[27]; // to detect when to flash
int AmmoMaxFlash[27]; // flash when ammo max amount changes
int AmmoOldMaxAmounts[27]; // to detect when to flash
Class<SWWMAmmo> AmmoSlots[27]; // ammo type on each slot
String AmmoNames[27]; // ammo 4-letter names
int HealthFlash; // flash when healing
int LastHealth; // to detect when to flash
int LagHealth[10]; // for delayed decay bar
SmoothDynamicValueInterpolator AltHealthInter, AltFuelInter, AltDashInter;
SmoothLinearValueInterpolator LagHealthInter;
void Alt_FlushInterpolators()
{
int hp = CPlayer.Health;
AltHealthInter.Reset(hp);
for ( int i=9; i>0; i-- )
LagHealth[i] = hp;
LagHealthInter.Reset(hp);
let d = Demolitionist(CPlayer.mo);
if ( d )
{
AltFuelInter.Reset(d.dashfuel/2);
AltDashInter.Reset((40-d.dashcooldown)*3);
}
else
{
AltFuelInter.Reset(0);
AltDashInter.Reset(0);
}
}
void Alt_UpdateInterpolators()
{
int hp = CPlayer.Health;
AltHealthInter.Update(hp);
// flash 'em
if ( hp > LastHealth ) HealthFlash = gametic+25;
// lag
if ( hp > LastHealth )
{
for ( int i=9; i>0; i-- )
LagHealth[i] = hp;
}
LagHealth[0] = LastHealth = hp;
LagHealthInter.Update(LagHealth[9]);
for ( int i=9; i>0; i-- )
LagHealth[i] = LagHealth[i-1];
// ammo updates
for ( int i=0; i<27; i++ )
{
let a = SWWMAmmo(CPlayer.mo.FindInventory(AmmoSlots[i]));
int amt = 0;
int maxamt = 0;
if ( a )
{
amt = a.Amount;
maxamt = a.MaxAmount;
if ( a.MagAmmoType )
{
let m = MagAmmo(CPlayer.mo.FindInventory(a.MagAmmoType));
if ( m )
{
amt *= m.ClipSize;
amt += m.Amount;
maxamt *= m.ClipSize;
}
}
}
else
{
let a = GetDefaultByType(AmmoSlots[i]);
maxamt = a.MaxAmount;
if ( a.MagAmmoType )
{
let m = GetDefaultByType(a.MagAmmoType);
maxamt *= m.ClipSize;
}
}
if ( amt > AmmoOldAmounts[i] ) AmmoFlash[i] = gametic+25;
AmmoOldAmounts[i] = amt;
if ( maxamt > AmmoOldMaxAmounts[i] ) AmmoMaxFlash[i] = gametic+25;
AmmoOldMaxAmounts[i] = maxamt;
}
}
void Alt_Tick()
{
let d = Demolitionist(CPlayer.mo);
if ( d )
{
AltFuelInter.Update(d.dashfuel/2);
AltDashInter.Update((40-d.dashcooldown)*3);
}
else
{
AltFuelInter.Update(0);
AltDashInter.Update(0);
}
// stats flashing
if ( level.killed_monsters > oldkills )
{
oldkills = level.killed_monsters;
killflash = gametic+25;
}
if ( level.found_items > olditems )
{
olditems = level.found_items;
itemflash = gametic+25;
}
if ( level.found_secrets > oldsecrets )
{
oldsecrets = level.found_secrets;
secretflash = gametic+25;
}
if ( level.total_monsters > oldtkills )
{
oldtkills = level.total_monsters;
tkillflash = gametic+25;
}
if ( level.total_items > oldtitems )
{
oldtitems = level.total_items;
titemflash = gametic+25;
}
if ( level.total_secrets > oldtsecrets )
{
oldtsecrets = level.total_secrets;
tsecretflash = gametic+25;
}
// purge expired key flashes
for ( int i=0; i<keyflash.Size(); i++ )
{
if ( keyflash[i].flashtime >= gametic ) continue;
keyflash.Delete(i--);
}
// low health pulsing
if ( (CPlayer.health <= 0) || (CPlayer.health > 25) )
{
PulsePhase = 0;
return;
}
PulsePhase--;
if ( (PulsePhase < 0) || (PulsePhase > CPlayer.health*2+25) )
PulsePhase = CPlayer.health*2+25;
}
// hello??? why is this function clearscope???
override void ReceivedWeapon( Weapon weapn )
{
Super.ReceivedWeapon(weapn);
int dummy, slot;
[dummy, slot] = players[consoleplayer].weapons.LocateWeapon(weapn.GetClass());
EventHandler.SendNetworkEvent("swwmweaponreceive",slot,consoleplayer);
}
void Alt_Init()
{
AltStatusTex = TexMan.CheckForTexture("graphics/AltHUD/StatusBox.png",TexMan.Type_Any);
AltWeaponTex = TexMan.CheckForTexture("graphics/AltHUD/WeaponBox.png",TexMan.Type_Any);
AltScoreTex = TexMan.CheckForTexture("graphics/AltHUD/ScoreBox.png",TexMan.Type_Any);
AltHealthTex[0] = TexMan.CheckForTexture("graphics/AltHUD/HealthBar0.png",TexMan.Type_Any);
AltHealthTex[1] = TexMan.CheckForTexture("graphics/AltHUD/HealthBar1.png",TexMan.Type_Any);
AltHealthTex[2] = TexMan.CheckForTexture("graphics/AltHUD/HealthBar2.png",TexMan.Type_Any);
AltHealthTex[3] = TexMan.CheckForTexture("graphics/AltHUD/HealthBar3.png",TexMan.Type_Any);
AltHealthTex[4] = TexMan.CheckForTexture("graphics/AltHUD/HealthBarS.png",TexMan.Type_Any);
AltHealthTex[5] = TexMan.CheckForTexture("graphics/AltHUD/HealthBarD.png",TexMan.Type_Any);
AltHealthTex[6] = TexMan.CheckForTexture("graphics/AltHUD/HealthBarP.png",TexMan.Type_Any);
AltHealthTex[7] = TexMan.CheckForTexture("graphics/AltHUD/HealthBarF.png",TexMan.Type_Any);
AltHealthTex[8] = TexMan.CheckForTexture("graphics/AltHUD/HealthBarL.png",TexMan.Type_Any);
AltFuelTex[0] = TexMan.CheckForTexture("graphics/AltHUD/FuelBar.png",TexMan.Type_Any);
AltFuelTex[1] = TexMan.CheckForTexture("graphics/AltHUD/FuelBarS.png",TexMan.Type_Any);
AltDashTex = TexMan.CheckForTexture("graphics/AltHUD/DashBar.png",TexMan.Type_Any);
AltGenericAmmoTex[0] = TexMan.CheckForTexture("graphics/AltHUD/GenericAmmoBoxL.png",TexMan.Type_Any);
AltGenericAmmoTex[1] = TexMan.CheckForTexture("graphics/AltHUD/GenericAmmoBoxM.png",TexMan.Type_Any);
AltGenericAmmoTex[2] = TexMan.CheckForTexture("graphics/AltHUD/GenericAmmoBoxR.png",TexMan.Type_Any);
AltAmmoTex[0] = TexMan.CheckForTexture("graphics/AltHUD/AmmoBoxT.png",TexMan.Type_Any);
AltAmmoTex[1] = TexMan.CheckForTexture("graphics/AltHUD/AmmoBoxM.png",TexMan.Type_Any);
AltAmmoTex[2] = TexMan.CheckForTexture("graphics/AltHUD/AmmoBoxB.png",TexMan.Type_Any);
MiniHudFont = Font.GetFont("MiniHUDFlat");
MiniHudFontOutline = Font.GetFont("MiniHUDOutline");
mhudfontcol[MCR_DEMOHUD] = Font.FindFontColor("MiniDemoHUD");
mhudfontcol[MCR_IBUKIHUD] = Font.FindFontColor("MiniIbukiHUD");
mhudfontcol[MCR_SAYAHUD] = Font.FindFontColor("MiniSayaHUD");
mhudfontcol[MCR_KIRINHUD] = Font.FindFontColor("MiniKirinHUD");
mhudfontcol[MCR_MARISAHUD] = Font.FindFontColor("MiniMarisaHUD");
mhudfontcol[MCR_VOIDHUD] = Font.FindFontColor("MiniVoidHUD");
mhudfontcol[MCR_WHITE] = Font.FindFontColor("MiniWhite");
mhudfontcol[MCR_RED] = Font.FindFontColor("MiniRed");
mhudfontcol[MCR_GREEN] = Font.FindFontColor("MiniGreen");
mhudfontcol[MCR_BLUE] = Font.FindFontColor("MiniBlue");
mhudfontcol[MCR_YELLOW] = Font.FindFontColor("MiniYellow");
mhudfontcol[MCR_CYAN] = Font.FindFontColor("MiniCyan");
mhudfontcol[MCR_PURPLE] = Font.FindFontColor("MiniPurple");
mhudfontcol[MCR_BRASS] = Font.FindFontColor("MiniBrass");
mhudfontcol[MCR_SILVER] = Font.FindFontColor("MiniSilver");
mhudfontcol[MCR_GOLD] = Font.FindFontColor("MiniGold");
mhudfontcol[MCR_MANA] = Font.FindFontColor("MiniMana");
mhudfontcol[MCR_CRIMSON] = Font.FindFontColor("MiniCrimson");
mhudfontcol[MCR_ELDRITCH] = Font.FindFontColor("MiniEldritch");
mhudfontcol[MCR_KINYLUM] = Font.FindFontColor("MiniKinylum");
mhudfontcol[MCR_NOKRON] = Font.FindFontColor("MiniNokron");
mhudfontcol[MCR_NOKOROKINYLUM] = Font.FindFontColor("MiniNokorokinylum");
mhudfontcol[MCR_DEMOBLUE] = Font.FindFontColor("MiniDemoBlue");
mhudfontcol[MCR_DEMOPINK] = Font.FindFontColor("MiniDemoPink");
mhudfontcol[MCR_FLASH] = Font.FindFontColor("MiniFlash");
mhudfontcol[MCR_REDFLASH] = Font.FindFontColor("MiniRedFlash");
tclabel = mhudfontcol[MCR_BRASS];
tcvalue = mhudfontcol[MCR_WHITE];
tcextra = mhudfontcol[MCR_IBUKIHUD];
tccompl = mhudfontcol[MCR_YELLOW];
tcsucks = mhudfontcol[MCR_RED];
tclabel_s = "[MiniBrass]";
tcextra_s = "[MiniIbukiHUD]";
LastHealth = CPlayer?CPlayer.health:100;
let d = Demolitionist(CPlayer?CPlayer.mo:null);
AltHealthInter = SmoothDynamicValueInterpolator.Create(LastHealth,.5,1,100);
AltFuelInter = SmoothDynamicValueInterpolator.Create(d?(d.dashfuel/2):120,.5,1,120);
AltDashInter = SmoothDynamicValueInterpolator.Create(d?((40-d.dashcooldown)*3):40,.5,1,40);
LagHealthInter = SmoothLinearValueInterpolator.Create(LastHealth,2);
for ( int i=0; i<10; i++ ) LagHealth[i] = LastHealth;
AmmoSlots[0] = 'RedShell';
AmmoSlots[1] = 'GreenShell';
AmmoSlots[2] = 'WhiteShell';
AmmoSlots[3] = 'BlueShell';
AmmoSlots[4] = 'BlackShell';
AmmoSlots[5] = 'PurpleShell';
AmmoSlots[6] = 'GoldShell';
AmmoSlots[7] = 'SMW05Ammo';
AmmoSlots[8] = 'EvisceratorShell';
AmmoSlots[9] = 'SheenAmmo';
AmmoSlots[10] = 'HellblazerMissiles';
AmmoSlots[11] = 'HellblazerCrackshots';
AmmoSlots[12] = 'HellblazerRavagers';
AmmoSlots[13] = 'HellblazerWarheads';
AmmoSlots[14] = 'QuadravolAmmo';
AmmoSlots[15] = 'SparkUnit';
AmmoSlots[16] = 'SparksterBAmmo';
AmmoSlots[17] = 'SparksterRAmmo';
AmmoSlots[18] = 'SilverBulletAmmo';
AmmoSlots[19] = 'SilverBulletAmmo2';
AmmoSlots[20] = 'RayAmmo';
AmmoSlots[21] = 'CandyGunAmmo';
AmmoSlots[22] = 'CandyGunSpares';
AmmoSlots[23] = 'MisterAmmo';
AmmoSlots[24] = 'MisterGAmmo';
AmmoSlots[25] = 'YnykronAmmo';
AmmoSlots[26] = 'UltimateAmmo';
AmmoNames[0] = "SHOT";
AmmoNames[1] = "SLUG";
AmmoNames[2] = "DRGN";
AmmoNames[3] = "SALT";
AmmoNames[4] = "FLCH";
AmmoNames[5] = "BALL";
AmmoNames[6] = "GOLD";
AmmoNames[7] = "SCRW";
AmmoNames[8] = "FLAK";
AmmoNames[9] = "MACH";
AmmoNames[10] = "RCKT";
AmmoNames[11] = "CLUS";
AmmoNames[12] = "RAVG";
AmmoNames[13] = "WARH";
AmmoNames[14] = "QUAD";
AmmoNames[15] = "BSPK";
AmmoNames[16] = "KINY";
AmmoNames[17] = "NOKR";
AmmoNames[18] = "RIFL";
AmmoNames[19] = "CHOD";
AmmoNames[20] = "BOLT";
AmmoNames[21] = "CAND";
AmmoNames[22] = "CGUN";
AmmoNames[23] = "MSTR";
AmmoNames[24] = "MGRN";
AmmoNames[25] = "CRYS";
AmmoNames[26] = "ULTI";
for ( int i=0; i<27; i++ )
{
AmmoFlash[i] = 0;
AmmoOldAmounts[i] = int.min;
if ( i >= 8 ) break;
AmmoMaxFlash[i] = 0;
AmmoOldMaxAmounts[i] = int.min;
}
}
void Alt_DrawTopStuff()
{
int xx, yy = margin;
if ( !automapactive && swwm_mm_enable )
yy += ((HALFMAPSIZE+2)*2)+5;
// draw stats and timer when automap is open
int fstats = swwm_forcestats;
if ( automapactive || (fstats > 0) )
{
xx = int(ss.x-(margin+2));
String str;
if ( automapactive || (fstats > 1) )
{
int label = am_showmaplabel;
String ln = level.levelname;
int iof = ln.IndexOf(" - by: ");
if ( iof != -1 ) ln.Truncate(iof);
if ( !label || ((level.clusterflags&level.CLUSTER_HUB) && (label == 2)) ) str = ln;
else str = String.Format("%s - %s",level.mapname.MakeUpper(),ln);
Screen.DrawText(mBigFont,tclabel,xx-mBigFont.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy += mBigFont.GetHeight()+4;
}
if ( (level.total_monsters > 0) && am_showmonsters && !deathmatch )
{
str = String.Format("\c"..tclabel_s.."K \c-%d\c"..tcextra_s.."/\c-%d",level.killed_monsters,level.total_monsters);
Screen.DrawText(MiniHUDFontOutline,(level.killed_monsters>=level.total_monsters)?tccompl:tcvalue,xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
if ( killflash && (gametic < killflash) )
{
double alph = max((killflash-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%d/%d",level.killed_monsters,level.total_monsters);
int slashpos = str.IndexOf("/");
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_FLASH],xx-MiniHUDFontOutline.StringWidth(str),yy,str.Left(slashpos),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
}
if ( tkillflash && (gametic < tkillflash) )
{
double alph = max((tkillflash-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%d",level.total_monsters);
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_FLASH],xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
}
yy += MiniHUDFontOutline.GetHeight()+2;
}
if ( (level.total_items > 0) && am_showitems && !deathmatch )
{
str = String.Format("\c"..tclabel_s.."I \c-%d\c"..tcextra_s.."/\c-%d",level.found_items,level.total_items);
Screen.DrawText(MiniHUDFontOutline,(level.found_items>=level.total_items)?tccompl:tcvalue,xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
if ( itemflash && (gametic < itemflash) )
{
double alph = max((itemflash-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%d/%d",level.found_items,level.total_items);
int slashpos = str.IndexOf("/");
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_FLASH],xx-MiniHUDFontOutline.StringWidth(str),yy,str.Left(slashpos),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
}
if ( titemflash && (gametic < titemflash) )
{
double alph = max((titemflash-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%d",level.total_items);
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_FLASH],xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
}
yy += MiniHUDFontOutline.GetHeight()+2;
}
if ( (level.total_secrets > 0) && am_showsecrets && !deathmatch )
{
str = String.Format("\c"..tclabel_s.."S \c-%d\c"..tcextra_s.."/\c-%d",level.found_secrets,level.total_secrets);
Screen.DrawText(MiniHUDFontOutline,(level.found_secrets>=level.total_secrets)?tccompl:tcvalue,xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
if ( secretflash && (gametic < secretflash) )
{
double alph = max((secretflash-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%d/%d",level.found_secrets,level.total_secrets);
int slashpos = str.IndexOf("/");
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_FLASH],xx-MiniHUDFontOutline.StringWidth(str),yy,str.Left(slashpos),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
}
if ( tsecretflash && (gametic < tsecretflash) )
{
double alph = max((tsecretflash-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%d",level.total_secrets);
Screen.DrawText(MiniHUDFontOutline,mhudfontcol[MCR_FLASH],xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
}
yy += MiniHUDFontOutline.GetHeight()+2;
}
int sec;
if ( am_showtime )
{
sec = Thinker.Tics2Seconds(level.maptime);
str = String.Format("\c"..tclabel_s.."T \c-%02d\c"..tcextra_s..":\c-%02d\c"..tcextra_s..":\c-%02d",sec/3600,(sec%3600)/60,sec%60);
Screen.DrawText(MiniHUDFontOutline,((level.sucktime>0)&&(sec>=(level.sucktime*3600)))?tcsucks:((level.partime>0)&&(sec<=level.partime))?tccompl:tcvalue,xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy += MiniHUDFontOutline.GetHeight()+2;
}
// don't show total time if it's equal to map time
if ( am_showtotaltime && (level.totaltime != level.maptime) )
{
sec = Thinker.Tics2Seconds(level.totaltime);
str = String.Format("\c"..tclabel_s.."TT \c-%02d\c"..tcextra_s..":\c-%02d\c"..tcextra_s..":\c-%02d",sec/3600,(sec%3600)/60,sec%60);
Screen.DrawText(MiniHUDFontOutline,tcvalue,xx-MiniHUDFontOutline.StringWidth(str),yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy += MiniHUDFontOutline.GetHeight()+2;
}
yy += 3;
}
// draw key icons
Vector2 keypos = (ss.x-(margin+2),yy);
int colc = 0;
double colh = 0;
int n = Key.GetKeyTypeCount();
Array<Key> klist;
for ( int i=0; i<n; i++ )
{
let k = Key(CPlayer.mo.FindInventory(Key.GetKeyType(i)));
if ( !k || !k.Icon.IsValid() ) continue;
klist.Push(k);
}
int maxcolc = (gameinfo.gametype&GAME_DOOMCHEX)?6:4;
for ( int i=0; i<klist.Size(); i++ )
{
let k = klist[i];
// Hexen key icons aren't meant for this kind of HUD
TextureID icon = (k is 'HexenKey')?k.SpawnState.GetSpriteTexture(0):k.Icon;
Vector2 siz = TexMan.GetScaledSize(icon);
Screen.DrawTexture(icon,false,keypos.x-siz.x,keypos.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_TopLeft,true);
for ( int j=0; j<keyflash.Size(); j++ )
{
if ( !(k is keyflash[j].got) ) continue;
if ( !keyflash[j].flashtime || (gametic >= keyflash[j].flashtime) ) continue;
double alph = max((keyflash[j].flashtime-(gametic+FracTic))/25.,0.)**1.5;
Screen.DrawTexture(icon,false,keypos.x-siz.x,keypos.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_TopLeft,true,DTA_ColorOverlay,0xFFFFC040,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
break;
}
keypos.x -= siz.x+2;
colh = max(colh,siz.y);
if ( ++colc == maxcolc )
{
keypos.x = ss.x-(margin+2);
keypos.y += colh+2;
colh = colc = 0;
}
}
}
void Alt_DrawWeapons()
{
if ( CPlayer.ReadyWeapon is 'SWWMWeapon' ) SWWMWeapon(CPlayer.ReadyWeapon).DrawWeaponAlt(FracTic,ss.x-(margin+55),ss.y-(margin+11),hs,ss);
else
{
// generic display
double xx = ss.x-(margin+57), yy = ss.y-(margin+11);
String str;
int len;
if ( CPlayer.ReadyWeapon.Ammo2 && (CPlayer.ReadyWeapon.Ammo2 != CPlayer.ReadyWeapon.Ammo1) )
{
str = String.Format("%d",CPlayer.ReadyWeapon.Ammo2.Amount);
len = str.Length();
yy -= 11;
Screen.DrawTexture(AltGenericAmmoTex[2],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
for ( int i=0; i<len; i++ )
{
xx -= 4;
Screen.DrawTexture(AltGenericAmmoTex[1],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
Screen.DrawTexture(AltGenericAmmoTex[0],false,xx-2,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
Screen.DrawText(MiniHUDFont,mhudfontcol[(CPlayer.ReadyWeapon.Ammo2.Amount<=0)?MCR_RED:MCR_BRASS],xx,yy+2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy += 11;
}
xx = ss.x-(margin+57);
if ( CPlayer.ReadyWeapon.Ammo1 )
{
str = String.Format("%d",CPlayer.ReadyWeapon.Ammo1.Amount);
len = str.Length();
Screen.DrawTexture(AltGenericAmmoTex[2],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
for ( int i=0; i<len; i++ )
{
xx -= 4;
Screen.DrawTexture(AltGenericAmmoTex[1],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
Screen.DrawTexture(AltGenericAmmoTex[0],false,xx-2,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
Screen.DrawText(MiniHUDFont,mhudfontcol[(CPlayer.ReadyWeapon.Ammo1.Amount<=0)?MCR_RED:MCR_BRASS],xx,yy+2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
}
Screen.DrawTexture(AltWeaponTex,false,ss.x-(margin+70),ss.y-(margin+9),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
double xx = ss.x-(margin+68), yy = ss.y-(margin+7);
for ( int i=1; i<=10; i++,xx+=7 )
{
int ncolor = mhudfontcol[MCR_WHITE];
if ( !CPlayer.HasWeaponsInSlot(i%10) )
{
Screen.DrawText(MiniHUDFont,ncolor,xx,yy,String.Format("%d",(i%10)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(128,0,0,0));
continue;
}
bool selected = false;
bool dummy;
int slot;
SWWMGesture hasgesture = null;
SWWMItemGesture hasitemgesture = null;
if ( CPlayer.PendingWeapon is 'SWWMGesture' ) hasgesture = SWWMGesture(CPlayer.PendingWeapon);
else if ( CPlayer.ReadyWeapon is 'SWWMGesture' ) hasgesture = SWWMGesture(CPlayer.ReadyWeapon);
if ( CPlayer.PendingWeapon is 'SWWMItemGesture' ) hasitemgesture = SWWMItemGesture(CPlayer.PendingWeapon);
else if ( CPlayer.ReadyWeapon is 'SWWMItemGesture' ) hasitemgesture = SWWMItemGesture(CPlayer.ReadyWeapon);
if ( hasgesture && hasgesture.formerweapon )
{
[dummy, slot] = CPlayer.weapons.LocateWeapon(hasgesture.formerweapon.GetClass());
if ( slot == (i%10) ) selected = true;
}
else if ( hasitemgesture && hasitemgesture.gest.formerweapon )
{
[dummy, slot] = CPlayer.weapons.LocateWeapon(hasitemgesture.gest.formerweapon.GetClass());
if ( slot == (i%10) ) selected = true;
}
else if ( CPlayer.PendingWeapon && (CPlayer.PendingWeapon != WP_NOCHANGE) )
{
[dummy, slot] = CPlayer.weapons.LocateWeapon(CPlayer.PendingWeapon.GetClass());
if ( slot == (i%10) ) selected = true;
}
else if ( (!CPlayer.PendingWeapon || (CPlayer.PendingWeapon == WP_NOCHANGE)) && CPlayer.ReadyWeapon )
{
[dummy, slot] = CPlayer.weapons.LocateWeapon(CPlayer.ReadyWeapon.GetClass());
if ( slot == (i%10) ) selected = true;
}
if ( selected ) ncolor = mhudfontcol[MCR_BRASS];
else
{
bool hasammo = (i==1);
for ( Inventory inv=CPlayer.mo.Inv; inv; inv=inv.Inv )
{
if ( inv is 'Weapon' ) [dummy, slot] = CPlayer.weapons.LocateWeapon(Weapon(inv).GetClass());
else continue;
if ( slot != (i%10) ) continue;
// CheckAmmo can't be called from ui, so we have to improvise
// for SWWM weapons I made a function for this at least
if ( (inv is 'SWWMWeapon') && SWWMWeapon(inv).ReportHUDAmmo() )
hasammo = true;
else if ( !(inv is 'SWWMWeapon') && ((!Weapon(inv).Ammo1 || (Weapon(inv).Ammo1.Amount > 0) || Weapon(inv).bAMMO_OPTIONAL) || (Weapon(inv).Ammo2 && ((Weapon(inv).Ammo2.Amount > 0) || Weapon(inv).bALT_AMMO_OPTIONAL))) )
hasammo = true;
}
if ( !hasammo ) ncolor = mhudfontcol[MCR_RED];
}
Screen.DrawText(MiniHUDFont,ncolor,xx,yy,String.Format("%d",(i%10)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
int f = hnd.WeaponFlash[i%10];
if ( f && (gametic < f) )
{
double alph = max((f-(gametic+FracTic))/25.,0.)**1.5;
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_FLASH],xx,yy,String.Format("%d",(i%10)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_LegacyRenderStyle,STYLE_Add);
}
}
xx = ss.x-(margin+53);
yy = ss.y-(margin+12);
Screen.DrawTexture(AltAmmoTex[2],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
String str;
bool drewammo = false;
for ( int i=0; i<27; i++ )
{
let a = AmmoSlots[i];
let cur = Ammo(CPlayer.mo.FindInventory(a));
if ( !cur ) continue;
drewammo = true;
yy -= 6;
Screen.DrawTexture(AltAmmoTex[1],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
xx += 2;
int amt, amax;
bool selected = false, used = false;
amt = cur.Amount;
amax = cur.MaxAmount;
if ( (cur is 'SWWMAmmo') && SWWMAmmo(cur).MagAmmoType )
{
let mag = MagAmmo(CPlayer.mo.FindInventory(SWWMAmmo(cur).MagAmmoType));
// theoretically this should never be null, but nevertheless...
if ( mag )
{
amt = amt*mag.ClipSize+mag.Amount;
amax = amax*mag.ClipSize+mag.MaxAmount;
}
else
{
let def = GetDefaultByType(SWWMAmmo(cur).MagAmmoType);
amt = amt*def.ClipSize;
amax = amax*def.ClipSize+def.MaxAmount;
}
}
if ( CPlayer.ReadyWeapon )
{
if ( CPlayer.ReadyWeapon is 'SWWMWeapon' )
{
selected = SWWMWeapon(CPlayer.ReadyWeapon).IsCurrentAmmo(a);
used = SWWMWeapon(CPlayer.ReadyWeapon).UsesAmmo(a);
}
else used = selected = (CPlayer.ReadyWeapon.AmmoType1 == a)||(CPlayer.ReadyWeapon.AmmoType2 == a);
}
int scol = mhudfontcol[selected?MCR_BRASS:MCR_WHITE];
int ncolor = (amt>0)?scol:mhudfontcol[MCR_RED];
int dcnt1 = 2-int(Log10(clamp(amt,1,999)));
int dcnt2 = 2-int(Log10(clamp(amax,1,999)));
for ( int i=0; i<dcnt1; i++ ) Screen.DrawChar(MiniHUDFont,ncolor,xx+20+i*4,yy,0x30,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(used?160:192,0,0,0));
for ( int i=0; i<dcnt2; i++ ) Screen.DrawChar(MiniHUDFont,scol,xx+38+i*4,yy,0x30,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(used?160:192,0,0,0));
str = AmmoNames[i];
Screen.DrawText(MiniHUDFont,scol,xx,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(used?0:96,0,0,0));
str = "/";
Screen.DrawText(MiniHUDFont,scol,xx+32,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(used?80:160,0,0,0));
str = String.Format("%3d",clamp(amt,0,999));
Screen.DrawText(MiniHUDFont,ncolor,xx+20,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(used?0:96,0,0,0));
str = String.Format("%3d",clamp(amax,0,999));
Screen.DrawText(MiniHUDFont,scol,xx+38,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(used?0:96,0,0,0));
let f = AmmoFlash[i];
if ( f && (gametic < f) )
{
double alph = max((f-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%3d",clamp(amt,0,999));
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_FLASH],xx+20,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_LegacyRenderStyle,STYLE_Add);
}
f = AmmoMaxFlash[i];
if ( f && (gametic < f) )
{
double alph = max((f-(gametic+FracTic))/25.,0.)**1.5;
str = String.Format("%3d",clamp(amax,0,999));
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_FLASH],xx+38,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_LegacyRenderStyle,STYLE_Add);
}
xx -= 2;
}
if ( !drewammo )
{
yy -= 6;
Screen.DrawTexture(AltAmmoTex[1],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
String str = "NO AMMO";
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_RED],xx+13,yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,Color(64,0,0,0));
}
yy -= 2;
Screen.DrawTexture(AltAmmoTex[0],false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
// score
String sstr = String.Format("%09d",ScoreInter.GetValue());
xx = ss.x-(margin+46);
yy -= 11;
Screen.DrawTexture(AltScoreTex,false,xx,yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
xx += 9;
yy += 2;
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_BRASS],xx,yy,sstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
}
void Alt_DrawStatus()
{
Screen.DrawTexture(AltStatusTex,false,margin,ss.y-(margin+20),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
String str;
double ht = clamp(AltHealthInter.GetValue(fractic),0,10000);
str = String.Format("%3d",clamp(round(ht),0,999));
double hw = min(ht,100);
double bhw = hw;
int hcolor = MCR_RED;
if ( round(ht) > 500 ) hcolor = MCR_YELLOW;
else if ( round(ht) > 200 ) hcolor = MCR_PURPLE;
else if ( round(ht) > 100 ) hcolor = MCR_CYAN;
if ( isInvulnerable() || CPlayer.mo.FindInventory("InvinciballPower") )
{
Screen.DrawTexture(AltHealthTex[4],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,hw);
hcolor = MCR_WHITE;
}
else
{
Screen.DrawTexture(AltHealthTex[0],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,hw);
if ( ht > 100 )
{
hw = min(ht-100,100);
Screen.DrawTexture(AltHealthTex[1],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,hw);
}
if ( ht > 200 )
{
hw = min(ht-200,300)/3.;
Screen.DrawTexture(AltHealthTex[2],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,hw);
}
if ( ht > 500 )
{
hw = min(ht-500,500)/5.;
Screen.DrawTexture(AltHealthTex[3],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,hw);
}
}
if ( CPlayer.mo.FindInventory("DivineSpriteEffect") )
{
double falph = clamp((ht-1000)/6000.,0.,1.);
Screen.DrawTexture(AltHealthTex[5],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,falph,DTA_LegacyRenderStyle,STYLE_Add);
String tst;
double alph = .1;
int trl = 9;
for ( double alph = .1; alph <= .5; alph += .1 )
{
tst = "AAA";
SWWMUtility.ObscureText(tst,(gametic-trl)/3,true);
trl--;
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_WHITE],margin+106,ss.y-(margin+18),tst,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,falph*alph,DTA_LegacyRenderStyle,STYLE_Add);
}
Screen.DrawText(MiniHUDFont,mhudfontcol[hcolor],margin+106,ss.y-(margin+18),String.Format("%3d",clamp(round(ht),0,999)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,1.-falph);
}
else
{
Screen.DrawText(MiniHUDFont,mhudfontcol[hcolor],margin+106,ss.y-(margin+18),String.Format("%3d",clamp(round(ht),0,999)),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
int f = HealthFlash;
if ( f && (gametic < f) )
{
double alph = max((f-(gametic+FracTic))/25.,0.)**1.5;
Screen.DrawTexture(AltHealthTex[7],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,bhw,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_FLASH],margin+106,ss.y-(margin+18),str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,alph);
}
if ( (CPlayer.health > 0) && (CPlayer.health <= 25) && (PulsePhase <= 15) )
{
double alph = clamp(sin((PulsePhase-FracTic)*12.),0.,1.);
Screen.DrawTexture(AltHealthTex[6],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,hw,DTA_Alpha,alph);
Screen.DrawText(MiniHUDFont,mhudfontcol[MCR_REDFLASH],margin+106,ss.y-(margin+18),str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alph);
}
ht = clamp(LagHealthInter.GetValue(fractic),0,1000);
double hwl = min(ht,100);
if ( hwl > bhw )
Screen.DrawTexture(AltHealthTex[8],false,margin+2,ss.y-(margin+18),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowLeftF,bhw,DTA_WindowRightF,hwl);
}
double ft = clamp(AltFuelInter.GetValue(fractic),0,120);
Screen.DrawTexture(AltFuelTex[swwm_superfuel],false,margin+2,ss.y-(margin+7),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,ft);
let d = Demolitionist(CPlayer.mo);
bool blink = (!d || (d.dashfuel > 20) || ((gametic%10) < 5));
double dt = clamp(AltDashInter.GetValue(fractic),0,120);
Screen.DrawTexture(AltDashTex,false,margin+2,ss.y-(margin+4),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_WindowRightF,dt,DTA_ColorOverlay,Color(blink?0:96,0,0,0));
}
}
// fractic-compatible interpolators, with double value
Class SmoothLinearValueInterpolator
{
private double val, oldval, diff;
static SmoothLinearValueInterpolator Create( double val, double diff )
{
let v = new("SmoothLinearValueInterpolator");
v.oldval = v.val = val;
v.diff = diff;
return v;
}
void Reset( double newval )
{
oldval = val = newval;
}
void Update( double newval )
{
oldval = val;
if ( abs(newval-val) < diff ) val = newval;
else if ( val > newval ) val = max(newval,val-diff);
else val = min(newval,val+diff);
}
double GetValue( double fractic = 1. )
{
return SWWMUtility.Lerp(oldval,val,fractic);
}
}
Class SmoothDynamicValueInterpolator
{
private double val, oldval, factor, mindiff, maxdiff;
static SmoothDynamicValueInterpolator Create( double val, double factor, double mindiff, double maxdiff )
{
let v = new("SmoothDynamicValueInterpolator");
v.oldval = v.val = val;
v.factor = factor;
v.mindiff = mindiff;
v.maxdiff = maxdiff;
return v;
}
void Reset( double newval )
{
oldval = val = newval;
}
void Update( double newval )
{
oldval = val;
if ( abs(newval-val) < mindiff ) val = newval;
else
{
double diff = min(abs(newval-val)*factor,maxdiff);
if ( val > newval ) val = max(newval,val-diff);
else val = min(newval,val+diff);
}
}
double GetValue( double fractic = 1. )
{
return SWWMUtility.Lerp(oldval,val,fractic);
}
}

View file

@ -119,6 +119,7 @@ Class SWWMStatusBar : BaseStatusBar
ScoreInter.Reset(SWWMCredits.Get(CPlayer));
FuelInter.Reset((CPlayer.mo is 'Demolitionist')?int(Demolitionist(CPlayer.mo).dashfuel):0);
DashInter.Reset((CPlayer.mo is 'Demolitionist')?int((40-Demolitionist(CPlayer.mo).dashcooldown)*3.):0);
Alt_FlushInterpolators();
if ( level.maptime <= 1 )
{
// flush ALL messages
@ -164,6 +165,19 @@ Class SWWMStatusBar : BaseStatusBar
}
return true;
}
else if ( msg.Left(11) ~== "swwmkeyget." )
{
String kname = msg.Mid(11);
Class<Key> k = kname;
if ( k )
{
let kg = new("KeyGet");
kg.got = k;
kg.flashtime = gametic+25;
keyflash.Push(kg);
}
return true;
}
SWWMDirectMessage m, m2;
// more hack
if ( msg ~== "swwmultdoom2map20dlg" )
@ -938,8 +952,8 @@ Class SWWMStatusBar : BaseStatusBar
void TickInterpolators()
{
HealthInter.Update(CPlayer.health);
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
ScoreInter.Update(SWWMCredits.Get(CPlayer));
Alt_UpdateInterpolators();
}
override void Tick()
@ -989,6 +1003,7 @@ Class SWWMStatusBar : BaseStatusBar
if ( abs(minimapzoom-desiredzoom) <= .01 )
minimapzoom = desiredzoom;
}
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
let cam = players[consoleplayer].camera;
Vector3 viewvec = (cos(viewrot.x)*cos(viewrot.y),sin(viewrot.x)*cos(viewrot.y),sin(-viewrot.y));
int sz;
@ -1142,6 +1157,7 @@ Class SWWMStatusBar : BaseStatusBar
}
}
lastwep = CPlayer.PendingWeapon;
Alt_Tick();
// make sure vanilla nametags don't display
DetachMessageID(0x5745504e); // WEPN
DetachMessageID(0x53494e56); // SINV
@ -1242,6 +1258,7 @@ Class SWWMStatusBar : BaseStatusBar
FuelInter = DynamicValueInterpolator.Create(120,.5,1,100);
DashInter = DynamicValueInterpolator.Create(120,.5,1,40);
hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
Alt_Init();
PrevFrame = MSTimeF();
}
@ -2184,14 +2201,18 @@ Class SWWMStatusBar : BaseStatusBar
return StringTable.Localize("$SWWM_PLACE"..val);
}
private void DrawScore()
private void DrawTopStuff( bool minimaponly = false )
{
String sstr = String.Format("%09d",ScoreInter.GetValue());
int xx = 73;
Screen.DrawTexture(ScoreTex,false,ss.x-(margin+xx),margin,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
xx -= 15;
Screen.DrawText(mSmallFont,Font.CR_FIRE,ss.x-(margin+xx),margin+2,sstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
int yy = margin+19;
int xx, yy = margin;
if ( !minimaponly )
{
String sstr = String.Format("%09d",ScoreInter.GetValue());
xx = 73;
Screen.DrawTexture(ScoreTex,false,ss.x-(margin+xx),margin,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
xx -= 15;
Screen.DrawText(mSmallFont,Font.CR_FIRE,ss.x-(margin+xx),margin+2,sstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy = margin+19;
}
// obviously, don't draw the minimap if the automap is open
if ( !automapactive && swwm_mm_enable )
{
@ -2218,6 +2239,7 @@ Class SWWMStatusBar : BaseStatusBar
Screen.ClearClipRect();
yy += ((HALFMAPSIZE+2)*2)+3;
}
if ( minimaponly ) return;
// draw stats and timer when automap is open
int fstats = swwm_forcestats;
if ( automapactive || (fstats > 0) )
@ -2384,11 +2406,11 @@ Class SWWMStatusBar : BaseStatusBar
return true;
}
private void DrawInventory()
private void DrawInventory( int invy = 58 )
{
// active items (armor / powerups)
double xx = margin+2;
double yy = ss.y-(margin+58);
double yy = ss.y-(margin+invy);
if ( CPlayer.mo.InvSel && !isInventoryBarVisible() ) yy -= 34;
bool drewarmor = false;
for ( Inventory i=CPlayer.mo.Inv; i; i=i.Inv )
@ -2398,7 +2420,7 @@ Class SWWMStatusBar : BaseStatusBar
yy -= 34;
drewarmor = true;
}
yy = ss.y-(margin+58);
yy = ss.y-(margin+invy);
if ( drewarmor ) xx += 40;
else if ( CPlayer.mo.InvSel && !isInventoryBarVisible() ) yy -= 34;
for ( Inventory i=CPlayer.mo.Inv; i; i=i.Inv )
@ -2452,11 +2474,11 @@ Class SWWMStatusBar : BaseStatusBar
DrawInvIcon(next[1],xx+70,yy+2,1./3.);
return;
}
Screen.DrawTexture(InventoryTex,false,margin,ss.y-(margin+60),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
DrawInvIcon(CPlayer.mo.InvSel,margin+2,ss.y-(margin+58));
Screen.DrawTexture(InventoryTex,false,margin,ss.y-(margin+invy+2),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
DrawInvIcon(CPlayer.mo.InvSel,margin+2,ss.y-(margin+invy));
}
private void DrawWeapon()
private void DrawWeapons()
{
if ( CPlayer.ReadyWeapon is 'SWWMWeapon' ) SWWMWeapon(CPlayer.ReadyWeapon).DrawWeapon(FracTic,ss.x-margin,ss.y-(margin+28),hs,ss);
else if ( CPlayer.ReadyWeapon )
@ -2894,12 +2916,20 @@ Class SWWMStatusBar : BaseStatusBar
else
{
DrawTarget();
if ( state != HUD_AltHUD ) // proper support for an alt hud will come someday
if ( swwm_althud )
{
DrawScore();
DrawTopStuff();
DrawInventory();
DrawStatus();
DrawWeapon();
DrawWeapons();
}
else
{
DrawTopStuff(true);
Alt_DrawTopStuff();
DrawInventory(54);
Alt_DrawStatus();
Alt_DrawWeapons();
}
if ( hnd ) hnd.DrawBossBar(self);
DrawPickups();

View file

@ -864,7 +864,7 @@ Class SilverBullets : MagAmmo
Inventory.Icon "graphics/HUD/Icons/A_SilverBulletBullet.png";
MagAmmo.ParentAmmo "SilverBulletAmmo";
MagAmmo.ClipSize 5;
Inventory.MaxAmount 8;
Inventory.MaxAmount 5;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
@ -916,7 +916,7 @@ Class SilverBullets2 : MagAmmo
Inventory.Icon "graphics/HUD/Icons/A_SilverBulletBullet2.png";
MagAmmo.ParentAmmo "SilverBulletAmmo2";
MagAmmo.ClipSize 5;
Inventory.MaxAmount 8;
Inventory.MaxAmount 5;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 4;
@ -1005,7 +1005,7 @@ Class CandyGunBullets : MagAmmo
Inventory.Icon "graphics/HUD/Icons/A_CandyBullet.png";
MagAmmo.ParentAmmo "CandyGunAmmo";
MagAmmo.ClipSize 7;
Inventory.MaxAmount 10;
Inventory.MaxAmount 7;
+FLOATBOB;
FloatBobStrength 0.25;
Radius 2;

View file

@ -2852,6 +2852,9 @@ Class Demolitionist : PlayerPawn
mystats.gotyorick = true;
SWWMHandler.AddOneliner("skullget",2);
}
// notify key obtained to flash icon
if ( item is 'Key' )
Console.MidPrint(null,"swwmkeyget."..item.GetClassName());
}
override bool UseInventory( Inventory item )
{

View file

@ -379,7 +379,7 @@ Class SWWMUtility
return str;
}
static clearscope void ObscureText( out String str, int seed )
static clearscope void ObscureText( out String str, int seed, bool alnum = false )
{
int len = str.CodePointCount();
String newstr = "";
@ -390,6 +390,12 @@ Class SWWMUtility
[ch, pos] = str.GetNextCodePoint(pos);
if ( (ch == 0x20) || (ch == 0x09) || (ch == 0x0A) )
newstr.AppendCharacter(ch);
else if ( alnum )
{
int sd = abs(seed%36);
if ( sd >= 10 ) sd += 7;
newstr.AppendCharacter(sd+48);
}
else newstr.AppendCharacter((abs(seed)%95)+32);
}
str = newstr;

View file

@ -411,6 +411,11 @@ Class SWWMWeapon : Weapon abstract
{
return (AmmoType1&&(kind is AmmoType1))||(AmmoType2&&(kind is AmmoType2));
}
// for the alt hud, this is meant for weapons with switchable types
virtual clearscope bool IsCurrentAmmo( Class<Ammo> kind )
{
return false;
}
override void ModifyDropAmount( int dropamount )
{
self.dropamount = dropamount;

View file

@ -241,6 +241,11 @@ Class Hellblazer : SWWMWeapon
return false;
}
override bool IsCurrentAmmo( Class<Ammo> kind )
{
return (kind is nextammo);
}
action void A_GlassOverlay( StateLabel g )
{
player.SetPSprite(PSP_WEAPON+1,invoker.FindState(g));

View file

@ -180,6 +180,11 @@ Class Spreadgun : SWWMWeapon
return false;
}
override bool IsCurrentAmmo( Class<Ammo> kind )
{
return (kind is nextammo);
}
action void A_SelectUnloadState()
{
static const Class<Ammo> types[] = {"RedShell","GreenShell","WhiteShell","BlueShell","BlackShell","PurpleShell","GoldShell"};

View file

@ -268,6 +268,11 @@ Class SilverBullet : SWWMWeapon
if ( (Ammo1.Amount <= 0) && (Ammo2.Amount <= 0) && (Owner.CountInv("SilverBullets") <= 0) && (Owner.CountInv("SilverBullets2") <= 0) ) return false;
return true;
}
override bool IsCurrentAmmo( Class<Ammo> kind )
{
if ( fcbselected ) return (kind is AmmoType2);
return (kind is AmmoType1);
}
override bool CheckAmmo( int firemode, bool autoswitch, bool requireammo, int ammocount )
{
if ( sv_infiniteammo || Owner.FindInventory('PowerInfiniteAmmo',true) ) return true;