Author Topic: ContextMenu activate entry in open ContextMenu  (Read 4382 times)

0 Members and 1 Guest are viewing this topic.

Offline OctavianTopic starter

  • Newbie
  • *
  • Posts: 4
  • Activity:
    0%
  • Reputation Power: 1
  • Octavian has no influence.
  • Respect: 0
  • Referrals: 0
    • View Profile
ContextMenu activate entry in open ContextMenu
« on: October 01, 2015, 04:50:26 AM »
0
Hi there,

My Problem:
Is there a way to activate a specific entry in an already open ContextMenu?

Why do I ask:
I have a problem regarding the context menu.
On my server we have a few skill trainer that can train your skill to high levels.
However the problem is that the index of the "Train <Skill>" entry is on a different position every time I open the ContextMenu.

My demo-Code:
Code: [Select]
# SKILL is the context-entry that shall be activated to train the skill.
SKILL = 'Train Archery'

def getSellContextMenu(vendorId):
    ClearContextMenu()
    while GetContextMenu() == []:
        RequestContextMenu(vendorId)
        sleep(0.5)
    contexts = GetContextMenu()
    contNr = -1
    # context is one line from the context menu.
    for context in contexts:
        if SKILL in context:
         # Get the position of the found context entry.
            contEntry = context.split('|', 1)[0]
            # print 'ContextEntry: %s, number: %s' % (context, contEntry)
            contNr = int(contEntry)
    if contNr == -1:
     # Skill was not found in the context menu.
        return False
    # Activate the found context-entry.
    SetContextMenuHook(vendorId, contNr)
The problem of my demo code:
SetContextMenuHook seems to open a new ContextMenu thus activating the wrong entry.

Offline Crome969

  • Moderator
  • *
  • *****
  • Posts: 2098
  • Activity:
    0%
  • Reputation Power: 25
  • Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.
  • Gender: Male
  • UO Enthusiast
  • Respect: +211
  • Referrals: 10
    • View Profile
    • ScriptSDK
Re: ContextMenu activate entry in open ContextMenu
« Reply #1 on: October 02, 2015, 02:24:41 PM »
0
Here is some code where i handle context properly in c#

Code: [Select]
using System;
using System.Collections.Generic;
using System.Linq;
using ScriptSDK.API;
using ScriptSDK.Data;
using ScriptSDK.Engines;

namespace ScriptSDK.ContextMenus
{
    public class ContextMenu
    {
        public ContextMenu(UOEntity owner)
        {
            Entries = new List<ContextMenuEntry>();
            Owner = owner;
        }

        protected UOEntity Owner { get; set; }
        public List<ContextMenuEntry> Entries { get; private set; }
        public event EventHandler<ContextMenuEventArgs> OnClick;

        public bool Click(string Text, bool strict = true)
        {
            var e = Entries;

            if (Text.Trim().Equals(string.Empty))
                return false;
            if (!strict)
                Text = Text.ToLower();
            if (e == null)
                return false;
            if (e.Count < 1)
                return false;

            foreach (var a in e)
            {
                var t = a.Text;
                if (!strict)
                    t = t.ToLower();
                if (t.Equals(Text))
                    return Click(a);
            }
            return false;
        }

        public bool Click(ContextMenuEntry entry)
        {
            if (Owner == null)
                return false;

            var LastUser = ContextOptions.AssignedObject.Value;

            if (!LastUser.Equals(Owner.Serial.Value))
                return OnUse(new ContextMenuEventArgs {Entry = entry, State = false});

            foreach (var e in Entries.Where(e => e.ClilocID.Equals(entry.ClilocID)))
            {
                return OnUse(new ContextMenuEventArgs {Entry = e, State = true});
            }
            return OnUse(new ContextMenuEventArgs {Entry = entry, State = false});
        }

        public bool Click(uint ClilocID)
        {
            foreach (var e in Entries.Where(e => e.ClilocID.Equals(ClilocID)))
            {
                return Click(e);
            }
            return OnUse(new ContextMenuEventArgs {Entry = new ContextMenuEntry(string.Empty, this), State = false});
        }

