-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathMQ2PluginDevelopment.html
128 lines (123 loc) · 7.91 KB
/
MQ2PluginDevelopment.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>MQ2 Plugin Development</title>
</head>
<body>
<p><b>MQ2 Plugin Development</b> </p>
<p>MQ2 Plugins by design inherit any and all functionality used in the MQ2 main
DLL (MQ2Main.dll). This means developing plugins and developing the
MQ2Main API are 99% equal, and if one can develop for one they can definitely
develop for the other.</p>
<p>MQ2 Plugins provide added functionality to MQ2. The default set of
functionality is more or less the core "macro" commands and other general-use
commands, parameters, and required API to make the entire system work.
Everything else belongs in plugins. Because we don't want a new plugin for
every command, most general-use commands will be implemented into the main DLL
rather than plugins. Commands specific to plugins with other functionality
will of course go in the plugin itself.</p>
<p><b>Creating a new plugin</b></p>
<p><b>Before selecting an option, read the paragraph under "The functionses, my
precious" that says <font size="4">TAKE OUT THE ONES YOUR PLUGIN DOES NOT USE</font>
at the end.</b></p>
<blockquote>
<p><b>OPTION 1:</b> MQ2Template is an empty plugin, and will always contain the newest possible
plugin template. The absolute first thing to do is to copy the contents of
the MQ2Template directory, except for the readme.txt, to a new directory.
For example purposes, we will use MQ2MyPlugin, but you would of course insert
your own plugin name. Next, open each file in notepad or another text
editor and replace every instance of MQ2Template with MQ2MyPlugin. Also,
rename each file from MQ2Template.* to MQ2MyPlugin.*. After doing so, your
plugin will be fully functional as a MQ2 plugin, and will compile to the Release
directory. </p>
<p><b>OPTION 2: </b>"mkplugin" has been created to automate the creation of one
or more plugins at once, automating the process given in option one. From
the command line, "mkplugin <name>" will create a plugin. The plugin will
automatically be prefixed with "MQ2" and the next letter capitalized (though the
rest is untouched). For example, "<b>mkplugin myPlugin</b>" and the name
given to the plugin will be "MQ2MyPlugin". If you do "<b>mkplugin
mq2myplugin</b>" the name given will be "MQ2Myplugin". To create multiple
plugins at once, just add a parameter to the command line for every plugin.
Example: "<b>mkplugin one two three four</b>" will create "MQ2One", "MQ2Two",
"MQ2Three" and "MQ2Four". mkplugin.exe is found in the Macroquest2
workspace/solution root directory. If you aren't familiar with DOS, simply
do this: Start->Run "<b>c:\mq2\mkplugin.exe one two three four</b>", but
replace c:\mq2 with the actual path to your MQ2.</p>
</blockquote>
<p>Now you can open your project in visual studio or open the main file with
whatever you happen to code with. Immediately you will see several very
concise functions, most of which simply DebugSpew. Make sure to not muck
with <b>PreSetup("MQ2MyPlugin");</b>.<b> </b>It is where it is supposed to
be, and sets up your plugin's DllMain and sets the INI filename and path.</p>
<p><b>The functionses, my precious</b> </p>
<p>The MQ2 Plugin system is based on <b>callback</b> functions. This means
that MQ2 is going to call certain functions in your plugin, if they exist.
None of the callbacks are absolutely mandatory, but you will at least want
InitializePlugin and ShutdownPlugin. <b><font size="4">TAKE OUT THE ONES YOUR
PLUGIN DOES NOT USE.</font></b></p>
<p>PLUGIN_API VOID InitializePlugin(VOID) </p>
<p>This function is called immediately after your plugin is loaded by the
system. Add any commands, aliases, detours, macro params here. It is
not safe to assume that EQ is "in-game" when this is called. </p>
<p>PLUGIN_API VOID ShutdownPlugin(VOID) </p>
<p>This function is called immediately before your plugin is unloaded by the
system. Remove any commands, aliases, detours, macro params here. It
is not safe to assume that EQ is "in-game" when this is called. OnCleanUI is
explicitly called immediately before ShutdownPlugin(), so it is not necessary to
do anything found in OnCleanUI here.</p>
<p>PLUGIN_API VOID OnZoned(VOID)</p>
<p>This function is called immediately after the EQ client finishes entering a
new zone. It is safe to assume that EQ is "in-game" when this is called.</p>
<p>PLUGIN_API VOID OnCleanUI(VOID)</p>
<p>This function is called when EQ cleans its game ui. This could be from
in game or at character select, and I believe one other point. If you need
to clean up, make sure to check your data for existence first.</p>
<p>PLUGIN_API VOID SetGameState(DWORD GameState)</p>
<p>This function is called when EQ changes game state. If you do not need
to know when these changes occur, you do not need this function. You can
access MQ2's game state value with the gGameState global variable.</p>
<p>PLUGIN_API VOID OnPulse(VOID)</p>
<p>This function is called immediately after the MQ2Main Pulse function, many
many times per second. If you need continuous processing in your plugin,
this is what you're looking for.</p>
<p>PLUGIN_API DWORD OnWriteChatColor(PCHAR Line, DWORD Color, DWORD Filter)</p>
<p>This function is called every time WriteChatColor is called by MQ2Main or any
plugin, ignoring the filters built into MQ2Main. If you need to filter
this data, you need to implement the filters yourself. Note the Filter
parameter. This is for future use, it will currently always be 0.
It's intended to allow chat plugins to redirect MQ output, etc, regardless of
EQ's filters. Eventually, MQ2 calls to WriteChatColor will use a dynamic
filter system. For now, ignore it.</p>
<p>PLUGIN_API DWORD OnIncomingChat(PCHAR Line, DWORD Color)</p>
<p>This function is called every time EQ shows a line of chat with
CEverQuest::dsp_chat, but after MQ filters and chat events are taken care of.
</p>
<p><b>Using your plugin's INI file</b></p>
<p>Plugin INI files are not created until used, so even though the INI file name
is always defined for your plugin, it will not clutter up the directory if you
do not use it. The <b>INIFileName </b>variable is to be used as your
plugin's INI filename. Don't modify it, it's set for you to
MQ2MyPlugin.ini in the correct directory.</p>
<p><b>Adding Commands</b></p>
<p>Adding commands is incredibly simple with MQ2. Make your command
function with the standard prototype</p>
<p>VOID MyCommand(PSPAWNINFO pChar, PCHAR szLine)</p>
<p>Then, in InitializePlugin: <b>AddCommand("/mycommand",MyCommand);</b></p>
<p>and in ShutdownPlugin: <b>RemoveCommand("/mycommand");</b></p>
<p>Follow the pre-existing rules for coding your command function.</p>
<p><b>Adding Macro Parameters</b></p>
<p>Adding macro parameters is also incredibly simple. Make your param
function with the standard prototype</p>
<p>DWORD parmMyParm(PCHAR szVar, PCHAR szOutput, PSPAWNINFO pChar)</p>
<p>Then, in InitializePlugin: <b>AddParm("$myparm",parmMyParm);</b></p>
<p>and in ShutdownPlugin: <b>RemoveParm("$myparm");</b></p>
<p>Follow the pre-existing rules for coding your parameter function.</p>
<p><b>Adding Detours</b></p>
<p>Adding detours is almost equally simple.. but I'm going back to sleep very
soon and don't want to show how to do this at the moment. Take a look at
the existing plugins for examples.</p>
</body>
</html>