Overhaul the "swap weapon" prompt display.

This commit is contained in:
Mari the Deer 2025-01-15 16:49:55 +01:00
commit 67d8235459
7 changed files with 240 additions and 12 deletions

View file

@ -732,7 +732,7 @@ D_SENTRYEMPTY = "Sentry has run our of ammo.";
D_SENTRYFAR = "You're too far to recall the sentry.";
D_ANDIRA = "\cjShe knows where you are...\c-";
SWWM_YNYKRONREADY = "The Ynykron Artifact is ready for firing.";
SWWM_SWAPWEAPON = "\cjPress \cfUse\cj to swap \cf%s\cj for \cf%s\cj.\c-";
SWWM_SWAPWEAPON = "\cjPress \cfUse\cj to swap\n\cf%s\cj for \cf%s\c-";
SWWM_TODOWEAPON = "\cjThe \cf%s\cj is not yet implemented.\c-";
SWWM_TITLEPRESENTSA = "UnSX Team";
SWWM_TITLEPRESENTSB = "presents";

View file

@ -603,7 +603,7 @@ D_SPRITE = "El Sprite Divino ha soplado su último aliento.";
D_TETHERFAIL = "El vínculo del Enlace de Seguridad fue obstruído.";
D_ANDIRA = "\cjSabe donde estás...\c-";
SWWM_YNYKRONREADY = "El Artefacto Ynykron está listo para disparar.";
SWWM_SWAPWEAPON = "\cjPulsa \cfUsar\cj para cambiar \cf%s\cj por \cf%s\cj.\c-";
SWWM_SWAPWEAPON = "\cjPulsa \cfUsar\cj para cambiar\n\cf%s\cj por \cf%s\c-";
SWWM_TODOWEAPON = "\cjEl \cf%s\cj aun no está implementado.\c-";
SWWM_TODOWEAPON_FEM = "\cjLa \cf%s\cj aun no está implementada.\c-";
SWWM_TITLEPRESENTSB = "presenta";

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r1165 \cu(Wed Jan 15 13:48:46 CET 2025)\c-";
SWWM_SHORTVER="\cw1.3pre r1165 \cu(2025-01-15 13:48:46)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r1166 \cu(Wed Jan 15 16:49:55 CET 2025)\c-";
SWWM_SHORTVER="\cw1.3pre r1166 \cu(2025-01-15 16:49:55)\c-";

View file

@ -136,6 +136,31 @@ extend Class SWWMHandler
}
}
}
else if ( e.Name.Left(15) ~== "swwmwpnswaptip." )
{
let bar = SWWMStatusBar(StatusBar);
if ( !bar ) return;
// network IDs finally becoming useful here
uint ida = e.Name.Mid(15,8).ToInt(16);
uint idb = e.Name.Mid(23,8).ToInt(16);
let wa = Inventory(Object.GetNetworkEntity(ida));
let wb = Inventory(Object.GetNetworkEntity(idb));
if ( !wa || !wb ) return;
if ( e.Args[0] )
{
// force to expire
if ( bar.cstip ) bar.cstip.Expire(wa,wb);
return;
}
if ( bar.cstip )
{
bar.cstip.Poke(wa,wb);
return;
}
let tt = new("SWWMWeaponSwapTip").Init(wa,wb);
bar.cstip = tt;
bar.AttachMessage(tt,-2911);
}
else if ( e.Name.Left(12) ~== "swwmnametag." )
{
let bar = SWWMStatusBar(StatusBar);

View file

@ -142,6 +142,7 @@ Class SWWMStatusBar : BaseStatusBar
int puzzlecnt, realpuzzlecnt;
SWWMWeaponTooltip ctip;
SWWMWeaponSwapTip cstip;
double mm_zoom;
transient ThinkerIterator mi; // for map markers

View file

@ -225,6 +225,202 @@ Class SWWMAchievementNotification : HUDMessageBase
}
}
// weapon swap prompt
Class SWWMWeaponSwapTip : HUDMessageBase
{
Inventory wa, wb;
SWWMWeapon swa, swb;
bool duala, dualb;
String wpna, wpnb, txt;
transient BrokenLines l;
double tics, holdtics, fadeintics, fadeouttics;
TextureID icoa, icob;
Font mSmallFont;
// just code deduplication here
private void UpdateMe( Inventory fromweapon, Inventory toweapon )
{
wa = fromweapon;
swa = SWWMWeapon(wa);
if ( !swa ) ThrowAbortException("swap from (%s) is not SWWMWeapon",wa?wa.GetClassName():'Null');
// are we swapping from a dual weapon?
if ( swa.SisterWeapon && (swa.Amount>1) )
{
wpna = swa.SisterWeapon.GetTag();
icoa = GetIcon(swa.SisterWeapon);
duala = true;
}
else
{
wpna = swa.GetTag();
icoa = GetIcon(swa);
duala = false;
}
wb = toweapon;
// are we swapping to a dual weapon?
if ( wb is 'SWWMDualWeaponGiver' )
{
swb = SWWMDualWeaponGiver(wb).giveme[0];
wpnb = wb.GetTag();
icob = GetIcon(swb);
dualb = true;
}
else if ( wb is 'SWWMWeapon' )
{
swb = SWWMWeapon(wb);
wpnb = swb.GetTag();
icob = GetIcon(swb);
dualb = false;
}
else ThrowAbortException("swap to (%s) is not SWWMWeapon or SWWMDualWeaponGiver",wb?wb.GetClassName():'Null');
txt = String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),wpna,wpnb);
if ( l ) l.Destroy();
}
private TextureID GetIcon( Weapon w )
{
let [ico, applyScale] = StatusBar.GetInventoryIcon(w,StatusBar.DI_SKIPALTICON|StatusBar.DI_SKIPREADY);
return ico;
}
SWWMWeaponSwapTip Init( Inventory fromweapon, Inventory toweapon )
{
UpdateMe(fromweapon,toweapon);
holdtics = 50;
fadeintics = 5;
fadeouttics = 15;
tics = 0;
mSmallFont = Font.GetFont('TewiFont');
return self;
}
// used by weapons when an existing tip is already there
void Poke( Inventory fromweapon, Inventory toweapon )
{
// update icons and text if different weapons
if ( (fromweapon != wa) || (toweapon != wb) )
UpdateMe(fromweapon,toweapon);
// invert the fade out into a fade-in
// otherwise just wind the tics back to right after fade-in
if ( tics > (fadeintics+holdtics) )
tics = fadeintics-(tics-(fadeintics+holdtics))/(fadeouttics/fadeintics);
else if ( tics > fadeintics )
tics = fadeintics;
}
// used by weapons when the swap has already happened
void Expire( Inventory fromweapon, Inventory toweapon )
{
// just forces a fade out
if ( (fromweapon == wa) && (toweapon == wb) )
tics = max(tics,fadeintics+holdtics);
}
override bool Tick()
{
tics++;
return (tics > holdtics+fadeintics+fadeouttics);
}
override void Draw( int bottom, int visibility )
{
if ( tics <= 0 ) return;
double ymargin;
double hs;
Vector2 ss;
if ( SWWMStatusBar(StatusBar) )
{
ymargin = SWWMStatusBar(StatusBar).ymargin0;
hs = SWWMStatusBar(StatusBar).hs0;
ss = SWWMStatusBar(StatusBar).ss0;
}
else
{
ymargin = clamp(swwm_hudmargin,0,10);
hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/360.)),1.);
ss = (Screen.GetWidth()/hs,Screen.GetHeight()/hs);
}
double fractic = System.GetTimeFrac();
double ftics = tics+fractic;
double alpha = (ftics<fadeintics)?(ftics/fadeintics):(ftics<(fadeintics+holdtics))?1.:(1.-(ftics-(fadeintics+holdtics))/fadeouttics);
if ( !l ) l = mSmallFont.BreakLines(txt,600);
int txtw = 0;
for ( int i=0; i<l.Count(); i++ )
{
let lw = mSmallFont.StringWidth(l.StringAt(i));
if ( lw > txtw ) txtw = lw;
}
int icow = 16;
int icoh = mSmallFont.GetHeight()*2;
if ( icoa.IsValid() )
{
Vector2 sz = TexMan.GetScaledSize(icoa)*.125;
icow += int(sz.x)+(duala?12:4);
icoh = int(sz.y)+(duala?12:4);
}
else icow += mSmallFont.StringWidth(wpna);
if ( icob.IsValid() )
{
Vector2 sz = TexMan.GetScaledSize(icob)*.125;
icow += int(sz.x)+(dualb?12:4);
icoh = max(icoh,int(sz.y)+(dualb?12:4));
}
else
{
icow += mSmallFont.StringWidth(wpnb);
icoh = max(icoh,mSmallFont.GetHeight());
}
int w = max(txtw,icow);
int h = icoh+4+mSmallFont.GetHeight()*l.Count();
Vector2 pos = (int(ss.x/2),ss.y-(ymargin+80+h));
Screen.Dim("Black",.5*alpha,int((pos.x-(w+4)/2)*hs),int((pos.y-2)*hs),int((w+4)*hs),int((h+4)*hs));
// Left Icon
double x = pos.x-(icow/2);
if ( icoa.IsValid() )
{
Vector2 sz = TexMan.GetScaledSize(icoa)*.125;
if ( duala )
{
x += sz.x/2+6;
Screen.DrawTexture(icoa,false,(x-4)*hs,((pos.y+icoh/2)-4)*hs,DTA_ScaleX,.125*hs,DTA_ScaleY,.125*hs,DTA_Alpha,alpha,DTA_CenterOffset,true);
Screen.DrawTexture(icoa,false,(x+4)*hs,((pos.y+icoh/2)+4)*hs,DTA_ScaleX,.125*hs,DTA_ScaleY,.125*hs,DTA_Alpha,alpha,DTA_CenterOffset,true);
x += sz.x/2+6;
}
else
{
x += sz.x/2+2;
Screen.DrawTexture(icoa,false,x*hs,(pos.y+icoh/2)*hs,DTA_ScaleX,.125*hs,DTA_ScaleY,.125*hs,DTA_Alpha,alpha,DTA_CenterOffset,true);
x += sz.x/2+2;
}
}
// Swap Arrow
String arr = "→";
Screen.DrawText(mSmallFont,Font.CR_GREEN,x+(16-mSmallFont.StringWidth(arr))/2,pos.y+(icoh/2-mSmallFont.GetHeight()),arr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
arr = "←";
Screen.DrawText(mSmallFont,Font.CR_GREEN,x+(16-mSmallFont.StringWidth(arr))/2,pos.y+(icoh/2),arr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
x += 16;
// Right Icon
if ( icob.IsValid() )
{
Vector2 sz = TexMan.GetScaledSize(icob)*.125;
if ( dualb )
{
x += sz.x/2+6;
Screen.DrawTexture(icob,false,(x-4)*hs,((pos.y+icoh/2)-4)*hs,DTA_ScaleX,.125*hs,DTA_ScaleY,.125*hs,DTA_Alpha,alpha,DTA_CenterOffset,true);
Screen.DrawTexture(icob,false,(x+4)*hs,((pos.y+icoh/2)+4)*hs,DTA_ScaleX,.125*hs,DTA_ScaleY,.125*hs,DTA_Alpha,alpha,DTA_CenterOffset,true);
}
else
{
x += sz.x/2+2;
Screen.DrawTexture(icob,false,x*hs,(pos.y+icoh/2)*hs,DTA_ScaleX,.125*hs,DTA_ScaleY,.125*hs,DTA_Alpha,alpha,DTA_CenterOffset,true);
}
}
// Swap Message
for ( int i=0; i<l.Count(); i++ )
Screen.DrawText(mSmallFont,Font.CR_WHITE,pos.x-mSmallFont.StringWidth(l.StringAt(i))/2,pos.y+icoh+4+i*mSmallFont.GetHeight(),l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
}
}
// weapon tooltips
Class SWWMWeaponTooltip : HUDMessageBase
{

View file

@ -93,10 +93,9 @@ Class SWWMWeapon : Weapon abstract
{
if ( toucher.CheckLocalView() )
{
// use sisterweapon tag for dual wield (slot 2 weapons)
if ( sw.SisterWeapon && (sw.Amount > 1) )
Console.MidPrint(SmallFont,String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),sw.SisterWeapon.GetTag(),GetTag()));
else Console.MidPrint(SmallFont,String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),sw.GetTag(),GetTag()));
uint ida = sw.GetNetworkID();
uint idb = GetNetworkID();
EventHandler.SendInterfaceEvent(consoleplayer,String.Format("swwmwpnswaptip.%08x%08x",ida,idb));
}
return;
}
@ -165,6 +164,10 @@ Class SWWMWeapon : Weapon abstract
d.bSPECIAL = false;
d.DropTime = 30;
}
// notify the HUD tip (if any) to expire
uint ida = sw.GetNetworkID();
uint idb = GetNetworkID();
EventHandler.SendInterfaceEvent(consoleplayer,String.Format("swwmwpnswaptip.%08x%08x",ida,idb),1);
}
bUsePickup = true;
bSWAPPEDTO = true;
@ -799,10 +802,9 @@ Class SWWMDualWeaponGiver : Inventory
{
if ( toucher.CheckLocalView() )
{
// use sisterweapon tag for dual wield (slot 2 weapons)
if ( sw.SisterWeapon && (sw.Amount > 1) )
Console.MidPrint(SmallFont,String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),sw.SisterWeapon.GetTag(),GetTag()));
else Console.MidPrint(SmallFont,String.Format(StringTable.Localize("$SWWM_SWAPWEAPON"),sw.GetTag(),GetTag()));
uint ida = sw.GetNetworkID();
uint idb = GetNetworkID();
EventHandler.SendInterfaceEvent(consoleplayer,String.Format("swwmwpnswaptip.%08x%08x",ida,idb));
}
return;
}
@ -863,6 +865,10 @@ Class SWWMDualWeaponGiver : Inventory
user.player.ReadyWeapon = null;
user.player.PendingWeapon = WP_NOCHANGE;
}
// notify the HUD tip (if any) to expire
uint ida = sw.GetNetworkID();
uint idb = GetNetworkID();
EventHandler.SendInterfaceEvent(consoleplayer,String.Format("swwmwpnswaptip.%08x%08x",ida,idb),1);
}
bUsePickup = true;
Touch(user);