ServUO Version
Publish Unknown
Ultima Expansion
None
Hello guys im trying to make a list of all players then order it by the Value of 2 attachments together, higher at the top, leaderboard like


i saw this method somewhere (thanks vorspire) but its giving me 2 errors;


CS1061: Line 88: 'Server.Mobiles.PlayerMobile' does not contain a definition for 'OrderByDescending' and no extensio
n method 'OrderByDescending' accepting a first argument of type 'Server.Mobiles.PlayerMobile' could be found (are you mi
ssing a using directive or an assembly reference?)
CS1061: Line 88: 'Server.Mobiles.PlayerMobile' does not contain a definition for 'OrderBy' and no extension method '
OrderBy' accepting a first argument of type 'Server.Mobiles.PlayerMobile' could be found (are you missing a using direct

ive or an assembly reference?)


Im using Runuo 2.2 (yeah i should upgrade i know)

i added
C#:
using System.Linq;


and this


C#:
    public enum OrderBy
{
    None,
    level
}

C#:
     AddBackground (18, 0 ,512,478,2620);   
         AddAlphaRegion (18,0,498,463);
     
        AddLabel(101, 8, 1952, "Top exp");
 
        //AddLabel(440, 7, 1952, "Minimize");
        AddButton(492, 7, 2710, 2711, 2, GumpButtonType.Reply, 0);

        int page = 0, cpage = 1;
      var players = World.Mobiles.Values.OfType<PlayerMobile>(); // filter only PlayerMobiles
      players = players.Take( 10 ); // take the first 10
     
  int yOffset = 40;
 
   var orderBy = OrderBy.level; //   Sort by the int level?
var desc = Utility.RandomBool( ); // Random ascending or descending

