How to create plugins for ACT
Introduction
Included with ACT you will find the assembly "ACTPluginInterface.dll".
To develop a plugin for ACT, create a Visual C# "class library" project, Name it <something>Plugin (ex MyPlugin), and add a reference to ACTPluginInterface.dll.
then create a class in your project which implements the interface IACTPlugin.
Example:
public sealed class MyPlugin : IACTPlugin
{
public string Name
{
get { return "My Plugin"; }
set { }
}
public void InitAddon(IACT host, IACTPluginUI uihost)
{
}
}
Compile your project, our example project MyPlugin will produce MyPlugin.dll. Place this file in the same directory as ACT. When you run ACT your plugin will be loaded, and it will have its InitAddon() method called.
More Detail
Now to do something useful. (Note: the examples here are also available as VS2008 projects from the SVN)
As you can see there are 2 interfaces passed to InitAddon() IACT and IACTPluginUI.
Lets see what they do:
public interface IACT
{
event EventHandler<DamageEventArgs> Damage;
event EventHandler<HealEventArgs> Heal;
event EventHandler<ExperienceEventArgs> Experience;
event EventHandler<DeathEventArgs> Death;
event EventHandler<ActivityStatusEventArgs> ActivityStatus;
event EventHandler<GainEventArgs> Gain;
event EventHandler<AbsorbEventArgs> Absorb;
event EventHandler<CombatEventArgs> Tick;
}
public interface IACTPluginUI
{
void AddMenuItem(ToolStripMenuItem menu);
void AddUIPanel(string name, Panel panel, string infoLabelText);
void ActivateUI(Panel panel);
}
As you can see IACT provides a collection of events which are fired as data is retrieved from the combat log.
IACTPluginUI provides a way for your plugin to have a user interface within the ACT application.
A Simple Example
This simple example demonstrates a plugin which plays a sound file which says "Fatality!" during live combat log parsing - so the user hears it in-game while they are playing.
public sealed class FatalitySound : IACTPlugin
{
#region IACTPlugin Members
public string Name
{
get { return "Fatality Sound"; }
set { }
}
public void InitAddon(IACT host, IACTPluginUI uihost)
{
host.Gain += Combat_OnGain;
_player.SoundLocation = Path.Combine(Directory.GetCurrentDirectory(), "fatality.wav");
_player.Load();
}
#endregion
static SoundPlayer _player = new SoundPlayer();
private static void Combat_OnGain(object sender, GainEventArgs e)
{
if ( e.Source == Units.Player && e.Target == Units.Player)
{
if (e.Effect == "Fatality")
_player.Play();
}
}
}
As you can see, all we do is register for the "Gain" event in InitAddon() then we recieve events for each "gain", ex. "You gain Fatality".
A More Complex Example
You can also add a user interface to show more complex information.
public sealed class SamplePlugin : IACTPlugin
{
private const string _addonName = "Experience By Mob";
private SortedDictionary<string, int> _xpPerMob = new SortedDictionary<string, int>();
private int _lastXP;
ToolStripMenuItem Menu { get; set; }
Panel UIPanel { get; set; }
DataGridView Grid { get; set; }
IACTPluginUI UIHost { get; set; }
public string Name
{
get { return _addonName; }
set { }
}
public void InitAddon(IACT host, IACTPluginUI uihost)
{
UIHost = uihost;
Menu = new ToolStripMenuItem(Name);
UIHost.AddMenuItem(Menu);
UIPanel = new Panel();
ConfigurePanel();
UIPanel.VisibleChanged += UI_OnVisibleChanged;
UIHost.AddUIPanel(Name, UIPanel, "This is a sample plugin");
Menu.Click += Menu_OnClick;
host.Death += Combat_OnDeath;
host.Experience += Combat_OnExperience;
host.Tick += Combat_OnTick;
}
Here - in InitAddon, we create a menu item, and a panel (which show up as an additional tab in ACT). We also register for the events we will need to gather XP per Mob type data.
With this we are able to add a grid view to display the data our plugin is collecting - total experience gained broken down by the individual mob types.
Now the rest of the code implements the UI and data collection functionality.
private void UI_OnVisibleChanged(object sender, EventArgs e)
{
if (UIPanel.Visible)
UpdateUI();
}
private void ConfigurePanel()
{
Grid = new DataGridView {Dock = DockStyle.Fill};
Grid.Columns.Add("name", "Name");
Grid.Columns.Add("amount", "Amount");
Grid.EditMode = DataGridViewEditMode.EditProgrammatically;
UIPanel.Controls.Add(Grid);
}
// A naieve implementation of mob/XP correlation
private void Combat_OnTick(object sender, CombatEventArgs e)
{
_lastXP = 0;
}
private void Combat_OnExperience(object sender, ExperienceEventArgs e)
{
_lastXP = e.Amount;
}
private void Combat_OnDeath(object sender, DeathEventArgs e)
{
if (e.Target != Units.Player)
{
if (_lastXP > 0)
AddExperience(e.Target, _lastXP);
}
_lastXP = 0;
}
private void AddExperience(string source, int amount)
{
if (_xpPerMob.ContainsKey(source))
_xpPerMob[source] += amount;
else
_xpPerMob[source] = amount;
if (UIPanel.Visible)
UpdateUI();
}
private void Menu_OnClick(object sender, EventArgs e)
{
UIHost.ActivateUI(UIPanel);
UpdateUI();
}
private delegate void UpdateUIDelegate();
private void UpdateUI()
{
if (UIPanel.InvokeRequired)
{
UIPanel.Invoke(new UpdateUIDelegate(UpdateUI));
return;
}
Grid.Rows.Clear();
foreach (var item in _xpPerMob)
{
Grid.Rows.Add(new object[] { item.Key, item.Value });
}
}
}
Facts
- Date created
- 05 Jun 2008
- Last updated
- 06 Jun 2008