        public bool Parse()
        {
            if (ContextOptions.AssignedObject.Equals(Owner.Serial))
                return false;

            Entries.Clear();

            if (Owner == null)
                return false;

            var LastUser = ContextOptions.AssignedObject;

            if (!LastUser.Value.Equals(0) && !LastUser.Equals(Owner.Serial))
                return false;

            Stealth.Client.ClearContextMenu();
            Entries = new List<ContextMenuEntry>();
            if (Owner == null)
                return false;

            Stealth.Client.RequestContextMenu(Owner.Serial.Value);

            if (ContextOptions.ParserDelay > 0)
                Stealth.Client.Wait(ContextOptions.ParserDelay);

            var list = Stealth.Client.GetContextMenu();
            if (!list.Contains("\r\n"))
            {
                const string Code =
                    "ContextMenu Parsing Error!\nFollowing choices could solve the issue:\n* Increase Parser Delay\n* visit https://bitbucket.org/Stealthadmin/stealth-beta-client/issue/11/70411-update";

                ScriptLogger.WriteLine(Code);

                return false;
            }

            list = list.Replace("\r\n", ContextOptions.ParserSymbol.ToString());

            var s = list.Split(ContextOptions.ParserSymbol);

            Entries.Clear();

            foreach (var e in s)
                Entries.Add(new ContextMenuEntry(e, this));

            ContextOptions.AssignedObject = Owner.Serial;

            return true;
        }

        public UOEntity GetOwner()
        {
            return new UOEntity(Owner.Serial.Value);
        }

        protected virtual bool OnUse(ContextMenuEventArgs e)
        {
            if (e.State)
            {
                var lu = ContextOptions.AssignedObject;

                if (Owner == null || !Owner.Serial.Value.Equals(lu.Value))
                    e.State = false;

                if ((!e.Entry.Flags.Equals(CMEFlags.Disabled)) && (e.State))
                {
                    Stealth.Client.ClearContextMenu();
                    Stealth.Client.SetContextMenuHook(lu.Value, (byte) e.Entry.Tag);
                    Stealth.Client.RequestContextMenu(lu.Value);
                    if (ContextOptions.ParserDelay > 0)
                        Stealth.Client.Wait(ContextOptions.ParserDelay);
                    Stealth.Client.ClearContextMenu();
                    Stealth.Client.RequestContextMenu(0);
                    Stealth.Client.SetContextMenuHook(0, 0);
                }
                else
                    e.State = false;
            }
            var handler = OnClick;
            if (handler != null)
            {
                handler(this, e);
            }
            return e.State;
        }
    }
    public interface ICMEntry
    {
        CMEFlags Flags { get; }
        uint ClilocID { get; }
        ushort Tag { get; }
        ushort Color { get; }
        string Text { get; }
    }

    public class ContextMenuEntry : ICMEntry
    {
        public ContextMenuEntry(string properties, ContextMenu owner)
        {
            var list = properties.Split('|');
            var parseable = list.Length.Equals(5);

            Text = parseable ? list[2] : "INVALID ENTRY";
            Flags = parseable ? (CMEFlags) Convert.ToUInt16(list[2]) : CMEFlags.Disabled;
            Color = parseable ? Convert.ToUInt16(list[4]) : (ushort) 0;
            Tag = parseable ? Convert.ToUInt16(list[3]) : (ushort) 0;
            ClilocID = parseable ? Convert.ToUInt32(list[1]) : 0;

            _owner = owner;
        }

        protected ContextMenu _owner { get; set; }
        public CMEFlags Flags { get; private set; }
        public uint ClilocID { get; private set; }
        public ushort Tag { get; private set; }
        public ushort Color { get; private set; }
        public string Text { get; private set; }
    }
}

Offline OctavianTopic starter

  • Newbie
  • *
  • Posts: 4
  • Activity:
    0%
  • Reputation Power: 1
  • Octavian has no influence.
  • Respect: 0
  • Referrals: 0
    • View Profile
Re: ContextMenu activate entry in open ContextMenu
« Reply #2 on: October 02, 2015, 02:57:39 PM »
0
But if I read your code right you open a new ContextMenu in "OnUse":
Code: [Select]
Stealth.Client.ClearContextMenu();
Stealth.Client.SetContextMenuHook(lu.Value, (byte) e.Entry.Tag);
Stealth.Client.RequestContextMenu(lu.Value);

This code closes the existing ContextMenu and opens a new one with a hook activated.
My problem is that the entry I want to activate is on a different position (if it is there at all) when I reopen the context menu.

Offline Crome969

  • Moderator
  • *
  • *****
  • Posts: 2098
  • Activity:
    0%
  • Reputation Power: 25
  • Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.Crome969 is on the verge of being accepted.
  • Gender: Male
  • UO Enthusiast
  • Respect: +211
  • Referrals: 10
    • View Profile
    • ScriptSDK
Re: ContextMenu activate entry in open ContextMenu
« Reply #3 on: October 03, 2015, 01:33:53 AM »
0
When i posted this i was drunk and tired but here a few answers.
In Stealth certain functions needs to be capturing the information.
So context Menu you need to hook the context menu, then read and give an index.
In most cases where the index stays alive you normaly request a context, read data and then clear menu, hook the entry and then renew your request (see my c# snippet)
if you post me via pm wich shard you play, i may could take a look what exactly happen there and if i can find a solution.

Tags: