What's new
  • Visit Rebornbuddy
  • Visit Panda Profiles
  • Visit LLamamMagic
  • Visit Resources
  • Visit Downloads
  • Visit Portal

Writing a plugin to run only when a Keypress event is called.

Upperfoot

New Member
Joined
Sep 10, 2012
Messages
4
Reaction score
0
Hello I am rather new to this and wish to start writing a basic plugin that runs a piece of code when a keypress is called within Warcraft (making more complicated macros for instance) and need a bit of help finding out how to do it, as I have no idea what functions are needed to achieve this.

Can anyone help me along my way to writing this plugin, a bit of sample code would help me immensely :o
 
Hello I am rather new to this and wish to start writing a basic plugin that runs a piece of code when a keypress is called within Warcraft (making more complicated macros for instance) and need a bit of help finding out how to do it, as I have no idea what functions are needed to achieve this.

Can anyone help me along my way to writing this plugin, a bit of sample code would help me immensely :o

Hi, Upperfoot,

Thankfully, the rewrite of Honorbuddy has made this task very easy. "Hooking" a hotkey looks like:

using System.Windows.Forms;
using Styx.Common;

public class MyClass
{
public void MyInitFunc()
{
//...whatever...

Hotkeys.RegisterHotkey("Toggle Movement", () => { MovementToggle(); }, Keys.PageDown);​
}

public static bool MovementToggle()
{
//...whatever...
return (true);​
}​
}​
There is one undocumented quirk if you are registering multiple Hotkeys... the first argument (a string) to RegisterHotkey must be unique. If you try to assign the same string value to different RegisterHotkey calls, the hotkeys that share a common string value will behave strangely.

cheers and good luck with your project,
chinajade
 
Thanks chinajade, I have one more question I would like to ask, if I need to cast a spell in a specific location, say either me or my pet, how would I accomplish this via a plugin and it not being dependant on a CC? For example I want the keypress to perform the function and nothing more as I want to handle everything else myself, and it seems that Singular takes control of my character.

Now I have played around with it and the functions to execute a spell are within Singular/Helpers/Spell.cs and Singular/Helpers/Pet.cs, are these required for me to execute a spell?
 
Thanks chinajade, I have one more question I would like to ask, if I need to cast a spell in a specific location, say either me or my pet, how would I accomplish this via a plugin and it not being dependant on a CC? For example I want the keypress to perform the function and nothing more as I want to handle everything else myself, and it seems that Singular takes control of my character.

Now I have played around with it and the functions to execute a spell are within Singular/Helpers/Spell.cs and Singular/Helpers/Pet.cs, are these required for me to execute a spell?

Hi, Upperfoot,

A quick-and-dirty implementation would look something like this:

public void CastMySpell()
{
if ((Me.Pet != null) && SpellManager.CanCast("SuperBuff", Me.Pet))
{
SpellManager.Cast("SuperBuff", Me.Pet);
while (Me.IsCasting)
{
Thread.Sleep(100);​
}​
}​
}​
This is far from the best way to do it, but its easy to understand and gets the job done.

cheers,
chinajade
 
Hi, Upperfoot,

A quick-and-dirty implementation would look something like this:

This is far from the best way to do it, but its easy to understand and gets the job done.

cheers,
chinajade

Thanks China, that helped me a lot :), I have this so far which works so long as I have a CC attached to it (Singular), is there anyway of getting this to run without a CC controlling my character?

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Styx;
using Styx.CommonBot;
using Styx.Common.Helpers;
using Styx.Common;
using Styx.Helpers;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWCache;
using Styx.WoWInternals.WoWObjects;
using Styx.Plugins;
using CommonBehaviors.Actions;
using Styx.TreeSharp;

namespace RunKeyPress
{
    public class RunKeyPressMacro : HBPlugin
    {
        private static readonly WaitTimer CallPetTimer = WaitTimer.OneSecond;

        private static ulong _petGuid;
        private static readonly List<WoWPetSpell> PetSpells = new List<WoWPetSpell>();
        public static readonly WaitTimer PetTimer = new WaitTimer(TimeSpan.FromSeconds(2));

        private static bool _wasMounted;

        public override Version Version { get { return new Version(1, 0, 0); } }

        public override string Author
        {
            get { return "Upperfoot"; }
        }

        public override string Name
        {
            get { return " Run Key Press Macro "; }
        }

        public override string ButtonText
        {
            get
            {
                return "*  Run Key Press Macro *";
            }
        }
        public override bool WantButton
        {
            get
            {
                return true;
            }
        }

        public override void Pulse()
        {
            if (!StyxWoW.Me.GotAlivePet)
            {
                PetSpells.Clear();
                return;
            }

            if (StyxWoW.Me.Mounted)
            {
                _wasMounted = true;
            }

            if (_wasMounted && !StyxWoW.Me.Mounted)
            {
                _wasMounted = false;
                PetTimer.Reset();
            }

            if (StyxWoW.Me.Pet != null && _petGuid != StyxWoW.Me.Pet.Guid)
            {
                _petGuid = StyxWoW.Me.Pet.Guid;
                PetSpells.Clear();
                // Cache the list. yea yea, we should just copy it, but I'd rather have shallow copies of each object, rather than a copy of the list.
                PetSpells.AddRange(StyxWoW.Me.PetSpells);
                PetTimer.Reset();
            }
        }

        public override void OnButtonPress()
        {

        }

        public override void Initialize()
        {
            Hotkeys.RegisterHotkey("Toggle Movement", () => { MovementToggle(); }, Keys.PageDown);
        }

        public bool CanCastPetAction(string action)
        {
            WoWPetSpell petAction = PetSpells.FirstOrDefault(p => p.ToString() == action);
            if (petAction == null || petAction.Spell == null)
            {
                return false;
            }

            return !petAction.Spell.Cooldown;
        }

        public void CastPetAction(string action)
        {
            WoWPetSpell spell = PetSpells.FirstOrDefault(p => p.ToString() == action);
            if (spell == null)
                return;

            Logging.Write(string.Format("[Pet] Casting {0}", action));
            Lua.DoString("CastPetAction({0})", spell.ActionBarIndex + 1);
        }

        public bool MovementToggle()
        {
            string action = "Freeze";
            Logging.Write("attempted " + action);
            if (StyxWoW.Me.CurrentTarget != null && CanCastPetAction(action))
            {
                Logging.Write(action + " Player");
                
                //Spell.CastOnGround("Blizzard", ret => StyxWoW.Me.CurrentTarget.Location);

                CastPetAction(action);
                new WaitContinue(System.TimeSpan.FromMilliseconds(250), ret => false, new ActionAlwaysSucceed());
                SpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);

                //Pet.CreateCastPetActionOnLocation("Freeze", ret => !StyxWoW.Me.Mounted && !StyxWoW.Me.CurrentTarget.HasAura("Frost Nova") && StyxWoW.Me.GotAlivePet && StyxWoW.Me.Pet.ManaPercent >= 12);
            }

            return (true);
        }
    }
}
 
Thanks China, that helped me a lot :), I have this so far which works so long as I have a CC attached to it (Singular), is there anyway of getting this to run without a CC controlling my character?

Hi again, Upperfoot,

Honorbuddy requires a CombatRoutine present and available just to operate.

You're in luck with Singular tho. Bobby53 has added the ability to not engage in combat, or to not move your toon. You configure these options in the Singular configuration panel (they are turned off by default):

Honorbuddy -> Characters & Settings -> Class Config -> Hotkey tab​

Once you configure this, I believe it will do exactly what you want.


And a heads up on looking through your code...
The WaitContinue() won't work as you think it does. Its meant to be used in a BehaviorTree context, and won't work from the functional context you are using in the Movement() method. I'm sad to say, you'll have to resort to Thread.Sleep(), instead.

But...
You on the very right track. It is not easy, but an efficient and mature plugin would take advantage of Behavior Trees, but the whole thing would need to be cast that way. This is not an easy task.

cheers,
chinajade
 
Last edited:
Awesome, I got my first plugin working very well now :).

It acts as a one button macro for casting my Pet's Freeze ability at the location of my currenttarget if hostile, now I need to figure out a way of having Honorbuddy detect a string within a macro when called, which will then call the plugin routine, so I can implement it in WoW rather than Honorbuddy, is there any way of doing this?
 
Back
Top