ServUO Version
Publish Unknown
Ultima Expansion
Mondain's Legacy
My shard is running on RunUO Version 2.1 . . . *ducks*

I don't know if this is possible or just fanciful dreaming. I searched everywhere and came up blank or just used the wrong searches. If it's possible then I have no clue how to make it work.


I want to create a NPC who will pay players for certain artifacts that a player drops on them (OnDragDrop) and specifically pay a higher amount depending on item's Properties for things like 'Defense, Guarding, Hardening, Fortification and Invulnerability' etc.

The artifacts I have show these properties in their 'GetProperties ( ObjectPropertyList list )'.
Here is an example:

Code:
        public override void GetProperties( ObjectPropertyList list )
         {
             base.GetProperties( list );
            list.Add( "<BASEFONT COLOR=#FD4541>Guarding<BR><BASEFONT COLOR=#75FBEB>Something about this item might be<BR>apparent when you have it enhanced" );
         }

1) Is it possible for a NPC to search an item's PropertyList for certain words (ie Defense, Guarding, Hardening, Fortification or Invulnerability) when the item is dropped on them so the NPC can calculate how much to gold to pay the player for the item?

2) Would it be necessary to have the key word in a line of its own or can it be detected out of a sentence like in the sample code above?

Either way, I'm sure it would involve some complicated text search of the ObjectPropertyList which is a few miles over my paygrade so to speak.

Has anyone tried this before? Can anyone offer some guidance (or if not possible . . put me out of my misery)?

I appreciate the community's input.

Many Thanks
 
You should have a property for the enchant level of the weapon / armor and you can just go from there. Reading a property list like that? Not really that feasable
 
Thank you Pyro . . I was afraid that would be the answer. My bad for creating hundreds of custom armor/shield/weapon/jewelry items and burying a quality aspect of the items in the GetProperties section.

For a moment I hoped that a NPC might be able to use OnSingleClick on a dropped item to extract a string from GetProperties and from which the first word in the string could be recognized. 'The Lesson' . . Bad foresight will bite your butt every time.

Sorry for people's time used on this and thanks to all who gave it a look.
 
Thank you Pyro . . I was afraid that would be the answer. My bad for creating hundreds of custom armor/shield/weapon/jewelry items and burying a quality aspect of the items in the GetProperties section.

For a moment I hoped that a NPC might be able to use OnSingleClick on a dropped item to extract a string from GetProperties and from which the first word in the string could be recognized. 'The Lesson' . . Bad foresight will bite your butt every time.

Sorry for people's time used on this and thanks to all who gave it a look.
You could use item.PropertyList.HeaderArgs to get string values.
Exemple:
C#:
        public override bool OnDragDrop(Mobile from, Item dropped)
        {
            if (dropped?.PropertyList?.HeaderArgs?.Contains("Guarding") == true)
            {
                // ToDo something.
                return true;
            }

            return base.OnDragDrop(from, dropped);
        }
But in fact, it would be more logical to add special properties to the item so that you can operate on them.
 
Hi Juzzver,

I 'm seriously excited that what you are suggesting might work because it would save me 'literally' hours of rescripting individual Artifact files.

I inserted the suggestion at the start of 'OnDragDrop' and started running tests.

The first line (with the '?' marks):
Code:
                if (dropped?.PropertyList?.HeaderArgs?.Contains("Guarding") == true)
                {
                    // ToDo something.
                    this.PrivateOverheadMessage( MessageType.Regular, 1153, false, "Thank You for the Guarding Artifact.", mobile.NetState );

                    return base.OnDragDrop(from, dropped);
                }
                else
                {
                    this.PrivateOverheadMessage( MessageType.Regular, 1153, false, "OOPS! Where is the Guarding Artifact?", mobile.NetState );
                }

. . . generates these errors . . .
Code:
Errors:
 + Customs/Quests/Quest Arti Dealer/Mobiles/QGArti.cs:
    CS1525: Line 215: Invalid expression term '.'
    CS1003: Line 215: Syntax error, ':' expected
    CS1525: Line 215: Invalid expression term '.'
    CS1003: Line 215: Syntax error, ':' expected
    CS1525: Line 215: Invalid expression term '.'
    CS1003: Line 215: Syntax error, ':' expected
    CS1002: Line 215: ; expected
    CS1525: Line 215: Invalid expression term ')'
    CS1002: Line 215: ; expected
    CS1525: Line 223: Invalid expression term 'else'
    CS1002: Line 223: ; expected


I then tried the same thing without the '?' marks like this:
Code:
                if (dropped.PropertyList.HeaderArgs.Contains("Guarding") == true)
                {
                    // ToDo something.
                    this.PrivateOverheadMessage( MessageType.Regular, 1153, false, "Thank You for the Guarding Artifact.", mobile.NetState );

                    return base.OnDragDrop(from, dropped);
                }

and the script compiled but when I drop a 'Guarding' artifact on the NPC nothing happened including the 'Thank You' message. The whole section appears to be is simply bypassed. After that I tried a couple other variations (such as removing the reference to '== true') but with the same result.

It makes sense to me that your approach should work but am at a loss to make that happen. If you (or anyone) can see where it fails, I would be doing the happy dance all night long.

