22using SwiftlyS2 . Shared ;
33using SwiftlyS2 . Shared . Menus ;
44using SwiftlyS2 . Core . Natives ;
5+ using SwiftlyS2 . Core . Menus . OptionsBase ;
56using SwiftlyS2 . Shared . Players ;
67using SwiftlyS2 . Shared . SchemaDefinitions ;
78
@@ -41,6 +42,11 @@ internal sealed class MenuAPI : IMenuAPI, IDisposable
4142 /// </summary>
4243 public IMenuBuilderAPI ? Builder { get ; init ; }
4344
45+ /// <summary>
46+ /// Gets or sets the default comment text to use when a menu option's Comment is not set.
47+ /// </summary>
48+ public string DefaultComment { get ; set ; } = $ "Powered by <font color='#ff3c00'>❤️</font> { HtmlGradient . GenerateGradientText ( "SwiftlyS2" , "#ffffff" , "#96d5ff" ) } ";
49+
4450 /// <summary>
4551 /// Gets or sets an object that contains data about this menu.
4652 /// </summary>
@@ -252,9 +258,10 @@ private void OnRender()
252258
253259 foreach ( var option in options )
254260 {
255- if ( option is OptionsBase . MenuOptionBase optionBase )
261+ if ( option is MenuOptionBase optionBase )
256262 {
257263 optionBase . UpdateDynamicText ( now ) ;
264+ optionBase . UpdateCustomAnimations ( now ) ;
258265 }
259266 }
260267
@@ -418,22 +425,47 @@ private string BuildMenuHtml( IPlayer player, IReadOnlyList<IMenuOption> visible
418425 option . GetDisplayText ( player , 0 )
419426 ) ) ) ;
420427
428+ var currentOption = visibleOptions . Count > 0 ? visibleOptions [ arrowPosition ] : null ;
429+ var optionBase = currentOption as MenuOptionBase ;
430+
431+ var comment = ! string . IsNullOrWhiteSpace ( optionBase ? . Comment )
432+ ? string . Concat (
433+ "<br>" ,
434+ guideLine ,
435+ "<br>" ,
436+ $ "<font class='fontSize-s'>{ optionBase . Comment } </font><br>"
437+ )
438+ : string . Concat (
439+ "<br>" ,
440+ guideLine ,
441+ "<br>" ,
442+ $ "<font class='fontSize-s'>{ DefaultComment } </font><br>"
443+ ) ;
444+
445+ var claimInfo = optionBase ? . InputClaimInfo ?? MenuInputClaimInfo . Empty ;
446+
421447 var footerSection = Configuration . HideFooter ? string . Empty :
422448 core . MenusAPI . Configuration . InputMode switch {
423449 "wasd" => string . Concat (
424- "<br>" , guideLine , "<br>" ,
425450 "<font class='fontSize-s' color='#FFFFFF'>" ,
426451 $ "<font color='{ footerColor } '>Move:</font> W/S",
427- $ " | <font color='{ footerColor } '>Use:</font> D",
428- Configuration . DisableExit ? string . Empty : $ " | <font color='{ footerColor } '>Exit:</font> A",
452+ claimInfo . ClaimsUse
453+ ? $ " | <font color='{ footerColor } '>{ claimInfo . UseLabel ?? "Use" } :</font> D"
454+ : $ " | <font color='{ footerColor } '>Use:</font> D",
455+ claimInfo . ClaimsExit
456+ ? $ " | <font color='{ footerColor } '>{ claimInfo . ExitLabel ?? "Exit" } :</font> A"
457+ : ( Configuration . DisableExit ? string . Empty : $ " | <font color='{ footerColor } '>Exit:</font> A") ,
429458 "</font>"
430459 ) ,
431460 _ => string . Concat (
432- "<br>" , guideLine , "<br>" ,
433461 "<font class='fontSize-s' color='#FFFFFF'>" ,
434462 $ "<font color='{ footerColor } '>Move:</font> { KeybindOverrides . Move ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsScroll . ToUpper ( ) } /{ KeybindOverrides . MoveBack ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsScrollBack . ToUpper ( ) } ",
435- $ " | <font color='{ footerColor } '>Use:</font> { KeybindOverrides . Select ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsUse . ToUpper ( ) } ",
436- Configuration . DisableExit ? string . Empty : $ " | <font color='{ footerColor } '>Exit:</font> { KeybindOverrides . Exit ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsExit . ToUpper ( ) } ",
463+ claimInfo . ClaimsUse
464+ ? $ " | <font color='{ footerColor } '>{ claimInfo . UseLabel ?? "Use" } :</font> { KeybindOverrides . Select ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsUse . ToUpper ( ) } "
465+ : $ " | <font color='{ footerColor } '>Use:</font> { KeybindOverrides . Select ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsUse . ToUpper ( ) } ",
466+ claimInfo . ClaimsExit
467+ ? $ " | <font color='{ footerColor } '>{ claimInfo . ExitLabel ?? "Exit" } :</font> { KeybindOverrides . Exit ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsExit . ToUpper ( ) } "
468+ : ( Configuration . DisableExit ? string . Empty : $ " | <font color='{ footerColor } '>Exit:</font> { KeybindOverrides . Exit ? . ToString ( ) ?? core . MenusAPI . Configuration . ButtonsExit . ToUpper ( ) } ") ,
437469 "</font>"
438470 )
439471 } ;
@@ -443,6 +475,7 @@ private string BuildMenuHtml( IPlayer player, IReadOnlyList<IMenuOption> visible
443475 "<font color='#FFFFFF' class='fontSize-sm'>" ,
444476 menuItems ,
445477 "</font>" ,
478+ comment ,
446479 footerSection
447480 ) ;
448481 }
@@ -499,7 +532,7 @@ public void ShowForPlayer( IPlayer player )
499532
500533 lock ( optionsLock )
501534 {
502- options . OfType < OptionsBase . MenuOptionBase > ( ) . ToList ( ) . ForEach ( option => option . ResumeTextAnimation ( ) ) ;
535+ options . OfType < MenuOptionBase > ( ) . ToList ( ) . ForEach ( option => option . ResumeTextAnimation ( ) ) ;
503536 }
504537 }
505538 }
@@ -556,7 +589,7 @@ public void HideForPlayer( IPlayer player )
556589
557590 lock ( optionsLock )
558591 {
559- options . OfType < OptionsBase . MenuOptionBase > ( ) . ToList ( ) . ForEach ( option => option . PauseTextAnimation ( ) ) ;
592+ options . OfType < MenuOptionBase > ( ) . ToList ( ) . ForEach ( option => option . PauseTextAnimation ( ) ) ;
560593 }
561594 }
562595 }
@@ -588,7 +621,7 @@ public void AddOption( IMenuOption option )
588621 // {
589622 // submenuOption.SubmenuRequested += OnSubmenuRequested;
590623 // }
591- if ( option is OptionsBase . MenuOptionBase baseOption )
624+ if ( option is MenuOptionBase baseOption )
592625 {
593626 baseOption . Menu = this ;
594627 }
@@ -667,17 +700,20 @@ public int GetCurrentOptionIndex( IPlayer player )
667700 // return selectedDisplayLine.TryGetValue(player, out var line) ? line : -1;
668701 // }
669702
670- private static void SetFreezeState ( IPlayer player , bool freeze )
703+ private void SetFreezeState ( IPlayer player , bool freeze )
671704 {
672705 if ( ! player . IsValid || player . IsFakeClient || ! ( player . PlayerPawn ? . IsValid ?? false ) )
673706 {
674707 return ;
675708 }
676709
677- var moveType = freeze ? MoveType_t . MOVETYPE_NONE : MoveType_t . MOVETYPE_WALK ;
678- player . PlayerPawn . MoveType = moveType ;
679- player . PlayerPawn . ActualMoveType = moveType ;
680- player . PlayerPawn . MoveTypeUpdated ( ) ;
710+ core . Scheduler . NextTick ( ( ) =>
711+ {
712+ var moveType = freeze ? MoveType_t . MOVETYPE_NONE : MoveType_t . MOVETYPE_WALK ;
713+ player . PlayerPawn . MoveType = moveType ;
714+ player . PlayerPawn . ActualMoveType = moveType ;
715+ player . PlayerPawn . MoveTypeUpdated ( ) ;
716+ } ) ;
681717 }
682718
683719 // private ValueTask OnOptionClick( object? sender, MenuOptionClickEventArgs args )
0 commit comments