int level = 0;
int levelm = 0;
foreach( var pm1 in players ) // iterate the results
{
XMLPlayerLevelAtt xml = XmlAttach.FindAttachment( pm1, typeof( XMLPlayerLevelAtt ) ) as XMLPlayerLevelAtt; //attach 1
XMLPlayerLevelAttm xml2 = XmlAttach.FindAttachment( pm1, typeof( XMLPlayerLevelAttm ) ) as XMLPlayerLevelAttm; //attach 2

if (xml != null)
level +=xml.Levell;      //adding the xmlvalue
if (xml2 != null)
levelm +=xml2.Levell;  //adding the 2nd xmlvalue

level += levelm;        //both values
 
switch( orderBy )
{
    case OrderBy.level:
        pm1 = desc ? pm1.OrderByDescending( pm1 => level ) : pm1.OrderBy( pm1 => level ); //error
    break;
}


      string text = string.Format( ""+pm1.Name+ " Level [{0}] Exp: {1} / {2}", level, xml.kxp, xml.ToLevell ); //TODO TOTAL EXP
 
        AddLabel( 70, yOffset, 1952, text );

    yOffset += 55;

the script is a clusterfuck, im sorry, thanks guys
 
your orderby code should probably be outside the foreach, and pm1 is not a list therefor you can not use that.
pm1 is just 1 playermobile from the list you grabbed befor.
 
hey pyro thank you, this one compiles but it shows the player name then [0] value of 0

string text = string.Format( ""+pm1.Name+ " Level [{0}] ", level );

C#:
namespace Server.Gumps
{
    public class armorygrand : Gump
    {

        public enum OrderBy
{
    None,
    level
}
        public armorygrand(PlayerMobile pm) : base( 0, 0 )
        {
            this.Closable=false;
            this.Disposable=true;
            this.Dragable=true;
            this.Resizable=false;
       
           #region exp
 
            AddPage(0);
          AddBackground (18, 0 ,512,478,2620);   
         AddAlphaRegion (18,0,498,463);
  
        AddLabel(101, 8, 1952, "");
 
 

        int page = 0, cpage = 1;
      var players = World.Mobiles.Values.OfType<PlayerMobile>(); // filter only PlayerMobiles
      players = players.Take( 10 ); // take the first 10
  
  int yOffset = 40;
 
   var orderBy = OrderBy.level; // Sort by xml level
var desc = Utility.RandomBool( ); // Random ascending or descending

int level = 0;
int levelm = 0;

XMLPlayerLevelAtt xml = XmlAttach.FindAttachment( players, typeof( XMLPlayerLevelAtt ) ) as XMLPlayerLevelAtt;
XMLPlayerLevelAttm xml2 = XmlAttach.FindAttachment( players, typeof( XMLPlayerLevelAttm ) ) as XMLPlayerLevelAttm;
if (xml != null)
level +=xml.Levell; //le sumamos el xmllevel
if (xml2 != null)
levelm +=xml2.Levell;
level += levelm;
 
switch( orderBy )
{
    case OrderBy.level:
        players = desc ? players.OrderByDescending( pm1 => level ) : players.OrderBy( pm1 => level );
    break;
}
foreach( var pm1 in players ) // iterate the results
{

     string text = string.Format( ""+pm1.Name+ " Level [{0}] ", level );
 
        AddLabel( 70, yOffset, 1952, text );

    yOffset += 55;
 

               }
            
              
#endregion
      
        }
 
Last edited:
Thats because you set the level value befor the foreach. You also try to grab the xml attachment from the list and not a player therefor it will be null.

So it stays at 0
 
Thats because you set the level value befor the foreach. You also try to grab the xml attachment from the list and not a player therefor it will be null.

So it stays at 0
Ok i get it, now its working but its showing the lower value first


Playername [3]
Playername [5]
Playername [12]
etc

I would like the opposite, the higher first
 
Well you have
C#:
switch( orderBy )
{
    case OrderBy.level:
        players = desc ? players.OrderByDescending( pm1 => level ) : players.OrderBy( pm1 => level );
    break;
}

to reverse it?
C#:
switch( orderBy )
{
    case OrderBy.level:
        players = desc ? players.OrderBy( pm1 => level ) : players.OrderByDescending( pm1 => level );
    break;
}
 
already tried that, still showing lowest first and if i add lets say a value of 20 to one player it increase it to every player, the way its looking for the attachment might be wrong
 
Are you resetting level and levelm to 0 in each iteration of the loop?

I am sure the code is shifted again so I cant be sure whats going on there now
 
Thank for your patience PyrO, ok i did that (line 104), now it shows the value correctly for each player but it only orders it once the first time i run the server, then it not orders it anymore


The gump is sent on login for testing purporses

C#:
    private class armorygrandpm2 : Gump
       {
public enum OrderBy
{
    None,
    level
}
         private const int LabelHue = 0x480;
        public armorygrandpm2(PlayerMobile pm) : base( 0, 0 )
        {
            this.Closable=false;
            this.Disposable=true;
            this.Dragable=true;
            this.Resizable=false;
            AddPage(0);
          AddBackground (18, 0 ,512,478,2620);
         AddAlphaRegion (18,0,498,463);
        AddLabel(121, 8, 1166, "Grand professions");
 
        AddButton(492, 7, 2710, 2711, 2, GumpButtonType.Reply, 0);
 
         AddLabel( 40, 40, 1952, "1" );
         AddLabel( 40, 70, 1952, "2" );
         AddLabel( 40, 97, 1952, "3" );
  
         AddLabel( 40, 152, 1952, "4" );
         AddLabel( 40, 179, 1952, "5" );
         AddLabel( 40, 234, 1952, "6" );
          AddLabel( 40, 261, 1952, "7" );
          AddLabel( 40, 289, 1952, "8" );
         AddLabel( 40, 316, 1952, "9" );
        AddLabel( 40, 336, 1952, "10" );
  
        int page = 0, cpage = 1;
 
 
  int yOffset = 40;
 
var orderBy = OrderBy.level; // Sort by xml level
var desc = Utility.RandomBool( ); // Random ascending or descending

int level = 0;

      var players = World.Mobiles.Values.OfType<PlayerMobile>(); // filter only PlayerMobiles
          
switch( orderBy )
{
    case OrderBy.level:
        players = desc ? players.OrderBy( pm1 => level ) : players.OrderByDescending( pm1 => level );
    break;
}
 
            foreach( var pme in players ) // iterate the results
            {

 
           players = players.Take( 10 ); // take the first 10
      
          ArrayList plist = XmlAttach.FindAttachments(pme);
            if (plist != null && plist.Count > 0)
            {
                for (int i = 0; i < plist.Count; i++)
                {
                    XMLPlayerLevelAtt a = plist[i] as XMLPlayerLevelAtt; //l
                    XMLPlayerLevelAttm b = plist[i] as XMLPlayerLevelAttm; //m
                    XMLPlayerLevelAtth h = plist[i] as XMLPlayerLevelAtth; //h
                    XMLPlayerLevelAtts s = plist[i] as XMLPlayerLevelAtts; //s
              
                    if (a != null && !a.Deleted)
                    {
                    level += a.Levell; //we add the lvl
              
              
                    }
                 if ( b != null && !b.Deleted)
                  {               
                level += b.Levell; //we add the lvl
          
              
                  }
                   if ( h != null && !h.Deleted)
                  {               
                level += h.Levellherreria; ///we add the lvl
          
          
                  }
                    if ( s != null && !s.Deleted)
                  {               
                level += s.Levell; //we add the lvl
          
          
                  }

              
                }
          
            }
      
      
         string text = string.Format( ""+pme.Name+ " Level [{0}]", level.ToString());
                                                                                                
          AddLabel( 70, yOffset, 1952, text );
                    level = 0;

    yOffset += 30;


 } //end for each
 
        } //end m.player
        
                  
#endregion
      
 


        public override void OnResponse(NetState sender, RelayInfo info)
        {
            Mobile from = sender.Mobile;

            switch(info.ButtonID)
            {
                    case 0:
                {

                // from.SendMessage ("case 0");
                    break;
                }
          
                                case 1: //boton  minimizar
                    {
              
                      if (from != null)
                        {
              
                        }
              
          
                    break;
              
                    }
                case 2: //boton cerrar
                {
                if (from != null)
           {
      
  
  
    
                
           }
          
              
                
                    break;
                }

            }
        }
        }


On the first pic
Kokoa is lvl 11
rere lvl 2
DAS lvl 1

FP.png

Then i give 100 lvls to DAS and relog (2nd pic), the gump doesnt orders it, he sitll appears the 3rd like hes the lowest one

fp2.png
 
Last edited:
Well looking at the code, then the result is as you wanted it (at least wrote it ;) )

Since you wanted to order by the level, you would have to know their total level while ordering.

I gave it an extension method, since I am not sure why there are 4 attachments with the same name and how they are written.

This is untestet but should do, and I also cleaned up the indentions
C#:
    public static class Extensions
    {
        public static int GetTotalLevel(this PlayerMobile pm)
        {
            int level = 0;
            ArrayList plist = XmlAttach.FindAttachments(pm);
            if (plist != null && plist.Count > 0)
            {
                for (int i = 0; i < plist.Count; i++)
                {
                    XMLPlayerLevelAtt a = plist[i] as XMLPlayerLevelAtt; //l
                    XMLPlayerLevelAttm b = plist[i] as XMLPlayerLevelAttm; //m
                    XMLPlayerLevelAtth h = plist[i] as XMLPlayerLevelAtth; //h
                    XMLPlayerLevelAtts s = plist[i] as XMLPlayerLevelAtts; //s
            
                    if (a != null && !a.Deleted)
                    {
                        level += a.Levell; //we add the lvl       
                    }
                    if ( b != null && !b.Deleted)
                    {               
                        level += b.Levell; //we add the lvl
                    }
                    if ( h != null && !h.Deleted)
                    {               
                        level += h.Levellherreria; ///we add the lvl     
                    }
                    if ( s != null && !s.Deleted)
                    {               
                        level += s.Levell; //we add the lvl
                    }
                }
            }     
            return level;
        }
    }

    private class Armorygrandpm2 : Gump
    {
        public enum OrderBy
        {
            None,
            level
        }

        private const int LabelHue = 0x480;
        public Armorygrandpm2(PlayerMobile pm) : base( 0, 0 )
        {
            Closable=false;
            Disposable=true;
            Dragable=true;
            Resizable=false;

            AddPage(0);
            AddBackground (18, 0 ,512,478,2620);
            AddAlphaRegion (18,0,498,463);
            AddLabel(121, 8, 1166, "Grand professions");

            AddButton(492, 7, 2710, 2711, 2, GumpButtonType.Reply, 0);

            AddLabel( 40, 40, 1952, "1" );
            AddLabel( 40, 70, 1952, "2" );
            AddLabel( 40, 97, 1952, "3" );

            AddLabel( 40, 152, 1952, "4" );
            AddLabel( 40, 179, 1952, "5" );
            AddLabel( 40, 234, 1952, "6" );
            AddLabel( 40, 261, 1952, "7" );
            AddLabel( 40, 289, 1952, "8" );
            AddLabel( 40, 316, 1952, "9" );
            AddLabel( 40, 336, 1952, "10" );

            int page = 0, cpage = 1;
 
 
            int yOffset = 40;
 
            var orderBy = OrderBy.level; // Sort by xml level
            var asc = Utility.RandomBool( ); // Random ascending or descending

            var players = World.Mobiles.Values.OfType<PlayerMobile>(); // filter only PlayerMobiles

            switch( orderBy )
            {
                case OrderBy.level:
                    players = asc ? players.OrderBy( player => player.GetTotalLevel() ) : players.OrderByDescending( player => player.GetTotalLevel() );
                break;
            }
            players = players.Take( 10 ); // take the first 10
            
            foreach( var pme in players ) // iterate the results
            {
                AddLabel( 70, yOffset, 1952, pme.Name+ " Level ["+pme.GetTotalLevel()+"]");
                yOffset += 30;
            } //end for each
        } //end m.player
#endregion

        public override void OnResponse(NetState sender, RelayInfo info)
        {
            Mobile from = sender.Mobile;

            switch(info.ButtonID)
            {
                case 0:
                {
                // from.SendMessage ("case 0");
                    break;
                }

                case 1: //boton  minimizar
                {
                    if (from != null)
                    {
                    }
                    break;
                }

                case 2: //boton cerrar
                {
                    if (from != null)
                    {
                    }
                    break;
                }
            }
        }
    }
 
Yess! works like a charm, just one more thing:

How to make a value of 3000 appear like 3.000?

I added;
C#:
public static int GetTotal(this PlayerMobile pm)
        {
          //  int level = 0;
            int totala = 0;
            ArrayList plist = XmlAttach.FindAttachments(pm);
            if (plist != null && plist.Count > 0)
            {
                for (int i = 0; i < plist.Count; i++)
                {
                    XmlValuetotal total = plist[i] as XmlValuetotal; //total exp

                      if (total != null && !total.Deleted)
                    {
                        totala += total.Value;
                    }

                }
            } 
            return totala;
        }


then:

C#:
     string text = string.Format( "{0}",pme.GetTotal().ToString()("#,0" )); //line 196
            
                AddLabel( 270, yOffset, 1152,"Total XP  "+text);

error:


CS0149: Line 196: Method name expected

Since that totala value is going to be a big number (millions) i would like it to look like 4.000.000 instead of 4000000

PS:If i ever launch my game and i get some donations id like to share with you few bucks. Thanks for your time
 
Last edited:
you already got the whole list, and if it is ordered properly then you can just use players[0], players[1] and players[2]
 
Ah, not sure if i know how to do that properly. It has to be outside the foreach method right? or it will do it for each player in the list

im trying to get the name of the top1 pme[0], it dont let me
 
well it was just an example.
I am not sure where you want to reward the players and when
 
You would basically do it the same way you already did in the Gump, but this time you wouldnt do Take(10) but Take(3).

If you would already have gotten a orderd list (for the levels) then you wouldnt need to use Take since you can just grab the first 3 Elements
 
I got it,im testing, added it to a worldbroadcast it grabs the first 3 and says their name, i just dont know how to check the order, so [0] gets better reward than [2]



C#:
  var players2 = World.Mobiles.Values.OfType<PlayerMobile>(); // filter only PlayerMobiles


   players2 = players.Take( 3 ); // take the first 3

  foreach( var pmea in players2 ) // iterate the results
            {
                 World.Broadcast(0x35, true, "[SYSTEM]   TOP 3 PLAYERS: "+pmea.Name);
            }
 
Pyro if you are willing to keep helping me, please can you tell me how to give different rewards for the first 3 players?, i mean how to check for the top1, the top2,the top3.

I mean i can take 1, give it a reward (would be top1) , attach an attachment, called ''noreward''
take 2, give reward only if the attach ''noreward'' is null top2 would get rewarded, give the attachment ''noreward''
take 3 and give reward if the attach ''noreward''' is null (top3 will get rewarded)

that hacky clunky method will look for world mobiles like 5 times, that might cause lag i guess
 
Last edited:
C#:
 var players = World.Mobiles.Values.OfType<PlayerMobile>().OrderByDescending(player => player.GetTotalLevel()).Take(3);

then players[0] would be the first
then players[1] would be the second
then players[2] would be the third

That should be all you need to do
 
C#:
  var players = World.Mobiles.Values.OfType<PlayerMobile>().OrderByDescending(player => player.GetTotalLevel()).Take(3);
                
             players[0].AddToBackpack (new Gold (10000));
             players[1].AddToBackpack (new Gold (5000));
             players[2].AddToBackpack (new Gold (1500));

CS0021: Line 238: Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable<Ser
ver.Mobiles.PlayerMobile>'
CS0021: Line 239: Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable<Ser
ver.Mobiles.PlayerMobile>'
CS0021: Line 240: Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable<Ser
ver.Mobiles.PlayerMobile>'



Another atempt:

C#:
foreach( var pma in players )
            {

            
             pma[0].AddToBackpack (new Gold (10000));
              pma[1].AddToBackpack (new Gold (5000));
              pma[2].AddToBackpack (new Gold (1500));
             }

CS0021: Line 242: Cannot apply indexing with [] to an expression of type 'Server.Mobiles.PlayerMobile'
CS0021: Line 243: Cannot apply indexing with [] to an expression of type 'Server.Mobiles.PlayerMobile'
CS0021: Line 244: Cannot apply indexing with [] to an expression of type 'Server.Mobiles.PlayerMobile'




 
Eh thought you could access it right away, so I guess you have to transform it to an array first.

World.Mobiles.Values.OfType<PlayerMobile>().OrderByDescending(player => player.GetTotalLevel()).Take(3).ToArray();

btw dont iterate over all (the 3) players and give them each 3 times the rewards
 
Eh thought you could access it right away, so I guess you have to transform it to an array first.

World.Mobiles.Values.OfType<PlayerMobile>().OrderByDescending(player => player.GetTotalLevel()).Take(3).ToArray();

btw dont iterate over all (the 3) players and give them each 3 times the rewards
working!!!! thanks for your time and help, yeah i removed the foreach
Thank U Reaction GIF by Mauro Gatti
 
Ughhh i cant figure this out, the more i try the worse it gets, same as before ordering it, thanks @PyrO


Trying to order a list


CS0266: Line 79: Cannot implicitly convert type 'System.Linq.IOrderedEnumerable<Server.Mobiles.PlayerMobile>' to 'Sy
stem.Collections.Generic.List<Server.Mobile>'. An explicit conversion exists (are you missing a cast?)


C#:
 if (orderBy == OrderBy.level)
                   {               
                m_List = m_List.OfType<PlayerMobile>().OrderByDescending( player => player.GetTotalLevel1());
                   }


C#:
using System.Collections.Generic;
using Server.Guilds;
using System;
using Server;
using Server.Items;
using Server.Gumps;
using Server.Prompts;
using Server.Network;
using Server.Regions;
using Server.Engines.XmlSpawner2;
using Server.Mobiles;
using Server.Regions;
using Server.Collections;

using System.IO;
using System.Text;
using System.Linq;
namespace Server.Gumps
{
    public abstract class GuildMobileListGump : Gump
    {
        protected Mobile m_Mobile;
        protected Guild m_Guild;
        protected List<Mobile> m_List;
 public enum OrderBy
        {
            None,
            level
        }
        public GuildMobileListGump( Mobile from, Guild guild, bool radio, List<Mobile> list )
            : base( 20, 30 )
        {
            m_Mobile = from;
            m_Guild = guild;

            Dragable = true;

            AddPage( 0 );
            AddBackground( 0, 0, 550, 440, 2620 );
            //AddBackground( 10, 10, 530, 420, 3000 );

            Design();

            m_List = new List<Mobile>( list );

            for ( int i = 0; i < m_List.Count; ++i )
            {
                if ( (i % 11) == 0 )
                {
                    if ( i != 0 )
                    {
                        AddButton( 300, 370, 4005, 4007, 0, GumpButtonType.Page, (i / 11) + 1 );
                        AddHtmlLocalized( 335, 370, 300, 35, 1011066, false, false ); // Next page
                    }

                    AddPage( (i / 11) + 1 );

                    if ( i != 0 )
                    {
                        AddButton( 20, 370, 4014, 4016, 0, GumpButtonType.Page, (i / 11) );
                        AddHtmlLocalized( 55, 370, 300, 35, 1011067, false, false ); // Previous page
                    }
                }

                if ( radio )
                    AddRadio( 20, 35 + ((i % 11) * 30), 208, 209, false, i );

                  Mobile m = m_List[i];

                 string name;

                if ( (name = m.Name) != null && (name = name.Trim()).Length <= 0 )
                    name = "(empty)";

                 var orderBy = OrderBy.level; // Ordenar por nivel

                if (orderBy == OrderBy.level)
                   {               
                m_List = m_List.OfType<PlayerMobile>().OrderByDescending( player => player.GetTotalLevel1());
                   }
            

               XMLPlayerLevelAtt te2 = (XMLPlayerLevelAtt)XmlAttach.FindAttachment(m, typeof(XMLPlayerLevelAtt));
        
               PlayerMobile pm = m as PlayerMobile;
           
              //TODO add the labels//
         

                //AddLabel( (radio ? 55 : 20), 35 + ((i % 11) * 30), 0, name );
            }
        }

        protected virtual void Design()
        {
        }
    }
}
 
Last edited:
C#:
if (orderBy == OrderBy.level)
{
    m_List = m_List.OfType<PlayerMobile>().OrderByDescending(player => player.GetTotalLevel1()).ToList();
}


CS0029: Line 87: Cannot implicitly convert type 'System.Collections.Generic.List<Server.Mobiles.PlayerMobile>' to 'S
ystem.Collections.Generic.List<Server.Mobile>'
 
Well it looks ugly imo but it works.

m_List = m_List.OfType<PlayerMobile>().OrderByDescending(player => player.GetTotalLevel()).Cast<Mobile>().ToList();
 
Back