Can't tell you how much your time on this means *bows*
 
The OPL is not a List in the sense of a generic List in C#

It writes the encoded bytes into the packet, and unless you would want to untangle the whole packet for an item to find the right bytes ...

Your code / your items should still use the default properties for the enchants, right?
1677598646571.png

This for example returns the protection level like this:
1677598705594.png

So you should rather use the property with the enum value check.
 
Hi Juzzver,

I 'm seriously excited that what you are suggesting might work because it would save me 'literally' hours of rescripting individual Artifact files.

I inserted the suggestion at the start of 'OnDragDrop' and started running tests.

The first line (with the '?' marks):
Code:
                if (dropped?.PropertyList?.HeaderArgs?.Contains("Guarding") == true)
                {
                    // ToDo something.
                    this.PrivateOverheadMessage( MessageType.Regular, 1153, false, "Thank You for the Guarding Artifact.", mobile.NetState );

                    return base.OnDragDrop(from, dropped);
                }
                else
                {
                    this.PrivateOverheadMessage( MessageType.Regular, 1153, false, "OOPS! Where is the Guarding Artifact?", mobile.NetState );
                }

. . . generates these errors . . .
Code:
Errors:
 + Customs/Quests/Quest Arti Dealer/Mobiles/QGArti.cs:
    CS1525: Line 215: Invalid expression term '.'
    CS1003: Line 215: Syntax error, ':' expected
    CS1525: Line 215: Invalid expression term '.'
    CS1003: Line 215: Syntax error, ':' expected
    CS1525: Line 215: Invalid expression term '.'
    CS1003: Line 215: Syntax error, ':' expected
    CS1002: Line 215: ; expected
    CS1525: Line 215: Invalid expression term ')'
    CS1002: Line 215: ; expected
    CS1525: Line 223: Invalid expression term 'else'
    CS1002: Line 223: ; expected


I then tried the same thing without the '?' marks like this:
Code:
                if (dropped.PropertyList.HeaderArgs.Contains("Guarding") == true)
                {
                    // ToDo something.
                    this.PrivateOverheadMessage( MessageType.Regular, 1153, false, "Thank You for the Guarding Artifact.", mobile.NetState );

                    return base.OnDragDrop(from, dropped);
                }

and the script compiled but when I drop a 'Guarding' artifact on the NPC nothing happened including the 'Thank You' message. The whole section appears to be is simply bypassed. After that I tried a couple other variations (such as removing the reference to '== true') but with the same result.

It makes sense to me that your approach should work but am at a loss to make that happen. If you (or anyone) can see where it fails, I would be doing the happy dance all night long.

Can't tell you how much your time on this means *bows*
I'm sorry, that was my mistake.
HeaderArgs would work for a custom item name, which made me mistakenly think it would work for all other labels as well.
But we still have the opportunity to make it work as we would like, though we need to make changes to the base code or use reflection methods.
But if you are using the VitaNex extension on your server, then you have nothing to worry about, because there is already have a solution through the calculation of hashes. An example using VitaNex would look like this:
C#:
    public override bool OnDragDrop(Mobile from, Item dropped)
        {
            string searchLabel = "Guarding<BR>";

            if (dropped != null && dropped.GetOPLString().Contains(label))
            {
                // ToDo something.
                this.PrivateOverheadMessage(MessageType.Regular, 1153, false, "Thank You for the Guarding Artifact.", from.NetState);

                return base.OnDragDrop(from, dropped);
            }
            else
            {
                this.PrivateOverheadMessage(MessageType.Regular, 1153, false, "OOPS! Where is the Guarding Artifact?", from.NetState);
                return false;
            }
        }
note that I am using the prefix:
<BR> to search for the labels we need. Because in your case, you run the risk of creating a problem where players will be able to turn in any item that has "Guarding" in the name or any other text that falls under your filters.
This is one of the typical reasons why it would be better to use the properties of the item, as Pyro wrote, instead of operating on text.
 
It is definitely possible to reverse engineer the OPL and search for strings within it, but PyrO is correct, you should just code against the actual properties that are used to generate the OPL anyway.

But, as Juzzver stated, Vita-Nex provides a simple way to achieve it, here is an expanded example that allows you to define a list of keywords and their point values to attain the total.
C#:
private static Dictionary<string, int> _Search = new Dictionary<string, int>( StringComparer.OrdinalIgnoreCase )
{
    ["Guarding"] = 123,
};

C#:
int total = 0;

foreach ( string line in item.PropertyList.EnumerateLines( ) )
{
    foreach ( KeyValuePair<string, int> search in _Search )
    {
        if ( line.Contains( search.Key ) )
        {
            total += search.Value;
        }
    }
}

It is also worth noting that this method is flawed in another way, as if you allow engraving tools or item renaming, players can easily exploit this approach.
 
Well this is amazing. All of you have been great here. Especially thanks to Pyro, Juzzver and Voxpire for the true help and the time taken to look at this for me. Thanks also to any who stopped, looked and pondered the situation. I now have a lot to work with. All combined . . a solid community.

Cheers
*bows*
 
Back