<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://datoolset.net/mw/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Obadiah</id>
		<title>Dragon Age Toolset Wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://datoolset.net/mw/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Obadiah"/>
		<link rel="alternate" type="text/html" href="http://datoolset.net/wiki/Special:Contributions/Obadiah"/>
		<updated>2026-04-24T08:39:35Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.25.6</generator>

	<entry>
		<id>http://datoolset.net/mw/index.php?title=Sound_and_music&amp;diff=17349</id>
		<title>Sound and music</title>
		<link rel="alternate" type="text/html" href="http://datoolset.net/mw/index.php?title=Sound_and_music&amp;diff=17349"/>
				<updated>2011-09-28T04:03:45Z</updated>
		
		<summary type="html">&lt;p&gt;Obadiah: /* Character soundsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sound in Dragon Age is packaged using a program called [[FMOD]]. FMOD sound banks include the audio waveform itself, and can also include settings determining how the sound is played.&lt;br /&gt;
&lt;br /&gt;
== Voice-over ==&lt;br /&gt;
&lt;br /&gt;
Voice over doesn't actually require you to work with FMOD, as the tools to package VO into FMOD sound banks are built into the toolset.&lt;br /&gt;
&lt;br /&gt;
Placeholder [[Voice-Over]] can be generated automatically by the toolset (using the default Microsoft text-to-speech engine that comes with your OS). This is intended as a way to easily produce a &amp;quot;rough cut&amp;quot; of a cinematic, giving an approximate feel for how long the line will last and allowing [[FaceFX]] to be generated.&lt;br /&gt;
&lt;br /&gt;
Recording real [[Voice-Over]] for [[conversation]]s is straightforward, though you'll need to keep track of the string IDs of the lines you're recording in order to give the wav files the proper filenames. &lt;br /&gt;
&lt;br /&gt;
== Placeable sound resources ==&lt;br /&gt;
&lt;br /&gt;
Other types of sound resources will require work with [[FMOD]] itself to get them into the game. See [[FMOD]] for details.&lt;br /&gt;
&lt;br /&gt;
Sound events are placed in an [[area]] layout using the area editor. Details such as how the sound loops, where the sound is simulated as coming from, and so forth, are defined in [[FMOD]].&lt;br /&gt;
&lt;br /&gt;
Areas can also have [[audio volume]]s, [[music volume]]s and [[reverb volume]]s defined, with associated sound events.&lt;br /&gt;
&lt;br /&gt;
== Adding sounds to animations ==&lt;br /&gt;
&lt;br /&gt;
The [[Blend tree editor]] allows sound events to be associated with an animation's timeline. So for example, an animation of a golem clapping could have a clanging sound added to the moment of impact of its hands.&lt;br /&gt;
&lt;br /&gt;
== Character soundsets ==&lt;br /&gt;
&lt;br /&gt;
Soundsets for characters (the collection of lines they choose from in combat and other routine in-game activities) are created as [[conversation]] resources, and are associated with individual creatures via a [[character]] resource. This allows one soundset to be reused for multiple different creatures. New soundsets can be created from templates listed in /_Core Soundsets/.&lt;/div&gt;</summary>
		<author><name>Obadiah</name></author>	</entry>

	<entry>
		<id>http://datoolset.net/mw/index.php?title=Sound_and_music&amp;diff=17348</id>
		<title>Sound and music</title>
		<link rel="alternate" type="text/html" href="http://datoolset.net/mw/index.php?title=Sound_and_music&amp;diff=17348"/>
				<updated>2011-09-28T04:03:11Z</updated>
		
		<summary type="html">&lt;p&gt;Obadiah: /* Character soundsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sound in Dragon Age is packaged using a program called [[FMOD]]. FMOD sound banks include the audio waveform itself, and can also include settings determining how the sound is played.&lt;br /&gt;
&lt;br /&gt;
== Voice-over ==&lt;br /&gt;
&lt;br /&gt;
Voice over doesn't actually require you to work with FMOD, as the tools to package VO into FMOD sound banks are built into the toolset.&lt;br /&gt;
&lt;br /&gt;
Placeholder [[Voice-Over]] can be generated automatically by the toolset (using the default Microsoft text-to-speech engine that comes with your OS). This is intended as a way to easily produce a &amp;quot;rough cut&amp;quot; of a cinematic, giving an approximate feel for how long the line will last and allowing [[FaceFX]] to be generated.&lt;br /&gt;
&lt;br /&gt;
Recording real [[Voice-Over]] for [[conversation]]s is straightforward, though you'll need to keep track of the string IDs of the lines you're recording in order to give the wav files the proper filenames. &lt;br /&gt;
&lt;br /&gt;
== Placeable sound resources ==&lt;br /&gt;
&lt;br /&gt;
Other types of sound resources will require work with [[FMOD]] itself to get them into the game. See [[FMOD]] for details.&lt;br /&gt;
&lt;br /&gt;
Sound events are placed in an [[area]] layout using the area editor. Details such as how the sound loops, where the sound is simulated as coming from, and so forth, are defined in [[FMOD]].&lt;br /&gt;
&lt;br /&gt;
Areas can also have [[audio volume]]s, [[music volume]]s and [[reverb volume]]s defined, with associated sound events.&lt;br /&gt;
&lt;br /&gt;
== Adding sounds to animations ==&lt;br /&gt;
&lt;br /&gt;
The [[Blend tree editor]] allows sound events to be associated with an animation's timeline. So for example, an animation of a golem clapping could have a clanging sound added to the moment of impact of its hands.&lt;br /&gt;
&lt;br /&gt;
== Character soundsets ==&lt;br /&gt;
&lt;br /&gt;
Soundsets for characters (the collection of lines they choose from in combat and other routine in-game activities) are created as [[conversation]] resources, and are associated with individual creatures via a [[character]] resource. This allows one soundset to be reused for multiple different creatures. New soundsets can be created from templates listed root of the /_Core Soundsets/.&lt;/div&gt;</summary>
		<author><name>Obadiah</name></author>	</entry>

	<entry>
		<id>http://datoolset.net/mw/index.php?title=UI_Tutorial_(draft)&amp;diff=16470</id>
		<title>UI Tutorial (draft)</title>
		<link rel="alternate" type="text/html" href="http://datoolset.net/mw/index.php?title=UI_Tutorial_(draft)&amp;diff=16470"/>
				<updated>2011-07-14T01:35:51Z</updated>
		
		<summary type="html">&lt;p&gt;Obadiah: /* Getting Information From The Engine */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Author's note''': STILL A WORK IN PROGRESS - FIRST DUMPING INFORMATION OUT, THEN I'LL FORMAT AND SECTION IT OFF BETTER. This isn't a very good tutorial, but as I said, I'm just trying to get the information out there and I'm slow to update this. Also, it may be simpler now that the UDK has support for GFX files, but I don't know the cross-licensing or technical situation on that right now.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The UI files are basically just version 8 Adobe Flash files, but extended with some extra properties and image handling (they even use nonstandard tags in the SWF for that). GFX files supposedly have more optimized fonts and who really knows what else, but you shouldn't have to worry about font embedding in Dragon Age.&lt;br /&gt;
&lt;br /&gt;
This means they use the older ActionScript 2.0, which you can find some learning resources on here [http://download.macromedia.com/pub/documentation/en/flash/fl8/fl8_learning_as2.pdf fl8_learning_as2.pdf] and here [http://livedocs.adobe.com/flash/9.0/main/flash_as2_learning.pdf flash_as2_learning.pdf], among other places scattered on the web. You can download the API reference, but a decent online location is [http://flash-reference.icod.de/ here] (faster than Adobe's site I find).&lt;br /&gt;
&lt;br /&gt;
For it to work in game, the U.I. element must be saved using the name of an existing U.I. file, as the engine will only run U.I. elements it is expecting. You can, however, leave the file extension as .swf and it will still run.&lt;br /&gt;
&lt;br /&gt;
=== Other information sources ===&lt;br /&gt;
There's a woefully incomplete GUI category on the wiki here [[:Category:GUI]]. It was an early effort at detailing some of the class specifics in the UI files. There are a lot of stubs, but some classes are more detailed.&lt;br /&gt;
&lt;br /&gt;
There's also a long-standing draft article on the profile page here [[User:FollowTheGourd]] about the conversation UI. It could also be ammended to explain things like 800x600 is treated as if it were 1024x768, and that the cutscene bars actually have a negative height if the screen width is much longer than the screen height, as seen with Eyefinity display setups.&lt;br /&gt;
&lt;br /&gt;
Another thing to realize is the game's aspect ratio correction and how one resolution in window mode will get stretched to fill your screen space in fullscreen mode. So then there's a difference between the Stage (Flash term) width and height and the video settings which you can access using the ExternalCommands ActionScript class. The point is that the Stage dimensions are more reliable than the video settings you can retrieve through the ExternalCommands class, although it doesn't stop the quickbar UI file from reading the attribute ''&amp;quot;ClientOptions.VideoOptions.ResolutionWidth&amp;quot;'' from it, but there might be a perfectly good reason for that like the engine notifying the GUI when it changes.&lt;br /&gt;
&lt;br /&gt;
== Toolchain ==&lt;br /&gt;
&lt;br /&gt;
[http://www.flashdevelop.org/ FlashDevelop IDE.]&lt;br /&gt;
etc&lt;br /&gt;
&lt;br /&gt;
== Organizing Sources ==&lt;br /&gt;
&lt;br /&gt;
Obtain an ActionScript 2.0 decompiler such as Sothink or Trillix. Each has their shortcomings and will require further post-processing. Sothink's ActionScript output will probably require more work to make compile with MTASC, but Trillix's output seems to have some stranger bugs I'll mention later, which makes me more hesitant to recommend it. Sothink's tool still seems to have an issue formatting double-precision values as single-precision, as detailed in the section below. [http://www.nowrap.de/flare.html Flare] is also a nice free tool to compare output against, but it unfortunately isn't in a format that you can simply recompile.&lt;br /&gt;
&lt;br /&gt;
[http://www.nowrap.de/flasm.html Flasm] is also a useful tool if you wish to examine the p-code directly (as a debug or learning aid perhaps), or even modify it that way.&lt;br /&gt;
&lt;br /&gt;
=== GFX to SWF ===&lt;br /&gt;
&lt;br /&gt;
If you want your changes to be compatible with a certain or the latest game patch, then you'll also have to first merge the appropriate [[GFX]] files. For example, to be compatible with game v1.03, you'll first need to extract the GFX files from guiexport.erf, and then from the patch000.erf, patch001.erf, and patch002.erf files found under C:\Program Files\Dragon Age\packages\core\patch. If you want to be compatible with v1.02a, then it should suffice to stop merging after patch001.erf.&lt;br /&gt;
&lt;br /&gt;
Then you want to change the first three bytes for the GFX to CWS and change the file suffix to SWF.&lt;br /&gt;
Example Python script:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
from __future__ import with_statement&lt;br /&gt;
# The first line is required if you get the following error when running the python script under 2.5.4/2.5.5&lt;br /&gt;
# SyntaxError: invalid syntax - with open(gfxPath, &amp;quot;rb+&amp;quot;) as gfxFile:&lt;br /&gt;
import glob&lt;br /&gt;
import os&lt;br /&gt;
import struct&lt;br /&gt;
&lt;br /&gt;
for gfxPath in glob.glob('*.gfx'):&lt;br /&gt;
	with open(gfxPath, &amp;quot;rb+&amp;quot;) as gfxFile:&lt;br /&gt;
		print(gfxPath)&lt;br /&gt;
		gfxFile.write(struct.pack('3s', &amp;quot;CWS&amp;quot;))&lt;br /&gt;
	os.rename(gfxPath, os.path.splitext(gfxPath)[0] + &amp;quot;.swf&amp;quot;) &lt;br /&gt;
		&lt;br /&gt;
line = input(&amp;quot;Press enter to exit.&amp;quot;)&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Obtain ActionScript Sources ===&lt;br /&gt;
&lt;br /&gt;
If you're using Sothink's tool, then here's an example of how you would quickly retrieve the ActionScript, if you've converted the GFX into SWFs as mentioned above. Do a multi-file export with all of the SWF files (merged to whichever patch version you wish). [http://i1002.photobucket.com/albums/af150/FollowTheGourd/sothink_swf.jpg Screen shot]&lt;br /&gt;
&lt;br /&gt;
=== Merge ActionScript Classes ===&lt;br /&gt;
&lt;br /&gt;
It's a good idea to create a single ActionScript library of all the game sources; that way you don't have to repeatedly make the same modifications for every SWF file that uses the same modified classes. As you'll see later when using the SWF injection method, that this doesn't make available all of the classes to every SWF file, but it's a way to avoid redundant editing.&lt;br /&gt;
&lt;br /&gt;
For instance, here's a embarrassingly quick and dirty way of doing it with a Python script:&lt;br /&gt;
''Note:'' this will throw an exception on later versions of Python because shutil.move undocumentedly doesn't want to clobber existing files. You could add a check if the file already exists and not move it - or rewrite the script and make something better.&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
from __future__ import with_statement&lt;br /&gt;
# The first line is required if you get the following error when running the python script under 2.5.4/2.5.5&lt;br /&gt;
# SyntaxError: invalid syntax - with open(gfxPath, &amp;quot;rb+&amp;quot;) as gfxFile:&lt;br /&gt;
# [Yes, this code probably sucks]&lt;br /&gt;
&lt;br /&gt;
import shutil&lt;br /&gt;
import os&lt;br /&gt;
import re&lt;br /&gt;
import zlib&lt;br /&gt;
&lt;br /&gt;
# Usage: have the batch exported ActionScript from the decompiler (say Sothink) in a dir called export. Then run this &lt;br /&gt;
# script at the same level as the export dir. It will create a C:\commonlib folder with the ActionScript merged into it.&lt;br /&gt;
# Left over in export is what you can import into a FlashDevelop project. You'll also want to make&lt;br /&gt;
# intrinsics out of export and commonlib, but commlib goes in the global classpath, while&lt;br /&gt;
# the appropriate export subfolder goes in the appropriate project classpath.&lt;br /&gt;
&lt;br /&gt;
mergedir = r'C:\commonlib'&lt;br /&gt;
scriptdict = {}&lt;br /&gt;
for dirpath, dirnames, filenames in os.walk('export'):&lt;br /&gt;
	print(dirpath)&lt;br /&gt;
	for junk in filter (lambda x: not x.endswith(&amp;quot;.as&amp;quot;), filenames):&lt;br /&gt;
		os.remove(os.path.join(dirpath, junk))&lt;br /&gt;
	for script in filter( lambda x : x.endswith(&amp;quot;.as&amp;quot;), filenames):&lt;br /&gt;
		scriptfile = open(os.path.join(dirpath, script))&lt;br /&gt;
		relativedir = re.sub(r'export\\[^\\]+\\?', '', dirpath)&lt;br /&gt;
		relativepath = os.path.join(relativedir, script)&lt;br /&gt;
		crc32 = zlib.crc32(scriptfile.read())&lt;br /&gt;
		scriptfile.close()&lt;br /&gt;
		sourcepath = os.path.join(dirpath, script)&lt;br /&gt;
		if relativepath in scriptdict:&lt;br /&gt;
			lastval = scriptdict[relativepath]&lt;br /&gt;
			if lastval['crc32'] == crc32:&lt;br /&gt;
				destdir = os.path.join(mergedir, relativedir)&lt;br /&gt;
				if os.path.exists(lastval['sourcepath']):&lt;br /&gt;
					os.remove(lastval['sourcepath'])&lt;br /&gt;
				if not os.path.exists(destdir):&lt;br /&gt;
					os.makedirs(destdir)&lt;br /&gt;
				#print(&amp;quot;move &amp;quot; + sourcepath + &amp;quot; to &amp;quot; + destdir)&lt;br /&gt;
				shutil.move(sourcepath, destdir)&lt;br /&gt;
			else:&lt;br /&gt;
				# There any many *Scene.as files that are the same&lt;br /&gt;
				# BUT there's an &amp;quot;emptyish&amp;quot; Scene.as used an as interface as well.&lt;br /&gt;
				# So you probably want Scene.as as common, but the other scenes as unique&lt;br /&gt;
				# even if they have the same name. Still throw if script is Scene.as but not if it ends with it.&lt;br /&gt;
				if not re.search(r'.Scene\.as$', script):&lt;br /&gt;
					raise Exception(&amp;quot;Same name, different CRC32: &amp;quot; + sourcepath)&lt;br /&gt;
		else:&lt;br /&gt;
			scriptdict[relativepath] = { 'crc32': crc32, 'sourcepath': sourcepath }&lt;br /&gt;
&lt;br /&gt;
# Find unique entries in SharedLibary, GUI, etc. Copy them over to commonlib but print out what we found.&lt;br /&gt;
# [Bit of a copy-pasta job here...]&lt;br /&gt;
for dirpath, dirnames, filenames in os.walk('export'):&lt;br /&gt;
	for script in filter (lambda x: x.endswith(&amp;quot;.as&amp;quot;), filenames):&lt;br /&gt;
		relativedir = re.sub(r'export\\[^\\]+\\?', '', dirpath)&lt;br /&gt;
		if relativedir == '':&lt;br /&gt;
			continue&lt;br /&gt;
		relativepath = os.path.join(relativedir, script)&lt;br /&gt;
		sourcepath = os.path.join(dirpath, script)&lt;br /&gt;
		destdir = os.path.join(mergedir, relativedir)&lt;br /&gt;
		if not os.path.exists(destdir):&lt;br /&gt;
			os.makedirs(destdir)&lt;br /&gt;
		print(&amp;quot;Unique commonlib: &amp;quot; + sourcepath)&lt;br /&gt;
		shutil.move(sourcepath, destdir)&lt;br /&gt;
&lt;br /&gt;
# Clean up empty dirs&lt;br /&gt;
for dirpath, dirnames, filenames in os.walk('export', topdown=False):&lt;br /&gt;
	for d in dirnames:&lt;br /&gt;
		try:&lt;br /&gt;
			os.rmdir(os.path.join(dirpath, d))&lt;br /&gt;
		except OSError:&lt;br /&gt;
			pass&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Making Modifications ==&lt;br /&gt;
=== Bugs and getting sources to compile ===&lt;br /&gt;
[ Note: this is mostly just copy and pasted from my post in another forum at the moment. It still needs some reworking to better explain things ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can first get the open source FlashDevelop IDE which comes with MTASC and the standard Flash library. If you have the SWFs and the ActionScript *.as files, then what you can do is create an empty ActionScript 2 project, in the project settings turn off &amp;quot;use main entry point&amp;quot; and under the project &amp;quot;injection&amp;quot; tab, point it to the SWF you want to update with your new ActionScript.&lt;br /&gt;
&lt;br /&gt;
You'll also want to update the project classpaths to point to your game's ActionScript library. Just in my experience, there seem to be some properties on some of the standard classes that would normally prevent the script from compiling - but in that case what you can do is modify the so-called intrinsic files to let the compiler know about them. E.g., you can add needed function and var declarations to the intrinsic class interfaces under C:\Program Files\FlashDevelop\Tools\mtasc. The nice thing about ActionScript and intrinsics is that (unless used as a case value in a switch-statement) you don't even need to know the values of these &amp;quot;missing&amp;quot; properties or functions if they're basically defined in the runtime environment. E.g., Mouse.LEFT isn't standard Flash, but if you edit Mouse.as and add '''static var LEFT;''' to the intrinsic class definition, then you're good to go, as the value gets looked up during execution like a dictionary value (in fact, Mouse[&amp;quot;LEFT&amp;quot;] should yield the same result).&lt;br /&gt;
&lt;br /&gt;
Also if you press Ctrl+J you'll get the type explorer where you can right click on a folder (that you've added to your classpath) and select &amp;quot;convert to intrinsic&amp;quot;. So this way you only need to compile the actual *.as file you're making changes to and keep the others around as intrinsics. Using the IDE's SWF injection I mentioned above will make it so you don't have to worry about recompiling everything.&lt;br /&gt;
&lt;br /&gt;
You'll probably get a bunch of warnings like &amp;quot;... needs the class &amp;lt;Whatever&amp;gt; which was not compiled&amp;quot; but that's just MTASC not liking how some class names are used outside of what you're compiling like in Flash registerObject calls.&lt;br /&gt;
&lt;br /&gt;
Now the bigger issue is that MTASC is pickier about things than Adobe's compiler. You'll often have to write this.varname or ClassName.varname instead of just varname, and MTASC doesn't like named *nested* functions. So you'll sometimes have to convert function FooBar() { ... } into something like &amp;quot;this.FooBar = function() { };&amp;quot; or &amp;quot;_root.FooBar = function() { };&amp;quot;. But also make sure that the variable for the function is a class member and not function-local or it'll just be a register or randomly named variable when compiled, or just not be available in the scope you need it to be.&lt;br /&gt;
&lt;br /&gt;
MTASC is also pickier about the scope of local variables. It may sound weird, but in ActionScript 2.0 a function-local variable is defined for the scope of the function - it doesn't matter if declared in an if-statement or in braces. But the MTASC compiler will enforce that you define the variable in a &amp;quot;proper&amp;quot; scope, so you may need to move where it's declared if you want things to compile. E.g., &amp;quot;if (foo) { var tmp = 1; } else { tmp = 2; }&amp;quot; won't fly with MTASC.&lt;br /&gt;
&lt;br /&gt;
Also it seems like MTASC doesn't like the global function &amp;quot;Array&amp;quot;, but doesn't mind if you use the constructor instead. E.g., I've had issues with var ar = Array(...), but var ar = new Array(...) works or you could use the square-bracket notation instead.&lt;br /&gt;
&lt;br /&gt;
Some other stuff... if you want multiple projects, just create the projects all in the same dir (but create folders if you want to separate stuff and adjust the project classpath accordingly).&lt;br /&gt;
Also, don't necessarily set &amp;quot;Always compile&amp;quot; for the *.as file or you might run into duplicate definition errors - things should get drawn in as needed, but I think you need to set it for classes in the original SWF you wish to update. That might be a little hit and miss at first, but you can always check to make sure your changes got in.&lt;br /&gt;
&lt;br /&gt;
Also, looking at the output in FLASM, MTASC might not generate the most blazing bytecode ever - but neither does Adobe's compiler. Just some things I noticed is that Adobe's will use function argument registers more than MTASC seems to... e.g., &amp;quot;push '_root'; getVariable&amp;quot; vs just a r:_root register.&lt;br /&gt;
&lt;br /&gt;
Another apparent annoyance with MTASC is that it doesn't seem to recognize some global variables (which you can confirm with flasm's output (push 'somevar'; getVariable). Workarounds include ''_global.someVariable'', or sometimes ''_root.someVariable'' as appropriate.&lt;br /&gt;
&lt;br /&gt;
One last thing... you may want to organize your *.as files so you combine the ones that are commonly used across different SWF files so you're not always having to edit multiple copies of SomeClass.as for each SWF that uses it.&lt;br /&gt;
&lt;br /&gt;
Also, I noticed a bug in sothink that I emailed them about: doubles are formatted as single-precision floating point. But some other tools, e.g., flare, get the value correctly. You might want to search your *.as files for &amp;quot;E-&amp;quot; and &amp;quot;E+&amp;quot; to look for these misformatted values if you're using it.&lt;br /&gt;
&lt;br /&gt;
EDIT: Here's a bug with Trillix I noticed, but they said it'll be fixed soon: if you have &amp;quot;var foo = this&amp;quot; and if a register is used for 'foo', then Trillix doesn't properly initialize the register... but instead just uses 'this' everywhere else. This causes problems if you needed that variable to choose between using 'this' and possibly another object. E.g., &amp;quot;var obj = this; if (something) { obj = someOtherObject; } someFunc.doIt(obj);&amp;quot; only works as long as &amp;quot;obj&amp;quot; is stored as a variable and not a register, which is up to the original compiler. In reply, they mentioned that you could work around that issue by turning off the &amp;quot;ActionScript 'Recover arguments' names&amp;quot; setting, which makes it a bit more difficult to keep track of function arguments, so it's less than ideal.&lt;br /&gt;
&lt;br /&gt;
=== Getting Information From The Engine ===&lt;br /&gt;
It is possible to get information from the engine using the ExternalCommands class. More on this class can be found at [[ActionScript:ExternalCommands|External Commands]]. Of particular interest is [[ActionScript:ExternalCommands.GetValue|GetValue]]&lt;br /&gt;
&lt;br /&gt;
=== Issues displaying custom MovieClip subclasses ===&lt;br /&gt;
'''Note:''' this tries to explain some of the issues, and isn't suggesting best practices. This is a bit rambling and should be presented with more concrete examples. Ideally it wouldn't be needed at all and we could use the Scaleform SDK to convert our SWFs into GFX, or we could splice in our own movieclip symbol tags into the GFX file.&lt;br /&gt;
&lt;br /&gt;
The simple issue is this: if it wasn't originally created in the Flash designer (also having a symbol in the Flash library), then you'll have a harder time of showing custom MovieClip objects through ActionScript alone. This would appear to be a bug, but speculatively, it could be for performance reasons.&lt;br /&gt;
&lt;br /&gt;
==== Using swfmill ====&lt;br /&gt;
This hasn't been thoroughly tested, but swfmill may be a simple way to add you own symbols. Use swfmill to convert the SWF into an XML file, edit it, and then use swfmill to convert it back. It appears to work, and even properly retains the non-standard SWF tags. For custom class behavior, you'll still need to make an ''Object.registerClass'' call to associate the library symbol with the class. If you do use this method, one thing to make sure of is that the embedded textures display properly, since they're being referred to using a non-standard SWF tag.&lt;br /&gt;
&lt;br /&gt;
==== createEmptyMovieClip method ====&lt;br /&gt;
So until splicing in tags becomes more streamlined, or some other method is found, then it may be easier to just create an empty movieclip and then populate the member fields using a mixin from another class or manually, although that's probably still less than ideal for classes that use the onLoad event. Another thing as mentioned below is the possibility of abusing prototype mechanics (which can be somewhat messy) or subclass an existing class to specialize the beha&lt;br /&gt;
&lt;br /&gt;
It would appear that the ''MovieClip'' method ''createEmptyMovieClip'' is of limited use unless you then load another movieclip (such as an icon image) into it or or do a ''beginFill ... endFill'' ('''fill-code''') for a few frames to define its dimensions, filling it for as many frames until, say, its '''_height''' property becomes non-zero. It's ugly, but works. Also, if you do a fill on an object in the library, then you actually affect its '''_xscale''' and '''_yscale''' by making the object stretch to fit into your fill. Ultimately, it'd probably be less of a hassle to alter the SWF file to insert your object. Because of having to rerun the code, you'll probably want to delay having to reload images or other intensive operations. You'll have to rerun the fill-code at least twice for this to work, timing alone doesn't matter as has been determined through trial and error.&lt;br /&gt;
&lt;br /&gt;
==== attachMovie method ====&lt;br /&gt;
Perhaps a simpler way is to use ''attachMovie'', although you'll have to find a pre-existing movieclip symbol that suites your needs, and if you want to change its default dimensions then you'll have to delay the fill-code for a few (let's say 150 or so since the scene began) frames after the game loads until it actually works. '''NOTE:''' Reconfirm this is actually necessary instead of just being able to set the _height/_width/_xscale/_yscale, although you may still need to delay setting those for the change to take effect. This way you shouldn't have to keep rerunning the fill-code as with the above ''createEmptyMovieClip'' method. This whole delay business is probably more of an issue in UI elements that are on the HUD instead of selected later from the navbar. You can probably check for when you've waited enough frames by running some simple fill-code on an empty movieclip and checking whether the '''_height''' property changes. &lt;br /&gt;
E.g., the PieCooldown symbol exists in the quickbar.swf file and isn't the worst choice for an empty MovieClip. You can use programs like swix, swfmill, and probably others to find simple objects without much embedded graphics.&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
private static var EMPTYMC_LINKID:String = &amp;quot;PieCooldown&amp;quot;;	&lt;br /&gt;
var mc:MovieClip = someClip_mc.attachMovie(EMPTYMC_LINKID, &amp;quot;SomeName_mc&amp;quot;, someClip_mc.getNextHighestDepth(), {_x:10, _y:10});&lt;br /&gt;
&lt;br /&gt;
// Changing the default dimensions of &amp;quot;PieCooldown&amp;quot;&lt;br /&gt;
// Although you can probably just change the _height, _width or scales after the&lt;br /&gt;
// needed delay instead, unlike with the createEmptyMovieClip method apparently.&lt;br /&gt;
// Also not really necessary if you just want to use it as an invisible container,&lt;br /&gt;
// since other items can be positioned outside of it, relative to its local &lt;br /&gt;
// coordinates.&lt;br /&gt;
with(mc)&lt;br /&gt;
{&lt;br /&gt;
   beginFill(0, 0); // alpha is zero.&lt;br /&gt;
   moveTo(0, 0);&lt;br /&gt;
   lineTo(21, 0);&lt;br /&gt;
   lineTo(21, 21);&lt;br /&gt;
   lineTo(0, 21);&lt;br /&gt;
   endFill();	&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The game's script sources also come with a ''MovieUtils'' class, which has a wrapper around ''attachMovie''. This can be useful to create an instance of a library symbol in the SWF file and use it instead for another purpose. &lt;br /&gt;
&lt;br /&gt;
Other useful workaround would be abusing prototype mechanics of ActionScript to give an already existing class other behavior if desired, and can be switched using a custom argument for the initObject during the attachMovie call. This way you don't have to edit the actual class file, if making it recompile is problematic or time consuming. Although this is a kludge method of doing it.&lt;br /&gt;
&lt;br /&gt;
Also of note is that ''Object.registerClass'' or the so-called [http://www.google.com/search?hl=en&amp;amp;source=hp&amp;amp;q=attachMovie+__packages+trick __Packages trick] won't really get you anywhere either. You'll be able to create the MovieClip subclass, but it won't display properly (or just differently) without the above-mentioned tricks.&lt;br /&gt;
&lt;br /&gt;
Creating a subclass of an existing class that's registered with ''Object.registerClass'' may also be a convenient way to customize class behavior without having to recompile the base class if you then change the registerClass call to use the subclass.&lt;/div&gt;</summary>
		<author><name>Obadiah</name></author>	</entry>

	<entry>
		<id>http://datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16468</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16468"/>
				<updated>2011-07-13T16:16:47Z</updated>
		
		<summary type="html">&lt;p&gt;Obadiah: /* Capture the EVENT_TYPE_PARTYMEMBER_ADDED Event */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Simple Follower Creation ==&lt;br /&gt;
&lt;br /&gt;
Follow these steps to create a follower that&lt;br /&gt;
&lt;br /&gt;
- Levels up with a default package&lt;br /&gt;
&lt;br /&gt;
- Can be chosen from the party picker&lt;br /&gt;
&lt;br /&gt;
- Can gain XP&lt;br /&gt;
&lt;br /&gt;
This guide assumes you know how to create a creature and are comfortable with basic scripting.&lt;br /&gt;
&lt;br /&gt;
You should only use this simple method if you are sure there will be empty space in the active party when your follower is recruited.&lt;br /&gt;
&lt;br /&gt;
A more comprehensive approach when there are more than three potential party members is discussed in the FAQ below. It's worth taking the time to understand the basics first, though. &lt;br /&gt;
&lt;br /&gt;
=== Create the creature ===&lt;br /&gt;
&lt;br /&gt;
Create a creature to act as your follower.  Set its name, appearance, gender, head morph, conversation, inventory etc as you want them to behave in-game.&lt;br /&gt;
&lt;br /&gt;
Set an appropriate '''Tag''' (you'll be using it a lot).  I suggest &amp;quot;party_charname&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Make sure you choose a '''Class'''.  For most followers this should be Rogue, Warrior or Wizard.&lt;br /&gt;
&lt;br /&gt;
[[File:class.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Under Package/Scaling set:&lt;br /&gt;
&lt;br /&gt;
'''General Package Type''' to be '''Party Members'''&lt;br /&gt;
&lt;br /&gt;
'''Package''' to be an appropriate value (probably &amp;quot;Generic - Wizard&amp;quot; or similar)&lt;br /&gt;
&lt;br /&gt;
'''Package AI''' (there should only be one choice)&lt;br /&gt;
&lt;br /&gt;
'''Rank''' to be '''Player'''&lt;br /&gt;
&lt;br /&gt;
[[File:package.jpg]]&lt;br /&gt;
&lt;br /&gt;
Save and export your character as normal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Overlay char_stage ===&lt;br /&gt;
&lt;br /&gt;
In the official campaign, the party picker uses a special area called char_stage. Whether you're extending the official campaign or making a standalone campaign, there is a function that allows you to overlap the offical stage with your own, so that both stages are active simultaneously in game.&lt;br /&gt;
&lt;br /&gt;
In your resource palette, right-click char_stage under the Global folder and select Duplicate to make a copy of the stage with a new resource name, e.g. my_char_stage. In the resource properties, ensure that both Module and Owner Module are set to your module, and the folder of your choice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:area_palette.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create a new waypoint for your follower to appear on the party picker.  This waypoint '''must''' have a tag in the form of &amp;quot;char_&amp;quot; followed by the exact tag of your follower.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:char_stage.jpg]]&lt;br /&gt;
&lt;br /&gt;
In this example the tag of my follower is '''bc_party_miera''' so her waypoint tag must be '''char_bc_party_miera'''&lt;br /&gt;
&lt;br /&gt;
For a standalone module (such as in this example), put your waypoint wherever you please.  The illustrated one is directly on top of Morrigan's.  For an add-in to the main campaign, you should position your wp appropriately relative to the core party members.&lt;br /&gt;
&lt;br /&gt;
Save and export the area.&lt;br /&gt;
&lt;br /&gt;
Add the following to your module event script:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
case EVENT_TYPE_MODULE_GETCHARSTAGE:&lt;br /&gt;
{&lt;br /&gt;
   // Overlay the existing stage with my stage&lt;br /&gt;
   // &amp;quot;my_char_stage&amp;quot; is the resource name of the overlay area&lt;br /&gt;
   // &amp;quot;partypicker&amp;quot; is the name of the default GDA&lt;br /&gt;
   SetPartyPickerStage(&amp;quot;my_char_stage&amp;quot;, &amp;quot;partypicker&amp;quot;);&lt;br /&gt;
   break;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create m2DAs for the Party Picker ===&lt;br /&gt;
&lt;br /&gt;
You will need to create two Excel spreadsheets.&lt;br /&gt;
&lt;br /&gt;
The first should be named (both worksheet and file) '''partypicker_''' with a unique suffix.  In this example, my first spreadsheet is named partypicker_fofbc.xls with a worksheet name of partypicker_fofbc - the suffix being the acronym of my module.&lt;br /&gt;
&lt;br /&gt;
Set up your columns as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:partypickerm2da.jpg]]&lt;br /&gt;
&lt;br /&gt;
The '''ID''' for your follower must be '''12 or higher'''.  11 is the highest value used in the base 2DA.  12 is fine for standalone modules, add-ins will probably want to use an arbitrarily high number to avoid potential conflicts.&lt;br /&gt;
&lt;br /&gt;
The '''Label''' should be the follower's name as you wish it to appear on the party picker.&lt;br /&gt;
&lt;br /&gt;
The '''Tag''' must be your follower's tag.&lt;br /&gt;
&lt;br /&gt;
All other values are non-functioning defaults and should be specified as in the image above unless you know explicitly what you're doing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NOTE - ON SELECTION ANIMATIONS'''&lt;br /&gt;
 &lt;br /&gt;
Add Animation and Remove Animation are actually Id numbers of different animations, taken from anim_base.gda&lt;br /&gt;
&lt;br /&gt;
Enter and Exit version of animations are generally the best ones to use, altough one can try others. NOT ALL ANIMATIONS WILL WORK, since some require special conditions.&lt;br /&gt;
Here are some examples you can use:&lt;br /&gt;
&lt;br /&gt;
819 - talk cursing&lt;br /&gt;
&lt;br /&gt;
629 - reading a book (doesn't work, since it probably requires a book object)&lt;br /&gt;
&lt;br /&gt;
844 - hands behind back (848 and 849 are Enter and Exit versions respectfully)&lt;br /&gt;
&lt;br /&gt;
850 - chest pounding salute&lt;br /&gt;
&lt;br /&gt;
811 - fist pounding&lt;br /&gt;
&lt;br /&gt;
277 - dance&lt;br /&gt;
&lt;br /&gt;
247 - cast area spell&lt;br /&gt;
&lt;br /&gt;
500 - vfx cast&lt;br /&gt;
&lt;br /&gt;
600 - surprised&lt;br /&gt;
&lt;br /&gt;
603 - praying&lt;br /&gt;
&lt;br /&gt;
607 - head bow&lt;br /&gt;
&lt;br /&gt;
609 - standing at attention&lt;br /&gt;
&lt;br /&gt;
651,652 - crouch pray (Enter and exit)&lt;br /&gt;
&lt;br /&gt;
808 - point forward&lt;br /&gt;
&lt;br /&gt;
825 - nodding&lt;br /&gt;
&lt;br /&gt;
840 - hand chop or frustration&lt;br /&gt;
&lt;br /&gt;
905,906 - crouch (Enter, Exit)&lt;br /&gt;
&lt;br /&gt;
919,920 - sit on ground (enter, exit)&lt;br /&gt;
&lt;br /&gt;
965 - kneel down loop&lt;br /&gt;
&lt;br /&gt;
972 - wipe nose&lt;br /&gt;
&lt;br /&gt;
976,977 - squat (Enter, Exit)&lt;br /&gt;
&lt;br /&gt;
986 - wipe eyes&lt;br /&gt;
&lt;br /&gt;
998,999 - hands clasped (Enter, exit)&lt;br /&gt;
&lt;br /&gt;
3029 - inspect nails&lt;br /&gt;
&lt;br /&gt;
3031,3032 - playful (enter, exit)&lt;br /&gt;
&lt;br /&gt;
3054,3056 - slouch (enter, exit)&lt;br /&gt;
255 - in-place fly&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NOTE - ON SELECTION VFX''' &lt;br /&gt;
&lt;br /&gt;
The VFX column is the ID of the vFX effect taken from vFx_base.gda. This one is a bit more tricky, since it also references the BlendTree value from the same file.&lt;br /&gt;
Find the ID of the spell effect and look for the BlendTreeName column (should the the 12th columun) and enter BOTH into the respective columns for your character in the partypicker file.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
ID      ---      BLENDTREENAME      ---   EFFECT&lt;br /&gt;
&lt;br /&gt;
6039    ---     fxm_energy_up_p    ---    Lady of the Forest pillar of light&lt;br /&gt;
&lt;br /&gt;
6040    ---     fxm_power_in_p      ---   Branka - power in&lt;br /&gt;
&lt;br /&gt;
3054    ---     fxc_lotf_c          ---   Lady of the Forest - swirling leaves&lt;br /&gt;
&lt;br /&gt;
3009    ---     fxc_succubus_c     ---    Succubus crust&lt;br /&gt;
&lt;br /&gt;
1549    ---     fxa_hly_imp_c       ---   Holy Impact crust&lt;br /&gt;
&lt;br /&gt;
1076    ---     fxa_spi_aur_mht_c   ---   Spirit - Aura Might crust&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second spreadsheet should be named '''party_picker_''' (note middle underscore).  Once again append your unique suffix (in this example party_picker_fofbc.xls with party_picker_fofbc as its worksheet).&lt;br /&gt;
&lt;br /&gt;
Set up your columns and data like so:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:party_pickerm2da.jpg]]&lt;br /&gt;
&lt;br /&gt;
'''ID''' and '''Tag''' should match what you did in the first spreadsheet.  Specify INVALID COLUMN for the third column.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you're familiar with m2DAs, generate them from these files, copy them to your module's override directory, and skip to the next step.  Otherwise, read on:&lt;br /&gt;
&lt;br /&gt;
- Go to '''\Program Files\Dragon Age\tools\ResourceBuild\Processors''' (or wherever you installed Dragon Age)&lt;br /&gt;
&lt;br /&gt;
- Copy '''ExcelProcessor.exe''' from that folder to whichever folder has the excel sheets you just created.&lt;br /&gt;
&lt;br /&gt;
- Drag and drop your xls files onto ExcelProcessor.  This will create .gda files.&lt;br /&gt;
&lt;br /&gt;
- Copy these .gda files to your module's export directory (probably \Documents\Bioware\Dragon Age\AddIns\yourModule\module\override\toolsetexport).  Make sure they are included in your .dazip when the time comes to build your module.&lt;br /&gt;
&lt;br /&gt;
If you are an OpenOffice user and have trouble with ExcelProcessor, you can use [http://social.bioware.com/project/755/ GDApp] to directly create the 2DAs.  It rocks!&lt;br /&gt;
&lt;br /&gt;
=== Capture the EVENT_TYPE_PARTYMEMBER_ADDED Event ===&lt;br /&gt;
&lt;br /&gt;
Amusingly enough, the Party Picker does not actually add followers to the party.  However it raises an event that allows you to do so.  Your module script needs to capture this event and execute some code.&lt;br /&gt;
&lt;br /&gt;
The following example shows what to do with the event.  The full script would work as a module script for an add-in (assuming it didn't need to do anything else), but otherwise you'll have to incorporate the event into your own module script.  &lt;br /&gt;
&lt;br /&gt;
If you're not sure how to set a module script, go to '''File''' then '''Manage Modules,''' select your module and click '''Properties.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEventType = GetEventType(ev);&lt;br /&gt;
    switch(nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);  //Allows the follower to gain XP&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));   //Ensures follower appears at PC's location.&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);  //Adds follower to the active party&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE)''' is the key statement to add the follower to the active party.  You must have this.&lt;br /&gt;
&lt;br /&gt;
'''SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0)''' is a bug-fix, as followers hired with UT_HireFollower() do not receive XP by default.  This statement fixes that, and I consider it best practice to keep it in this event to ensure it is always set.  You will not wish to do this if you want a follower that should not gain XP to be on the party picker.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that you do not need to intercept the corresponding event for a party member being removed - the party picker handles spawning/despawning, and thus will successfully remove members.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remember to save and export your module script.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you're not sure how to set a module script, go to '''File''' then '''Manage Modules,''' select your module and click '''Properties.'''  The module script is in the General category, as seen below:&lt;br /&gt;
&lt;br /&gt;
[[File:module_script.jpg]]&lt;br /&gt;
&lt;br /&gt;
You can set this to any script you've created.  See [[Scripting tutorial]] and [[Character generation]] for more background and some simple examples of event-handling scripts.  In general, you will want to make sure standalone module scripts pass events through to module_core (as in the [[Character generation]] examples) and add-in scripts do not (as in the example above).&lt;br /&gt;
&lt;br /&gt;
=== Create Your Hiring Script ===&lt;br /&gt;
&lt;br /&gt;
Now all that remains is to actually hire the follower :)&lt;br /&gt;
&lt;br /&gt;
Create a script to handle the hiring (which will most likely be fired from a conversation).  The script is quite simple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
        object oFollower = GetObjectByTag(&amp;quot;bc_party_miera&amp;quot;); //Use CreateObject() if the creature isn't present in the module yet&lt;br /&gt;
&lt;br /&gt;
        UT_HireFollower(oFollower);   //Hires the follower&lt;br /&gt;
&lt;br /&gt;
        SetPartyPickerGUIStatus(2);&lt;br /&gt;
&lt;br /&gt;
        ShowPartyPickerGUI();  //Shows the Party Picker; necessary for the follower to gain XP&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure you use your own follower's tag and not the example one :)&lt;br /&gt;
&lt;br /&gt;
This script fires the party picker after hiring the follower.  That is absolutely necessary via this method, as we have put the XP fix onto an event fired by the party picker.  You cannot put the XP fix into this script, it must be called from a later one (the bug is caused by an errant call to an event in player_core, which will be executed AFTER this script).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The easiest way to use this script is directly from conversation, putting it as an action on a line of dialogue where the PC invites the follower to join them.  If you're not sure how to associate a script with a dialogue line, see the following image:&lt;br /&gt;
&lt;br /&gt;
[[File:hire_conv.jpg]]&lt;br /&gt;
&lt;br /&gt;
Create your dialogue as normal, select the line you want to fire the script, and click the '''Plots and Scripting''' tab.  Use the '''Script''' file chooser in the Action section to browse to the script you created.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If everything worked, you should see something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:picker_success.jpg|thumb|200px|center]]&lt;br /&gt;
&lt;br /&gt;
== Advanced Follower Creation ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow these steps to have full control over the creation of your follower, with options such as:&lt;br /&gt;
&lt;br /&gt;
- Unique level-up template&lt;br /&gt;
&lt;br /&gt;
- Class and specialisation chosen via script&lt;br /&gt;
&lt;br /&gt;
- Any starting state&lt;br /&gt;
&lt;br /&gt;
- Level higher than the PC&lt;br /&gt;
&lt;br /&gt;
- Starts with a specialisation point rather than a specific specialisation&lt;br /&gt;
&lt;br /&gt;
- Set plot flags in the call to the hire script&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Prepare Creature, char_stage and Party Picker m2DAs ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow the same steps to create your follower creature, char_stage and Party Picker m2DAs as above.&lt;br /&gt;
&lt;br /&gt;
=== Create Party Plot ===&lt;br /&gt;
&lt;br /&gt;
While not necessary, it's very helpful to have plot flags set when a follower is hired or joins/leaves the active party.  This makes conversation interjections and the like very easy.&lt;br /&gt;
&lt;br /&gt;
Create a plot with appropriate flags.  There's no real need to associate journal text with them:&lt;br /&gt;
&lt;br /&gt;
[[File:follower_plot.jpg]]&lt;br /&gt;
&lt;br /&gt;
See FAQ for an alternative approach to plots when there are more than three potential party members.&lt;br /&gt;
&lt;br /&gt;
=== Add Plot Flags to Party Picker Event Intercept ===&lt;br /&gt;
&lt;br /&gt;
We then update our module script to make use of that plot, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_bc_create_party&amp;quot;   //make sure you include your own plot, not mine&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEventType = GetEventType(ev);&lt;br /&gt;
    switch(nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&lt;br /&gt;
&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));   //Ensures follower appears at PC's location.&lt;br /&gt;
            &lt;br /&gt;
            if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               //You must explicitly test for your follower's tag.&lt;br /&gt;
                WR_SetPlotFlag(PLT_BC_CREATE_PARTY, PARTY_MIERA_IN_PARTY, TRUE);     //Make sure you use your own flags!&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            break;&lt;br /&gt;
        }  &lt;br /&gt;
        &lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_DROPPED:                    &lt;br /&gt;
        {&lt;br /&gt;
              object oFollower = GetEventObject(ev, 0); &lt;br /&gt;
              &lt;br /&gt;
              if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) { &lt;br /&gt;
                WR_SetPlotFlag(PLT_BC_CREATE_PARTY, PARTY_MIERA_IN_PARTY, FALSE);     //As above, but set false.&lt;br /&gt;
              }&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create a Level Up Template ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can skip this step if you're content to use one of the generic Rogue, Wizard or Warrior templates, but I don't recommend it.  Making a template that suits your character is easy and will almost always be better for the player than a generic one that spends points poorly.&lt;br /&gt;
&lt;br /&gt;
Go to \Program Files\Dragon Age\tools\Source\2DA (or wherever you installed Dragon Age).&lt;br /&gt;
&lt;br /&gt;
You should see a number of excel sheets of the form '''ALCharacter.xls''' (such as ALAlistair.xls, ALLeliana.xls, ALRogue_Default.xls etc).  Open the one closest to your character (ie Morrigan or Wynne for a wizard, Leliana or Zevran for a rogue).  Save a copy as '''ALYourcharacter.xls''' in whatever directory you're using to create your 2DAs, remembering to rename the worksheet '''ALYourcharacter''' (in this example, ALMiera.xls with ALMiera as its worksheet).&lt;br /&gt;
&lt;br /&gt;
It should look something like this:&lt;br /&gt;
&lt;br /&gt;
[[File:ALtable.jpg|thumb|500px|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Columns B''' and '''C''' are the talents/spells available to this character.  Do not change them.&lt;br /&gt;
&lt;br /&gt;
'''Columns F''' and '''G''' are the skills available to this character.  Do not change them.&lt;br /&gt;
&lt;br /&gt;
We will edit the remaining columns like so:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Setting Stat Weights ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The stat weights in '''column J''' determine how the follower will spend their attribute points, in a rough ratio.  So if Dexterity is set to 1.5 and Intelligence to 1, you should expect to see 3 points of Dex for every 2 points of Cunning in-game (note Intelligence is the label used in the toolset for Cunning).&lt;br /&gt;
&lt;br /&gt;
Simply change the values in J to reflect how you'd like the character to spend their points.  In this example we're creating a wizard, so we're not going to mess around:&lt;br /&gt;
&lt;br /&gt;
[[File:miera_stat_weights.jpg]]&lt;br /&gt;
&lt;br /&gt;
This character will only raise magic.  I set the value to 5 rather than something like 1 to provide room underneath for the other stats while still overwhelmingly favouring magic, but in practice I only really ever want that one stat. &lt;br /&gt;
&lt;br /&gt;
In a note left on this column in the existing templates, Bioware's Georg Zoeller writes, &amp;quot;This is the weight of each attribute (row id links into properties.xls.id). 1.0 means 'try to keep this attribute level' (spend 1 point per level). 0.5 means 'try to spend 1 point every two levels' and so on.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The default Mage, Rogue and Warrior templates include '''column L''' labeled &amp;quot;AttInit.&amp;quot; Editing these values seems to have no effect on followers set to use these templates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Setting Talent and Skill Priorities ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Columns D''' and '''E''' are the talents/spells that the character will buy, in preference order from top to bottom.&lt;br /&gt;
&lt;br /&gt;
'''Columns H''' and '''I''' are the skills that the character will buy, in preference order from top to bottom.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To change these, just copy the appropriate two cells from columns B&amp;amp;C or F&amp;amp;G over the ones you want to replace.&lt;br /&gt;
&lt;br /&gt;
For example, here we're copying Morrigan's template.  Morrigan has Spider Shape high in her preferences, which we do not want.&lt;br /&gt;
&lt;br /&gt;
[[File:AlMori_talent_pref.jpg]]&lt;br /&gt;
&lt;br /&gt;
We decide we'd prefer Flame Blast, so we find it in columns B&amp;amp;C and copy both cells:&lt;br /&gt;
&lt;br /&gt;
[[File:ALMori_copy.jpg]]&lt;br /&gt;
&lt;br /&gt;
Then we select the cells we want to replace in columns D&amp;amp;E and paste over them:&lt;br /&gt;
&lt;br /&gt;
[[File:ALMori_paste.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Continue this process until your priorities list for both skills and talents/spells is exactly as you want it.  Make sure you have at least as many priorities as the core follower you're copying - points that cannot be spent according to these priorities have a habit of vanishing.&lt;br /&gt;
&lt;br /&gt;
If you used any abilities from a specialisation, make sure you remember to set that specialisation with the function we'll introduce later.  The autolevel scripts will add specialisation abilities to a character regardless of whether they have that spec or not.&lt;br /&gt;
&lt;br /&gt;
==== Create a M2DA_base_ m2DA ====&lt;br /&gt;
&lt;br /&gt;
Dragon Age will need to know where to find your autolevel template.  We tell it by extending M2DA_base.gda&lt;br /&gt;
&lt;br /&gt;
Create a spreadsheet with the name and worksheet name in the form '''M2DA_base_''' with your unique suffix (in this example, M2DA_base_fofbc.xls with M2DA_base_fofbc as a worksheet).&lt;br /&gt;
&lt;br /&gt;
Set up its columns and data like so (note I used GDApp because Open Office wasn't cooperating for this one!):&lt;br /&gt;
&lt;br /&gt;
[[File:m2da_base_fofbc.jpg]]&lt;br /&gt;
&lt;br /&gt;
The '''ID''' should be very high to avoid conflicts.  I've arbitrarily chosen 50,000+ here.  Carefully note the ID you've chosen for your character, you will need it later.&lt;br /&gt;
&lt;br /&gt;
Set the '''Label''' and '''Worksheet''' to be the name of your autolevel template worksheet (ALCharactername if you've been following this).&lt;br /&gt;
&lt;br /&gt;
Set the '''PackageIDForAI''' to be 0, it shouldn't be needed for followers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you're done, use ExcelProcessor to make GDAs of both spreadsheets and copy them to your module's export folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
FOR AUTOLEVEL TO WORK AFTER RECRUITING:&lt;br /&gt;
&lt;br /&gt;
Look in packages.xls. &lt;br /&gt;
There is a column called LevelupTable. That links to a corresponding AL* table. For instance,  row 81 is for Leliana. Her LevelupTable value is 258. If you look that up in 2DA_base, you'll see it links to ALLeliana.&lt;br /&gt;
(alternatively, you could try packages_base.gda)&lt;br /&gt;
&lt;br /&gt;
=== Create a New Hire Function Include ===&lt;br /&gt;
&lt;br /&gt;
This section is probably only relevent if you have a specific need to override the functionality of player_core.&lt;br /&gt;
&lt;br /&gt;
Many vital steps of follower addition happen inside an event in player_core.  Followers tend to be extremely buggy (no skill tree, for example) if this event does not fire.&lt;br /&gt;
&lt;br /&gt;
However, that event is not very flexible.  In order to control it to our requirements, we need to replicate its functionality inside our own script.  This is probably much safer than messing with player_core directly!&lt;br /&gt;
&lt;br /&gt;
Create a new script file, naming it something like '''hireCustomFollower_h'''.  We will be including this wherever we want to hire a follower.&lt;br /&gt;
&lt;br /&gt;
Paste in the following script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;sys_chargen_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_rewards_h&amp;quot;&lt;br /&gt;
#include &amp;quot;approval_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_autolevelup_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/*  Jye Nicolson 5-Jan-2010&lt;br /&gt;
This function set duplicates the full functionality chain of UT_HireFollower, with the following exceptions:&lt;br /&gt;
&lt;br /&gt;
-  Followers can gain XP&lt;br /&gt;
-  Autolevel status can be set (default off)&lt;br /&gt;
-  Followers can be set to any starting state (default Available) and will still be properly initalised and added to the party pool&lt;br /&gt;
-  Autolevel tables for non-core followers can be explicitly set.&lt;br /&gt;
-  Class and Specialisation can be chosen via script&lt;br /&gt;
-  Followers without specialisations are granted a spec point by default.&lt;br /&gt;
&lt;br /&gt;
It should only ever be called once each for characters you intend to be full followers.&lt;br /&gt;
Much of the protective code handling summoned creatures etc. in player_core is not present here.&lt;br /&gt;
&lt;br /&gt;
Calling the function:&lt;br /&gt;
&lt;br /&gt;
Simple:&lt;br /&gt;
&lt;br /&gt;
hireCustomFollower(oFollower, CLASS_WARRIOR);&lt;br /&gt;
&lt;br /&gt;
Change the class to CLASS_WIZARD or CLASS_ROGUE as appropriate.  &lt;br /&gt;
This will hire your follower and make them available.  &lt;br /&gt;
They will auto level up with a default package, and receive a free spec point.&lt;br /&gt;
&lt;br /&gt;
Best Practice:&lt;br /&gt;
&lt;br /&gt;
hireCustomFollower(oFollower, CLASS_WARRIOR, PLT_YOUR_PARTY_PLOT, YOUR_FOLLOWER_JOINED_FLAG, ABILITY_TALENT_HIDDEN_CHAMPION);&lt;br /&gt;
&lt;br /&gt;
Where the plot and flag are those for your module (remember to create the plot and include it on the calling script), and ABILITY_TALENT_HIDDEN etc is the desired spec.&lt;br /&gt;
&lt;br /&gt;
You should also have a custom ALTable set up.  &lt;br /&gt;
See wiki for details, and remember to edit it in to GetCustomFollowerALTable below or pass it directly as an argument to hireCustomFollower.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Full argument list:&lt;br /&gt;
&lt;br /&gt;
void hireCustomFollower (&lt;br /&gt;
        object oFollower,   //Pass your follower object, mandatory&lt;br /&gt;
        &lt;br /&gt;
        int nForceClass,    //Pass a Class constant here, usually CLASS_ROGUE, CLASS_WARRIOR, CLASS_WIZARD.  Mandatory due to a bug.&lt;br /&gt;
        &lt;br /&gt;
        string sPlot = &amp;quot;&amp;quot;,   //It's recommended you have a plot flag to be set when the follower joins.  Pass the plot constant here.  Remember to #include in calling script&lt;br /&gt;
        &lt;br /&gt;
        int nPlotFlag = &amp;quot;&amp;quot;,  //And then pass the flag constant.  Will be set to TRUE if available.&lt;br /&gt;
        &lt;br /&gt;
        int nForceSpec = 0,  //This is the ID of the Specialisation you want.  Note they are NOT classes, but abilities.  The full list is:&lt;br /&gt;
                             //ABILITY_SPELL_HIDDEN_ARCANE_WARRIOR, ABILITY_SPELL_HIDDEN_BLOODMAGE, ABILITY_SPELL_HIDDEN_SHAPESHIFTER, ABILITY_SPELL_HIDDEN_SPIRIT_HEALER&lt;br /&gt;
                             //ABILITY_SPELL_HIDDEN_BARD, ABILITY_TALENT_HIDDEN_ASSASSIN, ABILITY_TALENT_HIDDEN_DUELIST, ABILITY_TALENT_HIDDEN_RANGER&lt;br /&gt;
                             //ABILITY_TALENT_HIDDEN_BERSERKER, ABILITY_TALENT_HIDDEN_CHAMPION, ABILITY_TALENT_HIDDEN_REAVER, ABILITY_TALENT_HIDDEN_TEMPLAR&lt;br /&gt;
                             //I recommended forcing a spec, particularly if your ALTable includes abilities from one.&lt;br /&gt;
        &lt;br /&gt;
        int nALTable = 0,    //This is the ID of an ALTable from 2DA_base.GDA or your module's m2DA_base_*.GDA  I recommended the latter, but you can edit that into GetCustomFollowerALTable below rather than passing it.&lt;br /&gt;
        &lt;br /&gt;
        int bInvokePicker = FALSE,  //Sets whether the party picker should be opened on hiring.  I think it's cleaner to call the picker outside this script, particularly if you have multiple hires at once.&lt;br /&gt;
        &lt;br /&gt;
        int nInitialState = FOLLOWER_STATE_AVAILABLE,  //This sets whether the follower joins the active party or not.  Options are:&lt;br /&gt;
                                                       //FOLLOWER_STATE_ACTIVE (put them in the active party)&lt;br /&gt;
                                                       //FOLLOWER_STATE_LOCKEDACTIVE (force them into the active party and keep them there, remember to change this later.&lt;br /&gt;
                                                       //FOLLOWER_STATE_AVAILABLE (make them available on the party picker (if you've set it up for them), but not in the active party)&lt;br /&gt;
                                                       //Plus some others you're unlikely to need at this time.  Defaults to AVAILABLE because having 4+ active followers is screwy.&lt;br /&gt;
                                                       &lt;br /&gt;
        string sCurrPlot = &amp;quot;&amp;quot;,  //If you set FOLLOWER_STATE_ACTIVE or FOLLOWER_STATE_LOCKEDACTIVE, the script will check to see if you passed this.&lt;br /&gt;
                                //It is recommended that you have a plot flag set for a given follower being in the active party, this makes conversation interjection etc. much easier.&lt;br /&gt;
&lt;br /&gt;
        int nCurrPlotFlag = 0,  //This flag will be set if FOLLOWER_STATE_ACTIVE or FOLLOWER_STATE_LOCKEDACTIVE are true&lt;br /&gt;
                                //AND sCurrPlot has a value AND nCurrPlotFlag is &amp;gt; 0.  &lt;br /&gt;
                                //ie if you added someone to the active party and have a plot flag to cope with it.&lt;br /&gt;
&lt;br /&gt;
        int nAutolevel = 0,     //Sets the Autolevel flag on the character sheet.  0 is off, 1 is on, 2 forces it on and removes it so the player can't turn it off.&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
        bFreeSpecPoint = TRUE,  //This grants a specialisation point to the follower if they do not have a specialisation.  &lt;br /&gt;
                                //It's important to set this false for classes that do not have specs, such as CLASS_DOG.&lt;br /&gt;
                                &lt;br /&gt;
        int nTargetLevel = 0,   //If you want a specific level, set this.  Generally not worthwhile unless you set it higher than the player, since they'll just get XP from the party picker anyway.&lt;br /&gt;
        &lt;br /&gt;
        int nMinLevel = 0       //Set this if there's a specific level you don't want the follower to go below.  Probably only useful if the PC might be very low level but not necessarily so. &lt;br /&gt;
        &lt;br /&gt;
        )&lt;br /&gt;
*/       &lt;br /&gt;
/* GetCustomFollowerALTable()  &lt;br /&gt;
This function is where you put your custom table assignments.&lt;br /&gt;
&lt;br /&gt;
You should explicitly test for the tag of your follower (not mine!) and assign a value to nTable from your m2DA extension to M2DA_base &lt;br /&gt;
&lt;br /&gt;
See wiki for details on how to do this, or ignore it to get the default Warrior/Rogue/Wizard AL tables.&lt;br /&gt;
&lt;br /&gt;
NOTE: you MUST explicitly set a table for non-Warrior/Rogue/Wizards, eg dogs.  Use TABLE_AL_DOG for a default Mabari.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
int GetCustomFollowerALTable(object oFollower) {&lt;br /&gt;
    int nTable = _GetTableToUseForAL(oFollower);&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               &lt;br /&gt;
        nTable = 50143;   &lt;br /&gt;
    }   &lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_jysavin&amp;quot;) {&lt;br /&gt;
        nTable = 50144;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_geldual&amp;quot;) {&lt;br /&gt;
        nTable = 50145;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_braghon&amp;quot;) {&lt;br /&gt;
        nTable = 50146;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return nTable;    &lt;br /&gt;
}   &lt;br /&gt;
&lt;br /&gt;
// This just cleans up the main function a little&lt;br /&gt;
&lt;br /&gt;
int GetCustomFollowerTargetLevel(object oFollower, object oHero, int nPackage, int nMinLevel = 0) {&lt;br /&gt;
            int nPlayerLevel = GetLevel(oHero);&lt;br /&gt;
            int nTargetLevel = 0;&lt;br /&gt;
&lt;br /&gt;
            if((nPlayerLevel &amp;gt;= 13) || (nPlayerLevel == 1) || (!_UT_GetIsPlotFollower(oFollower))) {&lt;br /&gt;
               nTargetLevel = nPlayerLevel;&lt;br /&gt;
            } else {&lt;br /&gt;
               nTargetLevel = nPlayerLevel + 1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (nMinLevel == 0) {  //If nMinLevel is not specified, checks package 2DA for a value&lt;br /&gt;
              nMinLevel = GetM2DAInt(TABLE_PACKAGES, &amp;quot;MinLevel&amp;quot;, nPackage);&lt;br /&gt;
             }&lt;br /&gt;
            if(nMinLevel &amp;gt; 0 &amp;amp;&amp;amp; nMinLevel &amp;gt; nTargetLevel) {&lt;br /&gt;
               nTargetLevel = nMinLevel;&lt;br /&gt;
            }          &lt;br /&gt;
            &lt;br /&gt;
            return nTargetLevel;&lt;br /&gt;
    &lt;br /&gt;
}   &lt;br /&gt;
&lt;br /&gt;
// Moving this black box out :)  I don't really understand it, but it should function if you have tactics set up in a package.&lt;br /&gt;
&lt;br /&gt;
void InitCustomFollowerTactics(object oFollower, int nPackage) {&lt;br /&gt;
         int nTableID = GetM2DAInt(TABLE_PACKAGES, &amp;quot;FollowerTacticsTable&amp;quot;, nPackage);&lt;br /&gt;
         if (nTableID != -1)&lt;br /&gt;
            {&lt;br /&gt;
             int nRows = GetM2DARows(nTableID);&lt;br /&gt;
             int nMaxTactics = GetNumTactics(oFollower);&lt;br /&gt;
&lt;br /&gt;
             int nTacticsEntry = 1;&lt;br /&gt;
             int i;&lt;br /&gt;
             for (i = 1; i &amp;lt;= nRows &amp;amp;&amp;amp; nTacticsEntry &amp;lt;= nMaxTactics; ++i)&lt;br /&gt;
                {&lt;br /&gt;
                        int bAddEntry = FALSE;&lt;br /&gt;
                        int nTargetType = GetM2DAInt(nTableID, &amp;quot;TargetType&amp;quot;, i);&lt;br /&gt;
                        int nCondition = GetM2DAInt(nTableID, &amp;quot;Condition&amp;quot;, i);&lt;br /&gt;
                        int nCommandType = GetM2DAInt(nTableID, &amp;quot;Command&amp;quot;, i);&lt;br /&gt;
                        int nCommandParam = GetM2DAInt(nTableID, &amp;quot;SubCommand&amp;quot;, i);&lt;br /&gt;
&lt;br /&gt;
                        int nUseType = GetM2DAInt(TABLE_COMMAND_TYPES, &amp;quot;UseType&amp;quot;, nCommandType);&lt;br /&gt;
                        if (nUseType == 0)&lt;br /&gt;
                        {&lt;br /&gt;
                            bAddEntry = TRUE;&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            bAddEntry = HasAbility(oFollower, nCommandParam);&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        if (bAddEntry)&lt;br /&gt;
                        {&lt;br /&gt;
                            SetTacticEntry(oFollower, nTacticsEntry, TRUE, nTargetType, nCondition, nCommandType, nCommandParam);&lt;br /&gt;
                            ++nTacticsEntry;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
}  &lt;br /&gt;
&lt;br /&gt;
/* InitCustomFollowerSpec:&lt;br /&gt;
&lt;br /&gt;
This function tries to set the forced Specialisation.  If there is none, it checks the package for one.  &lt;br /&gt;
&lt;br /&gt;
If there isn't either of those, it grants a free spec point if bFreeSpecPoint is true.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void InitCustomFollowerSpec(object oFollower, int nPackage, int nForceSpec, int bFreeSpecPoint) {&lt;br /&gt;
    // Find specialization, and optionally add a spec point if none is found.&lt;br /&gt;
&lt;br /&gt;
        if (nForceSpec == 0) {&lt;br /&gt;
    &lt;br /&gt;
        int nSpecAbility = GetM2DAInt(TABLE_PACKAGES, &amp;quot;switch1_class&amp;quot;, nPackage); // followers can have only 1 advanced class&lt;br /&gt;
         if(nSpecAbility &amp;gt; 0)&lt;br /&gt;
         {&lt;br /&gt;
          AddAbility(oFollower, nSpecAbility);&lt;br /&gt;
         } else {&lt;br /&gt;
             if (bFreeSpecPoint) {&lt;br /&gt;
                 SetCreatureProperty(oFollower, 38, 1.00);&lt;br /&gt;
             }&lt;br /&gt;
         }                    &lt;br /&gt;
        &lt;br /&gt;
        } else {&lt;br /&gt;
         &lt;br /&gt;
             AddAbility(oFollower, nForceSpec);&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* hireCustomFollower()  (See doco at top of page)&lt;br /&gt;
&lt;br /&gt;
I strongly suggest you reorder the parameters if you're adding many followers with advanced options.&lt;br /&gt;
&lt;br /&gt;
Feel free to leave them alone if you only want to set class, plot, spec or don't mind long declarations.&lt;br /&gt;
&lt;br /&gt;
Note nForceClass is currently compulsory due to flakiness with GetCreatureCoreClass()&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void hireCustomFollower(object oFollower, int nForceClass, string sPlot = &amp;quot;&amp;quot;, int nPlotFlag = 0, int nForceSpec = 0, &lt;br /&gt;
int nALTable = 0, int bInvokePicker = FALSE, int nInitialState = FOLLOWER_STATE_AVAILABLE, string sCurrPlot = &amp;quot;&amp;quot;, &lt;br /&gt;
int nCurrPlotFlag = 0, int nAutolevel = 0, int bFreeSpecPoint = TRUE, int nTargetLevel = 0, int nMinLevel = 0) &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
        object oHero = GetHero();&lt;br /&gt;
&lt;br /&gt;
        /* #################  BEGIN BASIC FOLLOWER JOIN BLOCK   ###################&lt;br /&gt;
&lt;br /&gt;
        This loosely replicates WR_SetFollowerState.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        */    &lt;br /&gt;
        &lt;br /&gt;
        if (nForceClass == 0) {&lt;br /&gt;
            nForceClass = GetCreatureCoreClass(oFollower);           //This is not working.  Hence nForceClass mandatory.&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
        SetGroupId(oFollower, GetGroupId(oHero));      //Puts the follower in the pc's Group.&lt;br /&gt;
        SetEventScript(oFollower, RESOURCE_SCRIPT_PLAYER_CORE);  //This makes them act like a player.&lt;br /&gt;
        SetFollowerState(oFollower, nInitialState);  //This sets whether they are available, in the active party etc.&lt;br /&gt;
&lt;br /&gt;
        /* #################  END BASIC FOLLOWER JOIN BLOCK ##################### */&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        /* #################  BEGIN PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION #################&lt;br /&gt;
         This replicates the EVENT_TYPE_PARTY_MEMBER_HIRED handler from player_core, stripped down for simplicity and allowing our custom options.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        */&lt;br /&gt;
&lt;br /&gt;
        Chargen_EnableTacticsPresets(oFollower);    //I assume this is important.&lt;br /&gt;
        &lt;br /&gt;
        SetLocalInt(oFollower, FOLLOWER_SCALED, 1);  //This should prevent the follower being rescaled by player_core or what have you&lt;br /&gt;
        &lt;br /&gt;
        int nPackage = GetPackage(oFollower);  //Gets the package, which will be used to find a number of 2DA IDs.&lt;br /&gt;
        int nPackageClass = GetM2DAInt(TABLE_PACKAGES, &amp;quot;StartingClass&amp;quot;, nPackage);  //I don't think this is used, even by player_core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        // set behavior according to package&lt;br /&gt;
        int nBehavior = GetM2DAInt(TABLE_PACKAGES, &amp;quot;FollowerBehavior&amp;quot;, nPackage);&lt;br /&gt;
&lt;br /&gt;
        if(nBehavior &amp;gt;= 0) {&lt;br /&gt;
            SetAIBehavior(oFollower, nBehavior);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        Chargen_InitializeCharacter(oFollower);      //We initialise the follower and choose race/class.&lt;br /&gt;
        &lt;br /&gt;
        Chargen_SelectRace(oFollower,GetCreatureRacialType(oFollower));&lt;br /&gt;
        Chargen_SelectCoreClass(oFollower,nForceClass);        &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         if (nTargetLevel == 0) {   //This block picks a target level if not specified&lt;br /&gt;
            &lt;br /&gt;
              nTargetLevel = GetCustomFollowerTargetLevel(oFollower, oHero, nPackage, nMinLevel);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         int nXp = RW_GetXPNeededForLevel(Max(nTargetLevel, 1));      //Here is where the XP is calculated and rewarded&lt;br /&gt;
         RewardXP(oFollower, nXp, FALSE, FALSE);&lt;br /&gt;
&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         // add hidden approval talents - (JN: I don't know how to set these yet, but when I figure it out this should make it work)&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         int nIndex = Approval_GetFollowerIndex(oFollower);&lt;br /&gt;
         Approval_AddFollowerBonusAbility(nIndex, 0);&lt;br /&gt;
        &lt;br /&gt;
          //Handle Specialisation&lt;br /&gt;
          InitCustomFollowerSpec(oFollower, nPackage, nForceSpec, bFreeSpecPoint);&lt;br /&gt;
&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         // This spends all available attribute and stat points on the&lt;br /&gt;
         // creature according to the levelup table.  (JN:  this replicates AL_DoAutoLevelUp but with our choice of table)&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
         if (nALTable == 0) {&lt;br /&gt;
            nALTable = GetCustomFollowerALTable(oFollower);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         AL_SpendAttributePoints(oFollower, nALTable, FALSE);&lt;br /&gt;
         AL_SpendSkillPoints(oFollower, nALTable, TRUE);&lt;br /&gt;
         AL_SpendSpecializationPoints(oFollower, nALTable);&lt;br /&gt;
         AL_SpendTalentSpellPoints(oFollower, nALTable, TRUE);&lt;br /&gt;
&lt;br /&gt;
        // -------------------------------------------------------------------------&lt;br /&gt;
        // Update various UIs&lt;br /&gt;
        // -------------------------------------------------------------------------&lt;br /&gt;
        Chargen_SetNumTactics(oFollower);&lt;br /&gt;
        SetCanLevelUp(oFollower,Chargen_HasPointsToSpend(oFollower));&lt;br /&gt;
&lt;br /&gt;
        // load tactics&lt;br /&gt;
         InitCustomFollowerTactics(oFollower, nPackage);&lt;br /&gt;
&lt;br /&gt;
         /* #################  END PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION ################# */     &lt;br /&gt;
             &lt;br /&gt;
         &lt;br /&gt;
         SetAutoLevelUp(oFollower, nAutolevel);         //This is the autolevel flag on the character sheet.&lt;br /&gt;
         &lt;br /&gt;
         //Set plot flags&lt;br /&gt;
         &lt;br /&gt;
         if (!((sPlot == &amp;quot;&amp;quot;) || (nPlotFlag == 0))) {           //Joined Party&lt;br /&gt;
            WR_SetPlotFlag(sPlot, nPlotFlag, TRUE);   &lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         if ((nInitialState == FOLLOWER_STATE_ACTIVE) || (nInitialState == FOLLOWER_STATE_LOCKEDACTIVE)) {&lt;br /&gt;
            if (!((sCurrPlot == &amp;quot;&amp;quot;) || (nCurrPlotFlag == 0))) {&lt;br /&gt;
                WR_SetPlotFlag(sCurrPlot, nCurrPlotFlag, TRUE);   //Currently in Party&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
                     &lt;br /&gt;
        // Invoke picker if requested.&lt;br /&gt;
&lt;br /&gt;
        if (bInvokePicker) {&lt;br /&gt;
             SetPartyPickerGUIStatus(2);&lt;br /&gt;
             ShowPartyPickerGUI();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yeah, I know.  It can't really be any smaller.  Feel free to modify it if you're confident with scripting.&lt;br /&gt;
==== Add Your Custom Autolevel Template to GetCustomFollowerALTable() ====&lt;br /&gt;
While you can pass the ID you made for your autolevel template to that monster function as an argument, it's better to have them all in one place if you have multiple followers.&lt;br /&gt;
&lt;br /&gt;
GetCustomFollowerALTable() is the first function in our include, and you can add an explicit if test for your follower there to assign the correct table id (the one from your M2DA_base_ m2DA).  There is a function very much like it in sys_autolevel_h.nss for the core followers, so we'll copy Bioware's practice.&lt;br /&gt;
&lt;br /&gt;
Let's take a look at the function by itself:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int GetCustomFollowerALTable(object oFollower) {&lt;br /&gt;
    int nTable = _GetTableToUseForAL(oFollower);&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               &lt;br /&gt;
        nTable = 50143;   &lt;br /&gt;
    }   &lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_jysavin&amp;quot;) {&lt;br /&gt;
        nTable = 50144;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_geldual&amp;quot;) {&lt;br /&gt;
        nTable = 50145;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_braghon&amp;quot;) {&lt;br /&gt;
        nTable = 50146;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return nTable;    &lt;br /&gt;
    &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So we have a test for each follower tag from my module, matching up to an ID which is assigned to nTable.  All you need to do is change a tag from my follower to yours, and my ID to the correct one from your M2DA_base_* m2DA.  Then you should delete the rest of the example if statements :)&lt;br /&gt;
&lt;br /&gt;
Save and export the script.  Ignore the compiler error about lack of main();&lt;br /&gt;
&lt;br /&gt;
=== Include Function In Your Hire Script and Call It ===&lt;br /&gt;
&lt;br /&gt;
So instead of a hire script that calls UT_HireFollower(), we want one that includes our shiny new function and calls it.&lt;br /&gt;
&lt;br /&gt;
Take a look at the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;plt_bc_create_party&amp;quot;   //Make sure you include your party handling plot&lt;br /&gt;
#include &amp;quot;hireCustomFollower_h&amp;quot;  // And include the function script - which will in turn include a bunch of stuff&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
                    //Initialising my objects, not super-relevant to the example &lt;br /&gt;
                     &lt;br /&gt;
                    object oHero = GetHero();&lt;br /&gt;
                    object oMiera = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_miera.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oJysavin = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_jysavin.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oBraghon = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_braghon.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oSpider = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_geldual.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
&lt;br /&gt;
                    //Simplest hire call - adds to the party as a wizard.  Class is currently compulsory due to a bug.&lt;br /&gt;
                    hireCustomFollower(oMiera, CLASS_WIZARD);&lt;br /&gt;
&lt;br /&gt;
                    //Add to the party and set joining plot flags&lt;br /&gt;
                    hireCustomFollower(oJysavin, CLASS_WARRIOR, PLT_BC_CREATE_PARTY, PARTY_JYSAVIN_JOINED);&lt;br /&gt;
&lt;br /&gt;
                    //Add to the party, set plot flags, force a specialisation&lt;br /&gt;
                    hireCustomFollower(oBraghon, CLASS_ROGUE, PLT_BC_CREATE_PARTY, PARTY_BRAGHON_JOINED, ABILITY_TALENT_HIDDEN_ASSASSIN);&lt;br /&gt;
&lt;br /&gt;
                    //More complex example - Follower added as a unique class (Dog), not granted a specialisation or spec point.  &lt;br /&gt;
                    //Note unique classes must have an ALTable passed here or specified in GetCustomFollowerALTable() or they won't work&lt;br /&gt;
                    hireCustomFollower(oSpider, CLASS_DOG, PLT_BC_CREATE_PARTY, PARTY_GELDUAL_JOINED, 0, 0, FALSE, FOLLOWER_STATE_AVAILABLE, &amp;quot;&amp;quot;, 0, 0, FALSE);&lt;br /&gt;
                   &lt;br /&gt;
                    //Show the party picker to let the player choose from their new companions!&lt;br /&gt;
                    SetPartyPickerGUIStatus(2);&lt;br /&gt;
                    ShowPartyPickerGUI();                                                                                                                    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example shows several of the more simple ways of invoking the function.  Check the comments at the start of the function for a full list of arguments.&lt;br /&gt;
&lt;br /&gt;
I would suggest best practice for most followers would be to call as follows:&lt;br /&gt;
&lt;br /&gt;
'''hireCustomFollower(oFollower, CLASS, PLOT, PLOT_FLAG, SPECIALISATION)'''&lt;br /&gt;
&lt;br /&gt;
This will safely set the follower up as the desired class and specialisation (doubly important if there are spec abilities in their ALTable) while setting your plot flag for them being in the party.  hireCustomFollower(oFollower, CLASS, PLOT, PLOT_FLAG, SPECIALISATION, 0, TRUE) will do the same while invoking the Party Picker automatically.&lt;br /&gt;
&lt;br /&gt;
Note that the specialisations are abilities and not classes - you'll find them as ABILITY_HIDDEN_ constants.&lt;br /&gt;
&lt;br /&gt;
If it's all worked, you should find you can now add followers with a lot more flexibility!&lt;br /&gt;
&lt;br /&gt;
[[File:picker_advanced.jpg|thumb|500px|center]]&lt;br /&gt;
&lt;br /&gt;
== Common Follower Problems &amp;amp; FAQ ==&lt;br /&gt;
&lt;br /&gt;
====Why don't my followers gain XP?====&lt;br /&gt;
There is a bug in UT_HireFollower. Make a copy of UT_HireFollower in a function of your own, then make the following change:&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, TRUE);&lt;br /&gt;
to&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, bPreventLevelup);&lt;br /&gt;
&lt;br /&gt;
====When I choose followers from the Party Picker, they spawn into the area but do not join.====&lt;br /&gt;
&lt;br /&gt;
You need to intercept the EVENT_TYPE_PARTYMEMBER_ADDED event and set the follower to FOLLOWER_STATE_ACTIVE.  See Simple Follower Creation earlier in this document.&lt;br /&gt;
&lt;br /&gt;
====My followers don't have skill trees!====&lt;br /&gt;
&lt;br /&gt;
If a follower hasn't been through an initial chargen/autolevel event (via player_core/sys_autolevel_h) then the skill tree doesn't show.  You're probably trying to be clever and get around UT_HireFollower without going all the way (see monster function above ^_^).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====My followers don't have a class====&lt;br /&gt;
&lt;br /&gt;
GetCreatureCoreClass() seems flaky under some conditions.  It's best to explicitly set the class yourself; this is why class is currently a mandatory argument to hireCustomFollower()&lt;br /&gt;
&lt;br /&gt;
====Dog talents and equipment slots don't work====&lt;br /&gt;
Symptoms: dog talents appear on the talents screen but remain greyed out on level up. Warrior talents appear in the quickslots. Equipment slots are for humans, not dogs.&lt;br /&gt;
&lt;br /&gt;
Line 78 of packages_base in packages.xls (Dog) should have the LevelUpTable column set to 257 which is the ALDog table.&lt;br /&gt;
&lt;br /&gt;
The EquipmentLayout 2DA needs a new entry for the follower:&lt;br /&gt;
&lt;br /&gt;
 ID=same as partypicker 2DA	&lt;br /&gt;
 Tag=follower tag	&lt;br /&gt;
 AvailableEquipmentSlots=794624&lt;br /&gt;
 Layout=2	&lt;br /&gt;
 EnableWeaponSets=0&lt;br /&gt;
&lt;br /&gt;
If the creature is not using the appearance &amp;quot;Dog, Party Member&amp;quot;, it needs a new appearance line in APR_base. Most of the entries can be copied from the standard appearance (e.g. Wolf), but &lt;br /&gt;
&lt;br /&gt;
 MaxScaleLevel=-1&lt;br /&gt;
 DefaultArmor=&lt;br /&gt;
 AppearanceRestrictionGroup=1&lt;br /&gt;
&lt;br /&gt;
Otherwise, it won't be able to progress beyond a specified level. The player will receive an unwanted set of armour when the it is hired, and it won't be able to use Marabi crunch items. You may also need to tweak PERSPACE and/or BumpLevel if excessive clipping occurs.&lt;br /&gt;
&lt;br /&gt;
====Isn't there an easier way to do this?====&lt;br /&gt;
&lt;br /&gt;
Possibly.  There is a way of recruiting a follower by setting a plot flag.  However I don't understand it, and I expect it still doesn't allow custom autolevel templates, full control over specialisations etc.  There's still a fair bit of stuff hardcoded for the core followers, I'm not sure putting a custom follower through the same process as Al, Leli et al will have good results.&lt;br /&gt;
&lt;br /&gt;
The next section answers this question, up to a point.&lt;br /&gt;
&lt;br /&gt;
==== What if there are more than three potential followers? ====&lt;br /&gt;
This example handles larger numbers of followers, and doesn't force the player to use the party picker unless the party is already full.&lt;br /&gt;
&lt;br /&gt;
The prefix zzz, used throughout, can be replaced with whatever [[Prefixes_in_use | prefix]] you are using for your resources.&lt;br /&gt;
&lt;br /&gt;
If you're making a new campaign, to keep life simple, allocate a unique number to each follower. You could either use a creature variable or a script, e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Party member id (e.g. 1=Alicia, 2=Godwin...)&lt;br /&gt;
int zzzPartyMemberID(object oPartyMember)&lt;br /&gt;
{&lt;br /&gt;
  string sPartyMember = GetTag(oPartyMember);&lt;br /&gt;
&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_alicia&amp;quot;) return 1;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_godwin&amp;quot;) return 2;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_harold&amp;quot;) return 3;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_lara&amp;quot;  ) return 4;&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make two separate plots, e.g. zzzpt_hired for when a follower is first recruited, and zzzpt_party to flag whether they're currently in the party. Use flag values that correspond to the unique follower id, e.g. ZZZPT_HIRED_GODWIN will be 2.&lt;br /&gt;
&lt;br /&gt;
If you're modifying the official campaign, you won't be able to make this simplification - you'll need a set of plot flags for your new party members, similar to the official ones. The logic of what follows is still correct, it just means that instead of having one set of common code that works for everyone, you have to explicitly script each party member individually using their personal plot flags.&lt;br /&gt;
&lt;br /&gt;
Follower conversation is now very simple. In Godwin's dialogue, the hiring line will be conditional - when ZZZPT_HIRED_GODWIN is clear - and it will set ZZZPT_HIRED_GODWIN.  No conversation script is necessary. Instead, in the properties of the plot zzzpt_hired, we add a plot event script, as follows.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// PARTY HIRE PLOT SCRIPT&lt;br /&gt;
//&lt;br /&gt;
// This is called in conversation when a party member is hired for the first time.&lt;br /&gt;
// If the party is full, the party picker is displayed, which forces the PARTYMEMBER_ADDED&lt;br /&gt;
// module event.&lt;br /&gt;
//&lt;br /&gt;
// The flag value is never referenced, because the code is common for all party members.&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;events_h&amp;quot;&lt;br /&gt;
#include &amp;quot;global_objects_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_rewards_h&amp;quot;&lt;br /&gt;
#include &amp;quot;log_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plot_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;zzz_h&amp;quot;                  // A header containing the zzzPartyMemberID function&lt;br /&gt;
#include &amp;quot;plt_zzzpt_hired&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_zzzpt_party&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    event  eParms             = GetCurrentEvent();&lt;br /&gt;
    int    nType              = GetEventType(eParms);       // GET or SET&lt;br /&gt;
    string strPlot            = GetEventString(eParms, 0);  // Plot GUID&lt;br /&gt;
    int    nFlag              = GetEventInteger(eParms, 1); // Plot flag&lt;br /&gt;
    object oParty             = GetEventCreator(eParms);    // Plot table owner&lt;br /&gt;
    object oFollower          = GetEventObject(eParms, 0);  // Conversation owner (if any)&lt;br /&gt;
    int    nPlotType          = GetEventInteger(eParms, 5); // Plot type&lt;br /&gt;
&lt;br /&gt;
    int    bIsTutorial        = GetM2DAInt(TABLE_PLOT_TYPES, &amp;quot;IsTutorial&amp;quot;, nPlotType);&lt;br /&gt;
    int    bIsCodex           = GetM2DAInt(TABLE_PLOT_TYPES, &amp;quot;IsCodex&amp;quot;, nPlotType);&lt;br /&gt;
&lt;br /&gt;
    int    nResult            = FALSE;                      // return value for DEFINED GET&lt;br /&gt;
    object oPC                = GetPartyLeader();&lt;br /&gt;
&lt;br /&gt;
    plot_GlobalPlotHandler(eParms); // any global plot operations, including debug info&lt;br /&gt;
&lt;br /&gt;
    if (nType == EVENT_TYPE_SET_PLOT) // actions -&amp;gt; normal flags only&lt;br /&gt;
    {&lt;br /&gt;
        int nValue    = GetEventInteger(eParms, 2); // 0=Clear 1=Set&lt;br /&gt;
        int nOldValue = GetEventInteger(eParms, 3); // Current flag value&lt;br /&gt;
&lt;br /&gt;
        if (nValue)&lt;br /&gt;
          {&lt;br /&gt;
            if (GetArraySize(GetPartyList(oPC)) &amp;lt; 4)&lt;br /&gt;
              {&lt;br /&gt;
                // Code from UT_HireFollower with level up bug fixed&lt;br /&gt;
                SetAutoLevelUp(oFollower, 2);&lt;br /&gt;
                SetGroupId(oFollower, GetGroupId(GetHero()));&lt;br /&gt;
                WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, FALSE);  &lt;br /&gt;
                // End of code from UT_HireFollower&lt;br /&gt;
                AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
                WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), TRUE);&lt;br /&gt;
              }&lt;br /&gt;
            else&lt;br /&gt;
              {&lt;br /&gt;
                WR_SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE, FALSE);&lt;br /&gt;
                SetEventScript(oFollower, RESOURCE_SCRIPT_PLAYER_CORE);&lt;br /&gt;
                SendPartyMemberHiredEvent(oFollower, TRUE);&lt;br /&gt;
//                SetPartyPickerGUIStatus(PP_GUI_STATUS_USE);&lt;br /&gt;
//                ShowPartyPickerGUI();&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
     }&lt;br /&gt;
     else // EVENT_TYPE_GET_PLOT -&amp;gt; defined conditions only&lt;br /&gt;
     {&lt;br /&gt;
        switch(nFlag)&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    plot_OutputDefinedFlag(eParms, nResult);&lt;br /&gt;
    return nResult;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We still need to handle the party picker events in our module event script:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         // PARTY MEMBER ADDED - Allow XP gain. Come here, follow me, flag as party member.&lt;br /&gt;
         case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
         {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&lt;br /&gt;
            WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), TRUE);&lt;br /&gt;
            break;&lt;br /&gt;
         }&lt;br /&gt;
         // PARTY MEMBER DROPPED - flag as not party member.&lt;br /&gt;
         case EVENT_TYPE_PARTYMEMBER_DROPPED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), FALSE);&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When we need to refer to a particular follower explicitly, we can still do so - for example, the flag ZZZPT_PARTY_GODWIN will tell use whether Godwin is currently in the party or not.&lt;br /&gt;
&lt;br /&gt;
==== How do I turn off sustained abilities when a follower is dismissed? ====&lt;br /&gt;
'''Please note:''' The 1.04 DA:O patch is bugged and removed/broke several features of the toolkit, if you are using it please follow [http://social.bioware.com/forum/1/topic/71/index/3172230/1#3172537 these steps] to re-enable them as one is required for the script below to compile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is a potential exploit in what we've done so far. If a follower casts a sustained spell like Flaming Weapons, it affects all party members. When the follower is dismissed, the remaining party members continue to benefit from the spell.&lt;br /&gt;
&lt;br /&gt;
We can prevent this by deactivating modal abilities before opening the party picker. Add these snippets to the module event script:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;ability_h&amp;quot;&lt;br /&gt;
void zDeactivateModalAbilities();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         case EVENT_TYPE_PARTYPICKER_INIT:&lt;br /&gt;
           {&lt;br /&gt;
             // Deactivate party modal abilities. This ensures that the party no longer benefits&lt;br /&gt;
             // from spells like Flaming Weapons if the caster is dismissed from the party.&lt;br /&gt;
             zDeactivateModalAbilities();&lt;br /&gt;
             break;&lt;br /&gt;
           }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The function looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Deactivate party's modal abilities&lt;br /&gt;
&lt;br /&gt;
void zDeactivateModalAbilities()&lt;br /&gt;
{&lt;br /&gt;
  object    oPC            = GetHero();&lt;br /&gt;
  object [] oFollowerTable = GetPartyList(oPC);&lt;br /&gt;
  object    oFollower;&lt;br /&gt;
  int       nPartySize     = GetArraySize(oFollowerTable);&lt;br /&gt;
  int []    nAbilityTable;&lt;br /&gt;
  int       nAbilityCount;&lt;br /&gt;
  int       nAbility;&lt;br /&gt;
  int       i              = -1;&lt;br /&gt;
  int       j;&lt;br /&gt;
&lt;br /&gt;
  while (++i &amp;lt; nPartySize)&lt;br /&gt;
    {&lt;br /&gt;
      oFollower      = oFollowerTable[i];&lt;br /&gt;
      nAbilityTable  = GetAbilityList(oFollower);&lt;br /&gt;
      nAbilityCount  = GetArraySize(nAbilityTable);&lt;br /&gt;
      j              = -1;&lt;br /&gt;
&lt;br /&gt;
      while (++j &amp;lt; nAbilityCount)&lt;br /&gt;
        {&lt;br /&gt;
          nAbility = nAbilityTable[j];&lt;br /&gt;
&lt;br /&gt;
          if (Ability_IsAbilityActive(oFollower, nAbility))&lt;br /&gt;
            if (Ability_IsModalAbility(nAbility))&lt;br /&gt;
              Ability_DeactivateModalAbility(oFollower, nAbility);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If other ways of dismissing party members are permitted, the same function can be used.&lt;br /&gt;
&lt;br /&gt;
== Advanced Follower Creation: An Alternative Approach ==&lt;br /&gt;
&lt;br /&gt;
While these things are to a large extent a matter of taste, I see no reason to reinvent the wheel when there is a perfectly good wheel at hand. The following describes how to adapt the existing machinery for the recruitment and tracking of your own party members.&lt;br /&gt;
&lt;br /&gt;
First create the setup as described above in Simple Follower Creation, except for the scripts and plot tables. In addition, create the GDA extensions for a level-up table and the M2DA which points to those tables, as described in Advanced Follower Creation above.&lt;br /&gt;
&lt;br /&gt;
Now ...&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Create a party plot table ===&lt;br /&gt;
&lt;br /&gt;
Have a look at the gen00pt_party plot table and create a similar table for your own followers. Don't bother with the Defined Flags for the moment, just the Main Flags will do, ie recruited, in-camp and in-party for each follower. (Critical Note: Do not duplicate the plot table, create one from scratch. This is the case for ALL plot tables because of a show-stopping bug which means a new GUID is not assigned on Duplicate of a plot.)&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Create a party script ===&lt;br /&gt;
&lt;br /&gt;
Duplicate the gen00pt_party script and rename for your module (conventionally plot tables and their plot scripts have the same name). Delete (or comment out) the Defined Flags section at the end and any lines dealing with logging and tutorials. Change names to those of your party members. If you are using gifting, approval or forced inclusion you may wish to retain those sections of code, but additional machinery will be needed for these facilities to work. For approval you can specify a starting level of approval here for each follower if you want it to be other than zero (as per the existing section dealing with Dog). Note that the custom hire function at the head of the script allows you to specify whether or not to invoke the party picker on recruitment. You may not want to do so for the first couple of followers (but see below). You should already have defined all required constants in a separate file for your module, eg &amp;lt;module prefix&amp;gt;_constants_h. If not, do so now and include it, as well as your plot table, at the head of the script. Delete includes that only refer to the main campaign. (If this is all Greek to you, spend a couple of hours examining the set-up of the Demo, which is packaged with the toolset, and go through the introductory tutorials referenced on the main page of this wiki).&lt;br /&gt;
&lt;br /&gt;
Looking at the new party script, notice that the follower-in-camp function is not defined. This is because for some arcane reason it is defined in party_h, and unhappily references the main campaign's plot table. So we will have to create a new function to replace it, change the other function's flag reference (for the sake of neatness), and change the call in the main body of the script. (You may decide later for other reasons to replicate and customise party_h, but that won't interfere with re-creating this function here.)&lt;br /&gt;
&lt;br /&gt;
Our two functions at the head of the script should be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;void SetFollowerInParty(object oFollower, string sPlot, int nCampFlag)&lt;br /&gt;
{&lt;br /&gt;
    WR_SetPlotFlag(sPlot, nCampFlag, FALSE);&lt;br /&gt;
    WR_SetObjectActive(oFollower, TRUE);&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE);&lt;br /&gt;
    command cJump = CommandJumpToObject(GetPartyLeader());&lt;br /&gt;
    WR_AddCommand(oFollower, cJump);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SetFollowerInCamp(object oFollower, string sPlot, int nPartyFlag)&lt;br /&gt;
{&lt;br /&gt;
    WR_SetPlotFlag(sPlot, nPartyFlag, FALSE);&lt;br /&gt;
    WR_SetObjectActive(oFollower, FALSE);&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE, FALSE);&lt;br /&gt;
}&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the line in the in-camp sections for each follower should now be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;SetFollowerInCamp(o&amp;lt;follower&amp;gt;, strPlot, &amp;lt;follower&amp;gt;_IN_PARTY);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Step 3: Create package GDAs and reference them in you 2DA_base extension ===&lt;br /&gt;
&lt;br /&gt;
Look at the packages_base GDA and create an extension GDA with one line for each follower based on a main campaign follower that is most like your own follower, eg a sword-shield warrior can be a copy of Alistair, a battle mage a copy of Morrigan, etc. You can look at the Excel version of this GDA to more easily see what the fields mean. It is here that you can specify what if any specialisation will be assigned on hire and the level at which this spec point becomes available. (The IDs for each spec are in the 4000-range of ABI_base.)&lt;br /&gt;
&lt;br /&gt;
Most importantly, it is here also that you define the ID of both your level-up table and the AIP table you are about to create.&lt;br /&gt;
&lt;br /&gt;
Now create aip_follower_&amp;lt;follower name&amp;gt; gda tables, again based on a existing tables most like your own followers. No changes should be required to the copies you create.&lt;br /&gt;
&lt;br /&gt;
In the m2da_base_&amp;lt;your module&amp;gt; extension you have already created, add lines for your AIP tables with a package ID referencing the IDs you assigned in your packages extension table.&lt;br /&gt;
&lt;br /&gt;
Carefully check that all IDs in your GDAs are correct and cross-reference properly, and save the GDAs to your override directory.&lt;br /&gt;
&lt;br /&gt;
Desirable but not obligatory (except for non-humanoid characters), is an extension to the Portraits gda. Finally the Equipment Layout gda will need an extension for non-humanoids, who use a different equipment mask.&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Module script addition ===&lt;br /&gt;
&lt;br /&gt;
Modify your own module script to point to the new plot table and your own followers. To see an example of the required code for the two new sections look at the relevant section of module_core, which are for EVENT_TYPE_PARTYMEMBER_ADDED and EVENT_TYPE_PARTYMEMBER_DROPPED.&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
The recruit flag is set in a conversation (usually, but it could be a script) and that event is then processed by the plot script, which among other things sets both the in-camp and in-party flags, and fires up the party picker by default. If the player then selects the follower in the picker, the in-camp flag is unset (or vice versa if the follower is not selected to join). Subsequently, if the character is selected (or unselected) in the picker, the event is picked up by the module script, which sets the relevant plot flag as true, and that plot event is then sent to the plot scipt which sets the other flag as false. &lt;br /&gt;
&lt;br /&gt;
(Note that if the party picker is turned off for a particular follower's recruit event, that follower will be placed in the active party regardless of the number of members, so ONLY do this for a follower who cannot be recruited when there are already 3 possible followers.)&lt;br /&gt;
&lt;br /&gt;
On recruitment, player_core rebuilds the character according to the specifications laid out in the GDAs, so no further scripting is required.&lt;br /&gt;
&lt;br /&gt;
=== Uses ===&lt;br /&gt;
&lt;br /&gt;
To recruit a party member, set the recruit flag from your plot table in the relevant dialogue. Adding or subtracting followers from the active party is automatically tracked via this machinery, and the plot flags can be interrogated in all your scripts and conversations if you need to know who is currently in the party and who is in camp.&lt;br /&gt;
&lt;br /&gt;
Defined flags can be added as you need them to the script and plot table but there is no point having flags that you will not use, so as with all Defined Flags this is an as-you-go decision, but quite easy to do.&lt;br /&gt;
&lt;br /&gt;
Hiring and firing of temporary party members at the start of a campaign (such as Ser Jory, or Jowan, or Soris, etc) can be handled by UT_HireFollower, and the party picker is not invoked (nor is the Party Camp an available destination).&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
If you haven't done so already, create a simple debugging area for your module where you can dump the player, all followers and a couple of conversation dummies, and set up a dialogue in which you can invoke all required flags and conditions and see if they actually work as expected. (This setup can be used to test many other components as well.) Global machinery such as this can be painful to set up and get right (unless you are of an exceptionally methodical cast of mind), but it is worthwhile to ensure they are absolutely bullet-proof before you develop the specifics of your module.&lt;br /&gt;
&lt;br /&gt;
=== The KISS principle ===&lt;br /&gt;
&lt;br /&gt;
This is an &amp;quot;out-of-the-box&amp;quot; solution, and once set up is quite robust. If you want variants not catered for here, do NOT try to modify what you already have working.&lt;br /&gt;
&lt;br /&gt;
'''Use-case:''' You want a follower (example tag: dairren) to be recruited without a set specialisation and one level higher than the PC.&lt;br /&gt;
&lt;br /&gt;
Go to your packages gda and set the spec field to 0. In the character's plot table (you should have at least one for each follower) create a flag which we will call BLAH_BLAH. In the table's plot scipt insert the following very simple event handler:&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;dascript&amp;gt;case BLAH_BLAH:&lt;br /&gt;
         {&lt;br /&gt;
           SetCreatureProperty(oDairren, 38, 1.00); //awards the spec point; field from the properties gda&lt;br /&gt;
           int aLevel = GetLevel(oHero); //some simple arithmetic to find out the XP we need to award&lt;br /&gt;
           int bLevel = (aLevel+1);&lt;br /&gt;
           int aPoints = RW_GetXPNeededForLevel(aLevel);&lt;br /&gt;
           int bPoints = RW_GetXPNeededForLevel(bLevel);&lt;br /&gt;
           int targetPoints = (bPoints - aPoints);&lt;br /&gt;
           RewardXP(oDairren, targetPoints, FALSE, TRUE); //award the XP, and we're done&lt;br /&gt;
           break;&lt;br /&gt;
	 }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
The flag can be set in the same conversation as the recruit flag, so long as it comes afterwards. This way you not only maintain the integrity of your core machinery, but keep exceptions/variations for particular characters where they belong -- with that character's plot tables and scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Obadiah</name></author>	</entry>

	<entry>
		<id>http://datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16467</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16467"/>
				<updated>2011-07-13T16:13:50Z</updated>
		
		<summary type="html">&lt;p&gt;Obadiah: /* Add Plot Flags to Party Picker Event Intercept */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Simple Follower Creation ==&lt;br /&gt;
&lt;br /&gt;
Follow these steps to create a follower that&lt;br /&gt;
&lt;br /&gt;
- Levels up with a default package&lt;br /&gt;
&lt;br /&gt;
- Can be chosen from the party picker&lt;br /&gt;
&lt;br /&gt;
- Can gain XP&lt;br /&gt;
&lt;br /&gt;
This guide assumes you know how to create a creature and are comfortable with basic scripting.&lt;br /&gt;
&lt;br /&gt;
You should only use this simple method if you are sure there will be empty space in the active party when your follower is recruited.&lt;br /&gt;
&lt;br /&gt;
A more comprehensive approach when there are more than three potential party members is discussed in the FAQ below. It's worth taking the time to understand the basics first, though. &lt;br /&gt;
&lt;br /&gt;
=== Create the creature ===&lt;br /&gt;
&lt;br /&gt;
Create a creature to act as your follower.  Set its name, appearance, gender, head morph, conversation, inventory etc as you want them to behave in-game.&lt;br /&gt;
&lt;br /&gt;
Set an appropriate '''Tag''' (you'll be using it a lot).  I suggest &amp;quot;party_charname&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Make sure you choose a '''Class'''.  For most followers this should be Rogue, Warrior or Wizard.&lt;br /&gt;
&lt;br /&gt;
[[File:class.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Under Package/Scaling set:&lt;br /&gt;
&lt;br /&gt;
'''General Package Type''' to be '''Party Members'''&lt;br /&gt;
&lt;br /&gt;
'''Package''' to be an appropriate value (probably &amp;quot;Generic - Wizard&amp;quot; or similar)&lt;br /&gt;
&lt;br /&gt;
'''Package AI''' (there should only be one choice)&lt;br /&gt;
&lt;br /&gt;
'''Rank''' to be '''Player'''&lt;br /&gt;
&lt;br /&gt;
[[File:package.jpg]]&lt;br /&gt;
&lt;br /&gt;
Save and export your character as normal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Overlay char_stage ===&lt;br /&gt;
&lt;br /&gt;
In the official campaign, the party picker uses a special area called char_stage. Whether you're extending the official campaign or making a standalone campaign, there is a function that allows you to overlap the offical stage with your own, so that both stages are active simultaneously in game.&lt;br /&gt;
&lt;br /&gt;
In your resource palette, right-click char_stage under the Global folder and select Duplicate to make a copy of the stage with a new resource name, e.g. my_char_stage. In the resource properties, ensure that both Module and Owner Module are set to your module, and the folder of your choice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:area_palette.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create a new waypoint for your follower to appear on the party picker.  This waypoint '''must''' have a tag in the form of &amp;quot;char_&amp;quot; followed by the exact tag of your follower.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:char_stage.jpg]]&lt;br /&gt;
&lt;br /&gt;
In this example the tag of my follower is '''bc_party_miera''' so her waypoint tag must be '''char_bc_party_miera'''&lt;br /&gt;
&lt;br /&gt;
For a standalone module (such as in this example), put your waypoint wherever you please.  The illustrated one is directly on top of Morrigan's.  For an add-in to the main campaign, you should position your wp appropriately relative to the core party members.&lt;br /&gt;
&lt;br /&gt;
Save and export the area.&lt;br /&gt;
&lt;br /&gt;
Add the following to your module event script:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
case EVENT_TYPE_MODULE_GETCHARSTAGE:&lt;br /&gt;
{&lt;br /&gt;
   // Overlay the existing stage with my stage&lt;br /&gt;
   // &amp;quot;my_char_stage&amp;quot; is the resource name of the overlay area&lt;br /&gt;
   // &amp;quot;partypicker&amp;quot; is the name of the default GDA&lt;br /&gt;
   SetPartyPickerStage(&amp;quot;my_char_stage&amp;quot;, &amp;quot;partypicker&amp;quot;);&lt;br /&gt;
   break;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create m2DAs for the Party Picker ===&lt;br /&gt;
&lt;br /&gt;
You will need to create two Excel spreadsheets.&lt;br /&gt;
&lt;br /&gt;
The first should be named (both worksheet and file) '''partypicker_''' with a unique suffix.  In this example, my first spreadsheet is named partypicker_fofbc.xls with a worksheet name of partypicker_fofbc - the suffix being the acronym of my module.&lt;br /&gt;
&lt;br /&gt;
Set up your columns as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:partypickerm2da.jpg]]&lt;br /&gt;
&lt;br /&gt;
The '''ID''' for your follower must be '''12 or higher'''.  11 is the highest value used in the base 2DA.  12 is fine for standalone modules, add-ins will probably want to use an arbitrarily high number to avoid potential conflicts.&lt;br /&gt;
&lt;br /&gt;
The '''Label''' should be the follower's name as you wish it to appear on the party picker.&lt;br /&gt;
&lt;br /&gt;
The '''Tag''' must be your follower's tag.&lt;br /&gt;
&lt;br /&gt;
All other values are non-functioning defaults and should be specified as in the image above unless you know explicitly what you're doing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NOTE - ON SELECTION ANIMATIONS'''&lt;br /&gt;
 &lt;br /&gt;
Add Animation and Remove Animation are actually Id numbers of different animations, taken from anim_base.gda&lt;br /&gt;
&lt;br /&gt;
Enter and Exit version of animations are generally the best ones to use, altough one can try others. NOT ALL ANIMATIONS WILL WORK, since some require special conditions.&lt;br /&gt;
Here are some examples you can use:&lt;br /&gt;
&lt;br /&gt;
819 - talk cursing&lt;br /&gt;
&lt;br /&gt;
629 - reading a book (doesn't work, since it probably requires a book object)&lt;br /&gt;
&lt;br /&gt;
844 - hands behind back (848 and 849 are Enter and Exit versions respectfully)&lt;br /&gt;
&lt;br /&gt;
850 - chest pounding salute&lt;br /&gt;
&lt;br /&gt;
811 - fist pounding&lt;br /&gt;
&lt;br /&gt;
277 - dance&lt;br /&gt;
&lt;br /&gt;
247 - cast area spell&lt;br /&gt;
&lt;br /&gt;
500 - vfx cast&lt;br /&gt;
&lt;br /&gt;
600 - surprised&lt;br /&gt;
&lt;br /&gt;
603 - praying&lt;br /&gt;
&lt;br /&gt;
607 - head bow&lt;br /&gt;
&lt;br /&gt;
609 - standing at attention&lt;br /&gt;
&lt;br /&gt;
651,652 - crouch pray (Enter and exit)&lt;br /&gt;
&lt;br /&gt;
808 - point forward&lt;br /&gt;
&lt;br /&gt;
825 - nodding&lt;br /&gt;
&lt;br /&gt;
840 - hand chop or frustration&lt;br /&gt;
&lt;br /&gt;
905,906 - crouch (Enter, Exit)&lt;br /&gt;
&lt;br /&gt;
919,920 - sit on ground (enter, exit)&lt;br /&gt;
&lt;br /&gt;
965 - kneel down loop&lt;br /&gt;
&lt;br /&gt;
972 - wipe nose&lt;br /&gt;
&lt;br /&gt;
976,977 - squat (Enter, Exit)&lt;br /&gt;
&lt;br /&gt;
986 - wipe eyes&lt;br /&gt;
&lt;br /&gt;
998,999 - hands clasped (Enter, exit)&lt;br /&gt;
&lt;br /&gt;
3029 - inspect nails&lt;br /&gt;
&lt;br /&gt;
3031,3032 - playful (enter, exit)&lt;br /&gt;
&lt;br /&gt;
3054,3056 - slouch (enter, exit)&lt;br /&gt;
255 - in-place fly&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NOTE - ON SELECTION VFX''' &lt;br /&gt;
&lt;br /&gt;
The VFX column is the ID of the vFX effect taken from vFx_base.gda. This one is a bit more tricky, since it also references the BlendTree value from the same file.&lt;br /&gt;
Find the ID of the spell effect and look for the BlendTreeName column (should the the 12th columun) and enter BOTH into the respective columns for your character in the partypicker file.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
ID      ---      BLENDTREENAME      ---   EFFECT&lt;br /&gt;
&lt;br /&gt;
6039    ---     fxm_energy_up_p    ---    Lady of the Forest pillar of light&lt;br /&gt;
&lt;br /&gt;
6040    ---     fxm_power_in_p      ---   Branka - power in&lt;br /&gt;
&lt;br /&gt;
3054    ---     fxc_lotf_c          ---   Lady of the Forest - swirling leaves&lt;br /&gt;
&lt;br /&gt;
3009    ---     fxc_succubus_c     ---    Succubus crust&lt;br /&gt;
&lt;br /&gt;
1549    ---     fxa_hly_imp_c       ---   Holy Impact crust&lt;br /&gt;
&lt;br /&gt;
1076    ---     fxa_spi_aur_mht_c   ---   Spirit - Aura Might crust&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second spreadsheet should be named '''party_picker_''' (note middle underscore).  Once again append your unique suffix (in this example party_picker_fofbc.xls with party_picker_fofbc as its worksheet).&lt;br /&gt;
&lt;br /&gt;
Set up your columns and data like so:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:party_pickerm2da.jpg]]&lt;br /&gt;
&lt;br /&gt;
'''ID''' and '''Tag''' should match what you did in the first spreadsheet.  Specify INVALID COLUMN for the third column.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you're familiar with m2DAs, generate them from these files, copy them to your module's override directory, and skip to the next step.  Otherwise, read on:&lt;br /&gt;
&lt;br /&gt;
- Go to '''\Program Files\Dragon Age\tools\ResourceBuild\Processors''' (or wherever you installed Dragon Age)&lt;br /&gt;
&lt;br /&gt;
- Copy '''ExcelProcessor.exe''' from that folder to whichever folder has the excel sheets you just created.&lt;br /&gt;
&lt;br /&gt;
- Drag and drop your xls files onto ExcelProcessor.  This will create .gda files.&lt;br /&gt;
&lt;br /&gt;
- Copy these .gda files to your module's export directory (probably \Documents\Bioware\Dragon Age\AddIns\yourModule\module\override\toolsetexport).  Make sure they are included in your .dazip when the time comes to build your module.&lt;br /&gt;
&lt;br /&gt;
If you are an OpenOffice user and have trouble with ExcelProcessor, you can use [http://social.bioware.com/project/755/ GDApp] to directly create the 2DAs.  It rocks!&lt;br /&gt;
&lt;br /&gt;
=== Capture the EVENT_TYPE_PARTYMEMBER_ADDED Event ===&lt;br /&gt;
&lt;br /&gt;
Amusingly enough, the Party Picker does not actually add followers to the party.  However it raises an event that allows you to do so.  Your module script needs to capture this event and execute some code.&lt;br /&gt;
&lt;br /&gt;
The following example shows what to do with the event.  The full script would work as a module script for an add-in (assuming it didn't need to do anything else), but otherwise you'll have to incorporate the event into your own module script.  &lt;br /&gt;
&lt;br /&gt;
If you're not sure how to set a module script, go to '''File''' then '''Manage Modules,''' select your module and click '''Properties.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEventType = GetEventType(ev);&lt;br /&gt;
    switch(nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);  //Allows the follower to gain XP&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));   //Ensures follower appears at PC's location.&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);  //Adds follower to the active party&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE)''' is the key statement to add the follower to the active party.  You must have this.&lt;br /&gt;
&lt;br /&gt;
'''SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0)''' is a bug-fix, as followers hired with UT_HireFollower() do not receive XP by default.  This statement fixes that, and I consider it best practice to keep it in this event to ensure it is always set.  You will not wish to do this if you want a follower that should not gain XP to be on the party picker.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that you do not need to intercept the corresponding event for a party member being removed - the party picker handles spawning/despawning, and thus will successfully remove members.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remember to save and export your module script.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you're not sure how to set a module script, go to '''File''' then '''Manage Modules,''' select your module and click '''Properties.'''  The module script is in the General category, as seen below:&lt;br /&gt;
&lt;br /&gt;
[[File:module_script.jpg]]&lt;br /&gt;
&lt;br /&gt;
You can set this to any script you've created.  See [[Scripting tutorial]] and [[Character generation]] for more background and some simple examples of event-handling scripts.  In general, you will want to make sure standalone module scripts pass events through to module_core (as in the [[Character generation]] examples) and add-in scripts do not (as in the example above).&lt;br /&gt;
&lt;br /&gt;
=== Create Your Hiring Script ===&lt;br /&gt;
&lt;br /&gt;
Now all that remains is to actually hire the follower :)&lt;br /&gt;
&lt;br /&gt;
Create a script to handle the hiring (which will most likely be fired from a conversation).  The script is quite simple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
        object oFollower = GetObjectByTag(&amp;quot;bc_party_miera&amp;quot;); //Use CreateObject() if the creature isn't present in the module yet&lt;br /&gt;
&lt;br /&gt;
        UT_HireFollower(oFollower);   //Hires the follower&lt;br /&gt;
&lt;br /&gt;
        SetPartyPickerGUIStatus(2);&lt;br /&gt;
&lt;br /&gt;
        ShowPartyPickerGUI();  //Shows the Party Picker; necessary for the follower to gain XP&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure you use your own follower's tag and not the example one :)&lt;br /&gt;
&lt;br /&gt;
This script fires the party picker after hiring the follower.  That is absolutely necessary via this method, as we have put the XP fix onto an event fired by the party picker.  You cannot put the XP fix into this script, it must be called from a later one (the bug is caused by an errant call to an event in player_core, which will be executed AFTER this script).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The easiest way to use this script is directly from conversation, putting it as an action on a line of dialogue where the PC invites the follower to join them.  If you're not sure how to associate a script with a dialogue line, see the following image:&lt;br /&gt;
&lt;br /&gt;
[[File:hire_conv.jpg]]&lt;br /&gt;
&lt;br /&gt;
Create your dialogue as normal, select the line you want to fire the script, and click the '''Plots and Scripting''' tab.  Use the '''Script''' file chooser in the Action section to browse to the script you created.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If everything worked, you should see something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:picker_success.jpg|thumb|200px|center]]&lt;br /&gt;
&lt;br /&gt;
== Advanced Follower Creation ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow these steps to have full control over the creation of your follower, with options such as:&lt;br /&gt;
&lt;br /&gt;
- Unique level-up template&lt;br /&gt;
&lt;br /&gt;
- Class and specialisation chosen via script&lt;br /&gt;
&lt;br /&gt;
- Any starting state&lt;br /&gt;
&lt;br /&gt;
- Level higher than the PC&lt;br /&gt;
&lt;br /&gt;
- Starts with a specialisation point rather than a specific specialisation&lt;br /&gt;
&lt;br /&gt;
- Set plot flags in the call to the hire script&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Prepare Creature, char_stage and Party Picker m2DAs ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow the same steps to create your follower creature, char_stage and Party Picker m2DAs as above.&lt;br /&gt;
&lt;br /&gt;
=== Create Party Plot ===&lt;br /&gt;
&lt;br /&gt;
While not necessary, it's very helpful to have plot flags set when a follower is hired or joins/leaves the active party.  This makes conversation interjections and the like very easy.&lt;br /&gt;
&lt;br /&gt;
Create a plot with appropriate flags.  There's no real need to associate journal text with them:&lt;br /&gt;
&lt;br /&gt;
[[File:follower_plot.jpg]]&lt;br /&gt;
&lt;br /&gt;
See FAQ for an alternative approach to plots when there are more than three potential party members.&lt;br /&gt;
&lt;br /&gt;
=== Add Plot Flags to Party Picker Event Intercept ===&lt;br /&gt;
&lt;br /&gt;
We then update our module script to make use of that plot, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_bc_create_party&amp;quot;   //make sure you include your own plot, not mine&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEventType = GetEventType(ev);&lt;br /&gt;
    switch(nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&lt;br /&gt;
&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));   //Ensures follower appears at PC's location.&lt;br /&gt;
            &lt;br /&gt;
            if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               //You must explicitly test for your follower's tag.&lt;br /&gt;
                WR_SetPlotFlag(PLT_BC_CREATE_PARTY, PARTY_MIERA_IN_PARTY, TRUE);     //Make sure you use your own flags!&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            break;&lt;br /&gt;
        }  &lt;br /&gt;
        &lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_DROPPED:                    &lt;br /&gt;
        {&lt;br /&gt;
              object oFollower = GetEventObject(ev, 0); &lt;br /&gt;
              &lt;br /&gt;
              if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) { &lt;br /&gt;
                WR_SetPlotFlag(PLT_BC_CREATE_PARTY, PARTY_MIERA_IN_PARTY, FALSE);     //As above, but set false.&lt;br /&gt;
              }&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create a Level Up Template ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can skip this step if you're content to use one of the generic Rogue, Wizard or Warrior templates, but I don't recommend it.  Making a template that suits your character is easy and will almost always be better for the player than a generic one that spends points poorly.&lt;br /&gt;
&lt;br /&gt;
Go to \Program Files\Dragon Age\tools\Source\2DA (or wherever you installed Dragon Age).&lt;br /&gt;
&lt;br /&gt;
You should see a number of excel sheets of the form '''ALCharacter.xls''' (such as ALAlistair.xls, ALLeliana.xls, ALRogue_Default.xls etc).  Open the one closest to your character (ie Morrigan or Wynne for a wizard, Leliana or Zevran for a rogue).  Save a copy as '''ALYourcharacter.xls''' in whatever directory you're using to create your 2DAs, remembering to rename the worksheet '''ALYourcharacter''' (in this example, ALMiera.xls with ALMiera as its worksheet).&lt;br /&gt;
&lt;br /&gt;
It should look something like this:&lt;br /&gt;
&lt;br /&gt;
[[File:ALtable.jpg|thumb|500px|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Columns B''' and '''C''' are the talents/spells available to this character.  Do not change them.&lt;br /&gt;
&lt;br /&gt;
'''Columns F''' and '''G''' are the skills available to this character.  Do not change them.&lt;br /&gt;
&lt;br /&gt;
We will edit the remaining columns like so:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Setting Stat Weights ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The stat weights in '''column J''' determine how the follower will spend their attribute points, in a rough ratio.  So if Dexterity is set to 1.5 and Intelligence to 1, you should expect to see 3 points of Dex for every 2 points of Cunning in-game (note Intelligence is the label used in the toolset for Cunning).&lt;br /&gt;
&lt;br /&gt;
Simply change the values in J to reflect how you'd like the character to spend their points.  In this example we're creating a wizard, so we're not going to mess around:&lt;br /&gt;
&lt;br /&gt;
[[File:miera_stat_weights.jpg]]&lt;br /&gt;
&lt;br /&gt;
This character will only raise magic.  I set the value to 5 rather than something like 1 to provide room underneath for the other stats while still overwhelmingly favouring magic, but in practice I only really ever want that one stat. &lt;br /&gt;
&lt;br /&gt;
In a note left on this column in the existing templates, Bioware's Georg Zoeller writes, &amp;quot;This is the weight of each attribute (row id links into properties.xls.id). 1.0 means 'try to keep this attribute level' (spend 1 point per level). 0.5 means 'try to spend 1 point every two levels' and so on.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The default Mage, Rogue and Warrior templates include '''column L''' labeled &amp;quot;AttInit.&amp;quot; Editing these values seems to have no effect on followers set to use these templates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Setting Talent and Skill Priorities ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Columns D''' and '''E''' are the talents/spells that the character will buy, in preference order from top to bottom.&lt;br /&gt;
&lt;br /&gt;
'''Columns H''' and '''I''' are the skills that the character will buy, in preference order from top to bottom.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To change these, just copy the appropriate two cells from columns B&amp;amp;C or F&amp;amp;G over the ones you want to replace.&lt;br /&gt;
&lt;br /&gt;
For example, here we're copying Morrigan's template.  Morrigan has Spider Shape high in her preferences, which we do not want.&lt;br /&gt;
&lt;br /&gt;
[[File:AlMori_talent_pref.jpg]]&lt;br /&gt;
&lt;br /&gt;
We decide we'd prefer Flame Blast, so we find it in columns B&amp;amp;C and copy both cells:&lt;br /&gt;
&lt;br /&gt;
[[File:ALMori_copy.jpg]]&lt;br /&gt;
&lt;br /&gt;
Then we select the cells we want to replace in columns D&amp;amp;E and paste over them:&lt;br /&gt;
&lt;br /&gt;
[[File:ALMori_paste.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Continue this process until your priorities list for both skills and talents/spells is exactly as you want it.  Make sure you have at least as many priorities as the core follower you're copying - points that cannot be spent according to these priorities have a habit of vanishing.&lt;br /&gt;
&lt;br /&gt;
If you used any abilities from a specialisation, make sure you remember to set that specialisation with the function we'll introduce later.  The autolevel scripts will add specialisation abilities to a character regardless of whether they have that spec or not.&lt;br /&gt;
&lt;br /&gt;
==== Create a M2DA_base_ m2DA ====&lt;br /&gt;
&lt;br /&gt;
Dragon Age will need to know where to find your autolevel template.  We tell it by extending M2DA_base.gda&lt;br /&gt;
&lt;br /&gt;
Create a spreadsheet with the name and worksheet name in the form '''M2DA_base_''' with your unique suffix (in this example, M2DA_base_fofbc.xls with M2DA_base_fofbc as a worksheet).&lt;br /&gt;
&lt;br /&gt;
Set up its columns and data like so (note I used GDApp because Open Office wasn't cooperating for this one!):&lt;br /&gt;
&lt;br /&gt;
[[File:m2da_base_fofbc.jpg]]&lt;br /&gt;
&lt;br /&gt;
The '''ID''' should be very high to avoid conflicts.  I've arbitrarily chosen 50,000+ here.  Carefully note the ID you've chosen for your character, you will need it later.&lt;br /&gt;
&lt;br /&gt;
Set the '''Label''' and '''Worksheet''' to be the name of your autolevel template worksheet (ALCharactername if you've been following this).&lt;br /&gt;
&lt;br /&gt;
Set the '''PackageIDForAI''' to be 0, it shouldn't be needed for followers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you're done, use ExcelProcessor to make GDAs of both spreadsheets and copy them to your module's export folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
FOR AUTOLEVEL TO WORK AFTER RECRUITING:&lt;br /&gt;
&lt;br /&gt;
Look in packages.xls. &lt;br /&gt;
There is a column called LevelupTable. That links to a corresponding AL* table. For instance,  row 81 is for Leliana. Her LevelupTable value is 258. If you look that up in 2DA_base, you'll see it links to ALLeliana.&lt;br /&gt;
(alternatively, you could try packages_base.gda)&lt;br /&gt;
&lt;br /&gt;
=== Create a New Hire Function Include ===&lt;br /&gt;
&lt;br /&gt;
This section is probably only relevent if you have a specific need to override the functionality of player_core.&lt;br /&gt;
&lt;br /&gt;
Many vital steps of follower addition happen inside an event in player_core.  Followers tend to be extremely buggy (no skill tree, for example) if this event does not fire.&lt;br /&gt;
&lt;br /&gt;
However, that event is not very flexible.  In order to control it to our requirements, we need to replicate its functionality inside our own script.  This is probably much safer than messing with player_core directly!&lt;br /&gt;
&lt;br /&gt;
Create a new script file, naming it something like '''hireCustomFollower_h'''.  We will be including this wherever we want to hire a follower.&lt;br /&gt;
&lt;br /&gt;
Paste in the following script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;sys_chargen_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_rewards_h&amp;quot;&lt;br /&gt;
#include &amp;quot;approval_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_autolevelup_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/*  Jye Nicolson 5-Jan-2010&lt;br /&gt;
This function set duplicates the full functionality chain of UT_HireFollower, with the following exceptions:&lt;br /&gt;
&lt;br /&gt;
-  Followers can gain XP&lt;br /&gt;
-  Autolevel status can be set (default off)&lt;br /&gt;
-  Followers can be set to any starting state (default Available) and will still be properly initalised and added to the party pool&lt;br /&gt;
-  Autolevel tables for non-core followers can be explicitly set.&lt;br /&gt;
-  Class and Specialisation can be chosen via script&lt;br /&gt;
-  Followers without specialisations are granted a spec point by default.&lt;br /&gt;
&lt;br /&gt;
It should only ever be called once each for characters you intend to be full followers.&lt;br /&gt;
Much of the protective code handling summoned creatures etc. in player_core is not present here.&lt;br /&gt;
&lt;br /&gt;
Calling the function:&lt;br /&gt;
&lt;br /&gt;
Simple:&lt;br /&gt;
&lt;br /&gt;
hireCustomFollower(oFollower, CLASS_WARRIOR);&lt;br /&gt;
&lt;br /&gt;
Change the class to CLASS_WIZARD or CLASS_ROGUE as appropriate.  &lt;br /&gt;
This will hire your follower and make them available.  &lt;br /&gt;
They will auto level up with a default package, and receive a free spec point.&lt;br /&gt;
&lt;br /&gt;
Best Practice:&lt;br /&gt;
&lt;br /&gt;
hireCustomFollower(oFollower, CLASS_WARRIOR, PLT_YOUR_PARTY_PLOT, YOUR_FOLLOWER_JOINED_FLAG, ABILITY_TALENT_HIDDEN_CHAMPION);&lt;br /&gt;
&lt;br /&gt;
Where the plot and flag are those for your module (remember to create the plot and include it on the calling script), and ABILITY_TALENT_HIDDEN etc is the desired spec.&lt;br /&gt;
&lt;br /&gt;
You should also have a custom ALTable set up.  &lt;br /&gt;
See wiki for details, and remember to edit it in to GetCustomFollowerALTable below or pass it directly as an argument to hireCustomFollower.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Full argument list:&lt;br /&gt;
&lt;br /&gt;
void hireCustomFollower (&lt;br /&gt;
        object oFollower,   //Pass your follower object, mandatory&lt;br /&gt;
        &lt;br /&gt;
        int nForceClass,    //Pass a Class constant here, usually CLASS_ROGUE, CLASS_WARRIOR, CLASS_WIZARD.  Mandatory due to a bug.&lt;br /&gt;
        &lt;br /&gt;
        string sPlot = &amp;quot;&amp;quot;,   //It's recommended you have a plot flag to be set when the follower joins.  Pass the plot constant here.  Remember to #include in calling script&lt;br /&gt;
        &lt;br /&gt;
        int nPlotFlag = &amp;quot;&amp;quot;,  //And then pass the flag constant.  Will be set to TRUE if available.&lt;br /&gt;
        &lt;br /&gt;
        int nForceSpec = 0,  //This is the ID of the Specialisation you want.  Note they are NOT classes, but abilities.  The full list is:&lt;br /&gt;
                             //ABILITY_SPELL_HIDDEN_ARCANE_WARRIOR, ABILITY_SPELL_HIDDEN_BLOODMAGE, ABILITY_SPELL_HIDDEN_SHAPESHIFTER, ABILITY_SPELL_HIDDEN_SPIRIT_HEALER&lt;br /&gt;
                             //ABILITY_SPELL_HIDDEN_BARD, ABILITY_TALENT_HIDDEN_ASSASSIN, ABILITY_TALENT_HIDDEN_DUELIST, ABILITY_TALENT_HIDDEN_RANGER&lt;br /&gt;
                             //ABILITY_TALENT_HIDDEN_BERSERKER, ABILITY_TALENT_HIDDEN_CHAMPION, ABILITY_TALENT_HIDDEN_REAVER, ABILITY_TALENT_HIDDEN_TEMPLAR&lt;br /&gt;
                             //I recommended forcing a spec, particularly if your ALTable includes abilities from one.&lt;br /&gt;
        &lt;br /&gt;
        int nALTable = 0,    //This is the ID of an ALTable from 2DA_base.GDA or your module's m2DA_base_*.GDA  I recommended the latter, but you can edit that into GetCustomFollowerALTable below rather than passing it.&lt;br /&gt;
        &lt;br /&gt;
        int bInvokePicker = FALSE,  //Sets whether the party picker should be opened on hiring.  I think it's cleaner to call the picker outside this script, particularly if you have multiple hires at once.&lt;br /&gt;
        &lt;br /&gt;
        int nInitialState = FOLLOWER_STATE_AVAILABLE,  //This sets whether the follower joins the active party or not.  Options are:&lt;br /&gt;
                                                       //FOLLOWER_STATE_ACTIVE (put them in the active party)&lt;br /&gt;
                                                       //FOLLOWER_STATE_LOCKEDACTIVE (force them into the active party and keep them there, remember to change this later.&lt;br /&gt;
                                                       //FOLLOWER_STATE_AVAILABLE (make them available on the party picker (if you've set it up for them), but not in the active party)&lt;br /&gt;
                                                       //Plus some others you're unlikely to need at this time.  Defaults to AVAILABLE because having 4+ active followers is screwy.&lt;br /&gt;
                                                       &lt;br /&gt;
        string sCurrPlot = &amp;quot;&amp;quot;,  //If you set FOLLOWER_STATE_ACTIVE or FOLLOWER_STATE_LOCKEDACTIVE, the script will check to see if you passed this.&lt;br /&gt;
                                //It is recommended that you have a plot flag set for a given follower being in the active party, this makes conversation interjection etc. much easier.&lt;br /&gt;
&lt;br /&gt;
        int nCurrPlotFlag = 0,  //This flag will be set if FOLLOWER_STATE_ACTIVE or FOLLOWER_STATE_LOCKEDACTIVE are true&lt;br /&gt;
                                //AND sCurrPlot has a value AND nCurrPlotFlag is &amp;gt; 0.  &lt;br /&gt;
                                //ie if you added someone to the active party and have a plot flag to cope with it.&lt;br /&gt;
&lt;br /&gt;
        int nAutolevel = 0,     //Sets the Autolevel flag on the character sheet.  0 is off, 1 is on, 2 forces it on and removes it so the player can't turn it off.&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
        bFreeSpecPoint = TRUE,  //This grants a specialisation point to the follower if they do not have a specialisation.  &lt;br /&gt;
                                //It's important to set this false for classes that do not have specs, such as CLASS_DOG.&lt;br /&gt;
                                &lt;br /&gt;
        int nTargetLevel = 0,   //If you want a specific level, set this.  Generally not worthwhile unless you set it higher than the player, since they'll just get XP from the party picker anyway.&lt;br /&gt;
        &lt;br /&gt;
        int nMinLevel = 0       //Set this if there's a specific level you don't want the follower to go below.  Probably only useful if the PC might be very low level but not necessarily so. &lt;br /&gt;
        &lt;br /&gt;
        )&lt;br /&gt;
*/       &lt;br /&gt;
/* GetCustomFollowerALTable()  &lt;br /&gt;
This function is where you put your custom table assignments.&lt;br /&gt;
&lt;br /&gt;
You should explicitly test for the tag of your follower (not mine!) and assign a value to nTable from your m2DA extension to M2DA_base &lt;br /&gt;
&lt;br /&gt;
See wiki for details on how to do this, or ignore it to get the default Warrior/Rogue/Wizard AL tables.&lt;br /&gt;
&lt;br /&gt;
NOTE: you MUST explicitly set a table for non-Warrior/Rogue/Wizards, eg dogs.  Use TABLE_AL_DOG for a default Mabari.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
int GetCustomFollowerALTable(object oFollower) {&lt;br /&gt;
    int nTable = _GetTableToUseForAL(oFollower);&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               &lt;br /&gt;
        nTable = 50143;   &lt;br /&gt;
    }   &lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_jysavin&amp;quot;) {&lt;br /&gt;
        nTable = 50144;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_geldual&amp;quot;) {&lt;br /&gt;
        nTable = 50145;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_braghon&amp;quot;) {&lt;br /&gt;
        nTable = 50146;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return nTable;    &lt;br /&gt;
}   &lt;br /&gt;
&lt;br /&gt;
// This just cleans up the main function a little&lt;br /&gt;
&lt;br /&gt;
int GetCustomFollowerTargetLevel(object oFollower, object oHero, int nPackage, int nMinLevel = 0) {&lt;br /&gt;
            int nPlayerLevel = GetLevel(oHero);&lt;br /&gt;
            int nTargetLevel = 0;&lt;br /&gt;
&lt;br /&gt;
            if((nPlayerLevel &amp;gt;= 13) || (nPlayerLevel == 1) || (!_UT_GetIsPlotFollower(oFollower))) {&lt;br /&gt;
               nTargetLevel = nPlayerLevel;&lt;br /&gt;
            } else {&lt;br /&gt;
               nTargetLevel = nPlayerLevel + 1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (nMinLevel == 0) {  //If nMinLevel is not specified, checks package 2DA for a value&lt;br /&gt;
              nMinLevel = GetM2DAInt(TABLE_PACKAGES, &amp;quot;MinLevel&amp;quot;, nPackage);&lt;br /&gt;
             }&lt;br /&gt;
            if(nMinLevel &amp;gt; 0 &amp;amp;&amp;amp; nMinLevel &amp;gt; nTargetLevel) {&lt;br /&gt;
               nTargetLevel = nMinLevel;&lt;br /&gt;
            }          &lt;br /&gt;
            &lt;br /&gt;
            return nTargetLevel;&lt;br /&gt;
    &lt;br /&gt;
}   &lt;br /&gt;
&lt;br /&gt;
// Moving this black box out :)  I don't really understand it, but it should function if you have tactics set up in a package.&lt;br /&gt;
&lt;br /&gt;
void InitCustomFollowerTactics(object oFollower, int nPackage) {&lt;br /&gt;
         int nTableID = GetM2DAInt(TABLE_PACKAGES, &amp;quot;FollowerTacticsTable&amp;quot;, nPackage);&lt;br /&gt;
         if (nTableID != -1)&lt;br /&gt;
            {&lt;br /&gt;
             int nRows = GetM2DARows(nTableID);&lt;br /&gt;
             int nMaxTactics = GetNumTactics(oFollower);&lt;br /&gt;
&lt;br /&gt;
             int nTacticsEntry = 1;&lt;br /&gt;
             int i;&lt;br /&gt;
             for (i = 1; i &amp;lt;= nRows &amp;amp;&amp;amp; nTacticsEntry &amp;lt;= nMaxTactics; ++i)&lt;br /&gt;
                {&lt;br /&gt;
                        int bAddEntry = FALSE;&lt;br /&gt;
                        int nTargetType = GetM2DAInt(nTableID, &amp;quot;TargetType&amp;quot;, i);&lt;br /&gt;
                        int nCondition = GetM2DAInt(nTableID, &amp;quot;Condition&amp;quot;, i);&lt;br /&gt;
                        int nCommandType = GetM2DAInt(nTableID, &amp;quot;Command&amp;quot;, i);&lt;br /&gt;
                        int nCommandParam = GetM2DAInt(nTableID, &amp;quot;SubCommand&amp;quot;, i);&lt;br /&gt;
&lt;br /&gt;
                        int nUseType = GetM2DAInt(TABLE_COMMAND_TYPES, &amp;quot;UseType&amp;quot;, nCommandType);&lt;br /&gt;
                        if (nUseType == 0)&lt;br /&gt;
                        {&lt;br /&gt;
                            bAddEntry = TRUE;&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            bAddEntry = HasAbility(oFollower, nCommandParam);&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        if (bAddEntry)&lt;br /&gt;
                        {&lt;br /&gt;
                            SetTacticEntry(oFollower, nTacticsEntry, TRUE, nTargetType, nCondition, nCommandType, nCommandParam);&lt;br /&gt;
                            ++nTacticsEntry;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
}  &lt;br /&gt;
&lt;br /&gt;
/* InitCustomFollowerSpec:&lt;br /&gt;
&lt;br /&gt;
This function tries to set the forced Specialisation.  If there is none, it checks the package for one.  &lt;br /&gt;
&lt;br /&gt;
If there isn't either of those, it grants a free spec point if bFreeSpecPoint is true.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void InitCustomFollowerSpec(object oFollower, int nPackage, int nForceSpec, int bFreeSpecPoint) {&lt;br /&gt;
    // Find specialization, and optionally add a spec point if none is found.&lt;br /&gt;
&lt;br /&gt;
        if (nForceSpec == 0) {&lt;br /&gt;
    &lt;br /&gt;
        int nSpecAbility = GetM2DAInt(TABLE_PACKAGES, &amp;quot;switch1_class&amp;quot;, nPackage); // followers can have only 1 advanced class&lt;br /&gt;
         if(nSpecAbility &amp;gt; 0)&lt;br /&gt;
         {&lt;br /&gt;
          AddAbility(oFollower, nSpecAbility);&lt;br /&gt;
         } else {&lt;br /&gt;
             if (bFreeSpecPoint) {&lt;br /&gt;
                 SetCreatureProperty(oFollower, 38, 1.00);&lt;br /&gt;
             }&lt;br /&gt;
         }                    &lt;br /&gt;
        &lt;br /&gt;
        } else {&lt;br /&gt;
         &lt;br /&gt;
             AddAbility(oFollower, nForceSpec);&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* hireCustomFollower()  (See doco at top of page)&lt;br /&gt;
&lt;br /&gt;
I strongly suggest you reorder the parameters if you're adding many followers with advanced options.&lt;br /&gt;
&lt;br /&gt;
Feel free to leave them alone if you only want to set class, plot, spec or don't mind long declarations.&lt;br /&gt;
&lt;br /&gt;
Note nForceClass is currently compulsory due to flakiness with GetCreatureCoreClass()&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void hireCustomFollower(object oFollower, int nForceClass, string sPlot = &amp;quot;&amp;quot;, int nPlotFlag = 0, int nForceSpec = 0, &lt;br /&gt;
int nALTable = 0, int bInvokePicker = FALSE, int nInitialState = FOLLOWER_STATE_AVAILABLE, string sCurrPlot = &amp;quot;&amp;quot;, &lt;br /&gt;
int nCurrPlotFlag = 0, int nAutolevel = 0, int bFreeSpecPoint = TRUE, int nTargetLevel = 0, int nMinLevel = 0) &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
        object oHero = GetHero();&lt;br /&gt;
&lt;br /&gt;
        /* #################  BEGIN BASIC FOLLOWER JOIN BLOCK   ###################&lt;br /&gt;
&lt;br /&gt;
        This loosely replicates WR_SetFollowerState.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        */    &lt;br /&gt;
        &lt;br /&gt;
        if (nForceClass == 0) {&lt;br /&gt;
            nForceClass = GetCreatureCoreClass(oFollower);           //This is not working.  Hence nForceClass mandatory.&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
        SetGroupId(oFollower, GetGroupId(oHero));      //Puts the follower in the pc's Group.&lt;br /&gt;
        SetEventScript(oFollower, RESOURCE_SCRIPT_PLAYER_CORE);  //This makes them act like a player.&lt;br /&gt;
        SetFollowerState(oFollower, nInitialState);  //This sets whether they are available, in the active party etc.&lt;br /&gt;
&lt;br /&gt;
        /* #################  END BASIC FOLLOWER JOIN BLOCK ##################### */&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        /* #################  BEGIN PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION #################&lt;br /&gt;
         This replicates the EVENT_TYPE_PARTY_MEMBER_HIRED handler from player_core, stripped down for simplicity and allowing our custom options.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        */&lt;br /&gt;
&lt;br /&gt;
        Chargen_EnableTacticsPresets(oFollower);    //I assume this is important.&lt;br /&gt;
        &lt;br /&gt;
        SetLocalInt(oFollower, FOLLOWER_SCALED, 1);  //This should prevent the follower being rescaled by player_core or what have you&lt;br /&gt;
        &lt;br /&gt;
        int nPackage = GetPackage(oFollower);  //Gets the package, which will be used to find a number of 2DA IDs.&lt;br /&gt;
        int nPackageClass = GetM2DAInt(TABLE_PACKAGES, &amp;quot;StartingClass&amp;quot;, nPackage);  //I don't think this is used, even by player_core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        // set behavior according to package&lt;br /&gt;
        int nBehavior = GetM2DAInt(TABLE_PACKAGES, &amp;quot;FollowerBehavior&amp;quot;, nPackage);&lt;br /&gt;
&lt;br /&gt;
        if(nBehavior &amp;gt;= 0) {&lt;br /&gt;
            SetAIBehavior(oFollower, nBehavior);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        Chargen_InitializeCharacter(oFollower);      //We initialise the follower and choose race/class.&lt;br /&gt;
        &lt;br /&gt;
        Chargen_SelectRace(oFollower,GetCreatureRacialType(oFollower));&lt;br /&gt;
        Chargen_SelectCoreClass(oFollower,nForceClass);        &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         if (nTargetLevel == 0) {   //This block picks a target level if not specified&lt;br /&gt;
            &lt;br /&gt;
              nTargetLevel = GetCustomFollowerTargetLevel(oFollower, oHero, nPackage, nMinLevel);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         int nXp = RW_GetXPNeededForLevel(Max(nTargetLevel, 1));      //Here is where the XP is calculated and rewarded&lt;br /&gt;
         RewardXP(oFollower, nXp, FALSE, FALSE);&lt;br /&gt;
&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         // add hidden approval talents - (JN: I don't know how to set these yet, but when I figure it out this should make it work)&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         int nIndex = Approval_GetFollowerIndex(oFollower);&lt;br /&gt;
         Approval_AddFollowerBonusAbility(nIndex, 0);&lt;br /&gt;
        &lt;br /&gt;
          //Handle Specialisation&lt;br /&gt;
          InitCustomFollowerSpec(oFollower, nPackage, nForceSpec, bFreeSpecPoint);&lt;br /&gt;
&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         // This spends all available attribute and stat points on the&lt;br /&gt;
         // creature according to the levelup table.  (JN:  this replicates AL_DoAutoLevelUp but with our choice of table)&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
         if (nALTable == 0) {&lt;br /&gt;
            nALTable = GetCustomFollowerALTable(oFollower);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         AL_SpendAttributePoints(oFollower, nALTable, FALSE);&lt;br /&gt;
         AL_SpendSkillPoints(oFollower, nALTable, TRUE);&lt;br /&gt;
         AL_SpendSpecializationPoints(oFollower, nALTable);&lt;br /&gt;
         AL_SpendTalentSpellPoints(oFollower, nALTable, TRUE);&lt;br /&gt;
&lt;br /&gt;
        // -------------------------------------------------------------------------&lt;br /&gt;
        // Update various UIs&lt;br /&gt;
        // -------------------------------------------------------------------------&lt;br /&gt;
        Chargen_SetNumTactics(oFollower);&lt;br /&gt;
        SetCanLevelUp(oFollower,Chargen_HasPointsToSpend(oFollower));&lt;br /&gt;
&lt;br /&gt;
        // load tactics&lt;br /&gt;
         InitCustomFollowerTactics(oFollower, nPackage);&lt;br /&gt;
&lt;br /&gt;
         /* #################  END PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION ################# */     &lt;br /&gt;
             &lt;br /&gt;
         &lt;br /&gt;
         SetAutoLevelUp(oFollower, nAutolevel);         //This is the autolevel flag on the character sheet.&lt;br /&gt;
         &lt;br /&gt;
         //Set plot flags&lt;br /&gt;
         &lt;br /&gt;
         if (!((sPlot == &amp;quot;&amp;quot;) || (nPlotFlag == 0))) {           //Joined Party&lt;br /&gt;
            WR_SetPlotFlag(sPlot, nPlotFlag, TRUE);   &lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         if ((nInitialState == FOLLOWER_STATE_ACTIVE) || (nInitialState == FOLLOWER_STATE_LOCKEDACTIVE)) {&lt;br /&gt;
            if (!((sCurrPlot == &amp;quot;&amp;quot;) || (nCurrPlotFlag == 0))) {&lt;br /&gt;
                WR_SetPlotFlag(sCurrPlot, nCurrPlotFlag, TRUE);   //Currently in Party&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
                     &lt;br /&gt;
        // Invoke picker if requested.&lt;br /&gt;
&lt;br /&gt;
        if (bInvokePicker) {&lt;br /&gt;
             SetPartyPickerGUIStatus(2);&lt;br /&gt;
             ShowPartyPickerGUI();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yeah, I know.  It can't really be any smaller.  Feel free to modify it if you're confident with scripting.&lt;br /&gt;
==== Add Your Custom Autolevel Template to GetCustomFollowerALTable() ====&lt;br /&gt;
While you can pass the ID you made for your autolevel template to that monster function as an argument, it's better to have them all in one place if you have multiple followers.&lt;br /&gt;
&lt;br /&gt;
GetCustomFollowerALTable() is the first function in our include, and you can add an explicit if test for your follower there to assign the correct table id (the one from your M2DA_base_ m2DA).  There is a function very much like it in sys_autolevel_h.nss for the core followers, so we'll copy Bioware's practice.&lt;br /&gt;
&lt;br /&gt;
Let's take a look at the function by itself:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int GetCustomFollowerALTable(object oFollower) {&lt;br /&gt;
    int nTable = _GetTableToUseForAL(oFollower);&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               &lt;br /&gt;
        nTable = 50143;   &lt;br /&gt;
    }   &lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_jysavin&amp;quot;) {&lt;br /&gt;
        nTable = 50144;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_geldual&amp;quot;) {&lt;br /&gt;
        nTable = 50145;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_braghon&amp;quot;) {&lt;br /&gt;
        nTable = 50146;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return nTable;    &lt;br /&gt;
    &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So we have a test for each follower tag from my module, matching up to an ID which is assigned to nTable.  All you need to do is change a tag from my follower to yours, and my ID to the correct one from your M2DA_base_* m2DA.  Then you should delete the rest of the example if statements :)&lt;br /&gt;
&lt;br /&gt;
Save and export the script.  Ignore the compiler error about lack of main();&lt;br /&gt;
&lt;br /&gt;
=== Include Function In Your Hire Script and Call It ===&lt;br /&gt;
&lt;br /&gt;
So instead of a hire script that calls UT_HireFollower(), we want one that includes our shiny new function and calls it.&lt;br /&gt;
&lt;br /&gt;
Take a look at the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;plt_bc_create_party&amp;quot;   //Make sure you include your party handling plot&lt;br /&gt;
#include &amp;quot;hireCustomFollower_h&amp;quot;  // And include the function script - which will in turn include a bunch of stuff&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
                    //Initialising my objects, not super-relevant to the example &lt;br /&gt;
                     &lt;br /&gt;
                    object oHero = GetHero();&lt;br /&gt;
                    object oMiera = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_miera.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oJysavin = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_jysavin.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oBraghon = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_braghon.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oSpider = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_geldual.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
&lt;br /&gt;
                    //Simplest hire call - adds to the party as a wizard.  Class is currently compulsory due to a bug.&lt;br /&gt;
                    hireCustomFollower(oMiera, CLASS_WIZARD);&lt;br /&gt;
&lt;br /&gt;
                    //Add to the party and set joining plot flags&lt;br /&gt;
                    hireCustomFollower(oJysavin, CLASS_WARRIOR, PLT_BC_CREATE_PARTY, PARTY_JYSAVIN_JOINED);&lt;br /&gt;
&lt;br /&gt;
                    //Add to the party, set plot flags, force a specialisation&lt;br /&gt;
                    hireCustomFollower(oBraghon, CLASS_ROGUE, PLT_BC_CREATE_PARTY, PARTY_BRAGHON_JOINED, ABILITY_TALENT_HIDDEN_ASSASSIN);&lt;br /&gt;
&lt;br /&gt;
                    //More complex example - Follower added as a unique class (Dog), not granted a specialisation or spec point.  &lt;br /&gt;
                    //Note unique classes must have an ALTable passed here or specified in GetCustomFollowerALTable() or they won't work&lt;br /&gt;
                    hireCustomFollower(oSpider, CLASS_DOG, PLT_BC_CREATE_PARTY, PARTY_GELDUAL_JOINED, 0, 0, FALSE, FOLLOWER_STATE_AVAILABLE, &amp;quot;&amp;quot;, 0, 0, FALSE);&lt;br /&gt;
                   &lt;br /&gt;
                    //Show the party picker to let the player choose from their new companions!&lt;br /&gt;
                    SetPartyPickerGUIStatus(2);&lt;br /&gt;
                    ShowPartyPickerGUI();                                                                                                                    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example shows several of the more simple ways of invoking the function.  Check the comments at the start of the function for a full list of arguments.&lt;br /&gt;
&lt;br /&gt;
I would suggest best practice for most followers would be to call as follows:&lt;br /&gt;
&lt;br /&gt;
'''hireCustomFollower(oFollower, CLASS, PLOT, PLOT_FLAG, SPECIALISATION)'''&lt;br /&gt;
&lt;br /&gt;
This will safely set the follower up as the desired class and specialisation (doubly important if there are spec abilities in their ALTable) while setting your plot flag for them being in the party.  hireCustomFollower(oFollower, CLASS, PLOT, PLOT_FLAG, SPECIALISATION, 0, TRUE) will do the same while invoking the Party Picker automatically.&lt;br /&gt;
&lt;br /&gt;
Note that the specialisations are abilities and not classes - you'll find them as ABILITY_HIDDEN_ constants.&lt;br /&gt;
&lt;br /&gt;
If it's all worked, you should find you can now add followers with a lot more flexibility!&lt;br /&gt;
&lt;br /&gt;
[[File:picker_advanced.jpg|thumb|500px|center]]&lt;br /&gt;
&lt;br /&gt;
== Common Follower Problems &amp;amp; FAQ ==&lt;br /&gt;
&lt;br /&gt;
====Why don't my followers gain XP?====&lt;br /&gt;
There is a bug in UT_HireFollower. Make a copy of UT_HireFollower in a function of your own, then make the following change:&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, TRUE);&lt;br /&gt;
to&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, bPreventLevelup);&lt;br /&gt;
&lt;br /&gt;
====When I choose followers from the Party Picker, they spawn into the area but do not join.====&lt;br /&gt;
&lt;br /&gt;
You need to intercept the EVENT_TYPE_PARTYMEMBER_ADDED event and set the follower to FOLLOWER_STATE_ACTIVE.  See Simple Follower Creation earlier in this document.&lt;br /&gt;
&lt;br /&gt;
====My followers don't have skill trees!====&lt;br /&gt;
&lt;br /&gt;
If a follower hasn't been through an initial chargen/autolevel event (via player_core/sys_autolevel_h) then the skill tree doesn't show.  You're probably trying to be clever and get around UT_HireFollower without going all the way (see monster function above ^_^).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====My followers don't have a class====&lt;br /&gt;
&lt;br /&gt;
GetCreatureCoreClass() seems flaky under some conditions.  It's best to explicitly set the class yourself; this is why class is currently a mandatory argument to hireCustomFollower()&lt;br /&gt;
&lt;br /&gt;
====Dog talents and equipment slots don't work====&lt;br /&gt;
Symptoms: dog talents appear on the talents screen but remain greyed out on level up. Warrior talents appear in the quickslots. Equipment slots are for humans, not dogs.&lt;br /&gt;
&lt;br /&gt;
Line 78 of packages_base in packages.xls (Dog) should have the LevelUpTable column set to 257 which is the ALDog table.&lt;br /&gt;
&lt;br /&gt;
The EquipmentLayout 2DA needs a new entry for the follower:&lt;br /&gt;
&lt;br /&gt;
 ID=same as partypicker 2DA	&lt;br /&gt;
 Tag=follower tag	&lt;br /&gt;
 AvailableEquipmentSlots=794624&lt;br /&gt;
 Layout=2	&lt;br /&gt;
 EnableWeaponSets=0&lt;br /&gt;
&lt;br /&gt;
If the creature is not using the appearance &amp;quot;Dog, Party Member&amp;quot;, it needs a new appearance line in APR_base. Most of the entries can be copied from the standard appearance (e.g. Wolf), but &lt;br /&gt;
&lt;br /&gt;
 MaxScaleLevel=-1&lt;br /&gt;
 DefaultArmor=&lt;br /&gt;
 AppearanceRestrictionGroup=1&lt;br /&gt;
&lt;br /&gt;
Otherwise, it won't be able to progress beyond a specified level. The player will receive an unwanted set of armour when the it is hired, and it won't be able to use Marabi crunch items. You may also need to tweak PERSPACE and/or BumpLevel if excessive clipping occurs.&lt;br /&gt;
&lt;br /&gt;
====Isn't there an easier way to do this?====&lt;br /&gt;
&lt;br /&gt;
Possibly.  There is a way of recruiting a follower by setting a plot flag.  However I don't understand it, and I expect it still doesn't allow custom autolevel templates, full control over specialisations etc.  There's still a fair bit of stuff hardcoded for the core followers, I'm not sure putting a custom follower through the same process as Al, Leli et al will have good results.&lt;br /&gt;
&lt;br /&gt;
The next section answers this question, up to a point.&lt;br /&gt;
&lt;br /&gt;
==== What if there are more than three potential followers? ====&lt;br /&gt;
This example handles larger numbers of followers, and doesn't force the player to use the party picker unless the party is already full.&lt;br /&gt;
&lt;br /&gt;
The prefix zzz, used throughout, can be replaced with whatever [[Prefixes_in_use | prefix]] you are using for your resources.&lt;br /&gt;
&lt;br /&gt;
If you're making a new campaign, to keep life simple, allocate a unique number to each follower. You could either use a creature variable or a script, e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Party member id (e.g. 1=Alicia, 2=Godwin...)&lt;br /&gt;
int zzzPartyMemberID(object oPartyMember)&lt;br /&gt;
{&lt;br /&gt;
  string sPartyMember = GetTag(oPartyMember);&lt;br /&gt;
&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_alicia&amp;quot;) return 1;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_godwin&amp;quot;) return 2;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_harold&amp;quot;) return 3;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_lara&amp;quot;  ) return 4;&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make two separate plots, e.g. zzzpt_hired for when a follower is first recruited, and zzzpt_party to flag whether they're currently in the party. Use flag values that correspond to the unique follower id, e.g. ZZZPT_HIRED_GODWIN will be 2.&lt;br /&gt;
&lt;br /&gt;
If you're modifying the official campaign, you won't be able to make this simplification - you'll need a set of plot flags for your new party members, similar to the official ones. The logic of what follows is still correct, it just means that instead of having one set of common code that works for everyone, you have to explicitly script each party member individually using their personal plot flags.&lt;br /&gt;
&lt;br /&gt;
Follower conversation is now very simple. In Godwin's dialogue, the hiring line will be conditional - when ZZZPT_HIRED_GODWIN is clear - and it will set ZZZPT_HIRED_GODWIN.  No conversation script is necessary. Instead, in the properties of the plot zzzpt_hired, we add a plot event script, as follows.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// PARTY HIRE PLOT SCRIPT&lt;br /&gt;
//&lt;br /&gt;
// This is called in conversation when a party member is hired for the first time.&lt;br /&gt;
// If the party is full, the party picker is displayed, which forces the PARTYMEMBER_ADDED&lt;br /&gt;
// module event.&lt;br /&gt;
//&lt;br /&gt;
// The flag value is never referenced, because the code is common for all party members.&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;events_h&amp;quot;&lt;br /&gt;
#include &amp;quot;global_objects_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_rewards_h&amp;quot;&lt;br /&gt;
#include &amp;quot;log_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plot_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;zzz_h&amp;quot;                  // A header containing the zzzPartyMemberID function&lt;br /&gt;
#include &amp;quot;plt_zzzpt_hired&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_zzzpt_party&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    event  eParms             = GetCurrentEvent();&lt;br /&gt;
    int    nType              = GetEventType(eParms);       // GET or SET&lt;br /&gt;
    string strPlot            = GetEventString(eParms, 0);  // Plot GUID&lt;br /&gt;
    int    nFlag              = GetEventInteger(eParms, 1); // Plot flag&lt;br /&gt;
    object oParty             = GetEventCreator(eParms);    // Plot table owner&lt;br /&gt;
    object oFollower          = GetEventObject(eParms, 0);  // Conversation owner (if any)&lt;br /&gt;
    int    nPlotType          = GetEventInteger(eParms, 5); // Plot type&lt;br /&gt;
&lt;br /&gt;
    int    bIsTutorial        = GetM2DAInt(TABLE_PLOT_TYPES, &amp;quot;IsTutorial&amp;quot;, nPlotType);&lt;br /&gt;
    int    bIsCodex           = GetM2DAInt(TABLE_PLOT_TYPES, &amp;quot;IsCodex&amp;quot;, nPlotType);&lt;br /&gt;
&lt;br /&gt;
    int    nResult            = FALSE;                      // return value for DEFINED GET&lt;br /&gt;
    object oPC                = GetPartyLeader();&lt;br /&gt;
&lt;br /&gt;
    plot_GlobalPlotHandler(eParms); // any global plot operations, including debug info&lt;br /&gt;
&lt;br /&gt;
    if (nType == EVENT_TYPE_SET_PLOT) // actions -&amp;gt; normal flags only&lt;br /&gt;
    {&lt;br /&gt;
        int nValue    = GetEventInteger(eParms, 2); // 0=Clear 1=Set&lt;br /&gt;
        int nOldValue = GetEventInteger(eParms, 3); // Current flag value&lt;br /&gt;
&lt;br /&gt;
        if (nValue)&lt;br /&gt;
          {&lt;br /&gt;
            if (GetArraySize(GetPartyList(oPC)) &amp;lt; 4)&lt;br /&gt;
              {&lt;br /&gt;
                // Code from UT_HireFollower with level up bug fixed&lt;br /&gt;
                SetAutoLevelUp(oFollower, 2);&lt;br /&gt;
                SetGroupId(oFollower, GetGroupId(GetHero()));&lt;br /&gt;
                WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, FALSE);  &lt;br /&gt;
                // End of code from UT_HireFollower&lt;br /&gt;
                AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
                WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), TRUE);&lt;br /&gt;
              }&lt;br /&gt;
            else&lt;br /&gt;
              {&lt;br /&gt;
                WR_SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE, FALSE);&lt;br /&gt;
                SetEventScript(oFollower, RESOURCE_SCRIPT_PLAYER_CORE);&lt;br /&gt;
                SendPartyMemberHiredEvent(oFollower, TRUE);&lt;br /&gt;
//                SetPartyPickerGUIStatus(PP_GUI_STATUS_USE);&lt;br /&gt;
//                ShowPartyPickerGUI();&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
     }&lt;br /&gt;
     else // EVENT_TYPE_GET_PLOT -&amp;gt; defined conditions only&lt;br /&gt;
     {&lt;br /&gt;
        switch(nFlag)&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    plot_OutputDefinedFlag(eParms, nResult);&lt;br /&gt;
    return nResult;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We still need to handle the party picker events in our module event script:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         // PARTY MEMBER ADDED - Allow XP gain. Come here, follow me, flag as party member.&lt;br /&gt;
         case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
         {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&lt;br /&gt;
            WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), TRUE);&lt;br /&gt;
            break;&lt;br /&gt;
         }&lt;br /&gt;
         // PARTY MEMBER DROPPED - flag as not party member.&lt;br /&gt;
         case EVENT_TYPE_PARTYMEMBER_DROPPED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), FALSE);&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When we need to refer to a particular follower explicitly, we can still do so - for example, the flag ZZZPT_PARTY_GODWIN will tell use whether Godwin is currently in the party or not.&lt;br /&gt;
&lt;br /&gt;
==== How do I turn off sustained abilities when a follower is dismissed? ====&lt;br /&gt;
'''Please note:''' The 1.04 DA:O patch is bugged and removed/broke several features of the toolkit, if you are using it please follow [http://social.bioware.com/forum/1/topic/71/index/3172230/1#3172537 these steps] to re-enable them as one is required for the script below to compile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is a potential exploit in what we've done so far. If a follower casts a sustained spell like Flaming Weapons, it affects all party members. When the follower is dismissed, the remaining party members continue to benefit from the spell.&lt;br /&gt;
&lt;br /&gt;
We can prevent this by deactivating modal abilities before opening the party picker. Add these snippets to the module event script:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;ability_h&amp;quot;&lt;br /&gt;
void zDeactivateModalAbilities();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         case EVENT_TYPE_PARTYPICKER_INIT:&lt;br /&gt;
           {&lt;br /&gt;
             // Deactivate party modal abilities. This ensures that the party no longer benefits&lt;br /&gt;
             // from spells like Flaming Weapons if the caster is dismissed from the party.&lt;br /&gt;
             zDeactivateModalAbilities();&lt;br /&gt;
             break;&lt;br /&gt;
           }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The function looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Deactivate party's modal abilities&lt;br /&gt;
&lt;br /&gt;
void zDeactivateModalAbilities()&lt;br /&gt;
{&lt;br /&gt;
  object    oPC            = GetHero();&lt;br /&gt;
  object [] oFollowerTable = GetPartyList(oPC);&lt;br /&gt;
  object    oFollower;&lt;br /&gt;
  int       nPartySize     = GetArraySize(oFollowerTable);&lt;br /&gt;
  int []    nAbilityTable;&lt;br /&gt;
  int       nAbilityCount;&lt;br /&gt;
  int       nAbility;&lt;br /&gt;
  int       i              = -1;&lt;br /&gt;
  int       j;&lt;br /&gt;
&lt;br /&gt;
  while (++i &amp;lt; nPartySize)&lt;br /&gt;
    {&lt;br /&gt;
      oFollower      = oFollowerTable[i];&lt;br /&gt;
      nAbilityTable  = GetAbilityList(oFollower);&lt;br /&gt;
      nAbilityCount  = GetArraySize(nAbilityTable);&lt;br /&gt;
      j              = -1;&lt;br /&gt;
&lt;br /&gt;
      while (++j &amp;lt; nAbilityCount)&lt;br /&gt;
        {&lt;br /&gt;
          nAbility = nAbilityTable[j];&lt;br /&gt;
&lt;br /&gt;
          if (Ability_IsAbilityActive(oFollower, nAbility))&lt;br /&gt;
            if (Ability_IsModalAbility(nAbility))&lt;br /&gt;
              Ability_DeactivateModalAbility(oFollower, nAbility);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If other ways of dismissing party members are permitted, the same function can be used.&lt;br /&gt;
&lt;br /&gt;
== Advanced Follower Creation: An Alternative Approach ==&lt;br /&gt;
&lt;br /&gt;
While these things are to a large extent a matter of taste, I see no reason to reinvent the wheel when there is a perfectly good wheel at hand. The following describes how to adapt the existing machinery for the recruitment and tracking of your own party members.&lt;br /&gt;
&lt;br /&gt;
First create the setup as described above in Simple Follower Creation, except for the scripts and plot tables. In addition, create the GDA extensions for a level-up table and the M2DA which points to those tables, as described in Advanced Follower Creation above.&lt;br /&gt;
&lt;br /&gt;
Now ...&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Create a party plot table ===&lt;br /&gt;
&lt;br /&gt;
Have a look at the gen00pt_party plot table and create a similar table for your own followers. Don't bother with the Defined Flags for the moment, just the Main Flags will do, ie recruited, in-camp and in-party for each follower. (Critical Note: Do not duplicate the plot table, create one from scratch. This is the case for ALL plot tables because of a show-stopping bug which means a new GUID is not assigned on Duplicate of a plot.)&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Create a party script ===&lt;br /&gt;
&lt;br /&gt;
Duplicate the gen00pt_party script and rename for your module (conventionally plot tables and their plot scripts have the same name). Delete (or comment out) the Defined Flags section at the end and any lines dealing with logging and tutorials. Change names to those of your party members. If you are using gifting, approval or forced inclusion you may wish to retain those sections of code, but additional machinery will be needed for these facilities to work. For approval you can specify a starting level of approval here for each follower if you want it to be other than zero (as per the existing section dealing with Dog). Note that the custom hire function at the head of the script allows you to specify whether or not to invoke the party picker on recruitment. You may not want to do so for the first couple of followers (but see below). You should already have defined all required constants in a separate file for your module, eg &amp;lt;module prefix&amp;gt;_constants_h. If not, do so now and include it, as well as your plot table, at the head of the script. Delete includes that only refer to the main campaign. (If this is all Greek to you, spend a couple of hours examining the set-up of the Demo, which is packaged with the toolset, and go through the introductory tutorials referenced on the main page of this wiki).&lt;br /&gt;
&lt;br /&gt;
Looking at the new party script, notice that the follower-in-camp function is not defined. This is because for some arcane reason it is defined in party_h, and unhappily references the main campaign's plot table. So we will have to create a new function to replace it, change the other function's flag reference (for the sake of neatness), and change the call in the main body of the script. (You may decide later for other reasons to replicate and customise party_h, but that won't interfere with re-creating this function here.)&lt;br /&gt;
&lt;br /&gt;
Our two functions at the head of the script should be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;void SetFollowerInParty(object oFollower, string sPlot, int nCampFlag)&lt;br /&gt;
{&lt;br /&gt;
    WR_SetPlotFlag(sPlot, nCampFlag, FALSE);&lt;br /&gt;
    WR_SetObjectActive(oFollower, TRUE);&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE);&lt;br /&gt;
    command cJump = CommandJumpToObject(GetPartyLeader());&lt;br /&gt;
    WR_AddCommand(oFollower, cJump);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SetFollowerInCamp(object oFollower, string sPlot, int nPartyFlag)&lt;br /&gt;
{&lt;br /&gt;
    WR_SetPlotFlag(sPlot, nPartyFlag, FALSE);&lt;br /&gt;
    WR_SetObjectActive(oFollower, FALSE);&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE, FALSE);&lt;br /&gt;
}&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the line in the in-camp sections for each follower should now be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;SetFollowerInCamp(o&amp;lt;follower&amp;gt;, strPlot, &amp;lt;follower&amp;gt;_IN_PARTY);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Step 3: Create package GDAs and reference them in you 2DA_base extension ===&lt;br /&gt;
&lt;br /&gt;
Look at the packages_base GDA and create an extension GDA with one line for each follower based on a main campaign follower that is most like your own follower, eg a sword-shield warrior can be a copy of Alistair, a battle mage a copy of Morrigan, etc. You can look at the Excel version of this GDA to more easily see what the fields mean. It is here that you can specify what if any specialisation will be assigned on hire and the level at which this spec point becomes available. (The IDs for each spec are in the 4000-range of ABI_base.)&lt;br /&gt;
&lt;br /&gt;
Most importantly, it is here also that you define the ID of both your level-up table and the AIP table you are about to create.&lt;br /&gt;
&lt;br /&gt;
Now create aip_follower_&amp;lt;follower name&amp;gt; gda tables, again based on a existing tables most like your own followers. No changes should be required to the copies you create.&lt;br /&gt;
&lt;br /&gt;
In the m2da_base_&amp;lt;your module&amp;gt; extension you have already created, add lines for your AIP tables with a package ID referencing the IDs you assigned in your packages extension table.&lt;br /&gt;
&lt;br /&gt;
Carefully check that all IDs in your GDAs are correct and cross-reference properly, and save the GDAs to your override directory.&lt;br /&gt;
&lt;br /&gt;
Desirable but not obligatory (except for non-humanoid characters), is an extension to the Portraits gda. Finally the Equipment Layout gda will need an extension for non-humanoids, who use a different equipment mask.&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Module script addition ===&lt;br /&gt;
&lt;br /&gt;
Modify your own module script to point to the new plot table and your own followers. To see an example of the required code for the two new sections look at the relevant section of module_core, which are for EVENT_TYPE_PARTYMEMBER_ADDED and EVENT_TYPE_PARTYMEMBER_DROPPED.&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
The recruit flag is set in a conversation (usually, but it could be a script) and that event is then processed by the plot script, which among other things sets both the in-camp and in-party flags, and fires up the party picker by default. If the player then selects the follower in the picker, the in-camp flag is unset (or vice versa if the follower is not selected to join). Subsequently, if the character is selected (or unselected) in the picker, the event is picked up by the module script, which sets the relevant plot flag as true, and that plot event is then sent to the plot scipt which sets the other flag as false. &lt;br /&gt;
&lt;br /&gt;
(Note that if the party picker is turned off for a particular follower's recruit event, that follower will be placed in the active party regardless of the number of members, so ONLY do this for a follower who cannot be recruited when there are already 3 possible followers.)&lt;br /&gt;
&lt;br /&gt;
On recruitment, player_core rebuilds the character according to the specifications laid out in the GDAs, so no further scripting is required.&lt;br /&gt;
&lt;br /&gt;
=== Uses ===&lt;br /&gt;
&lt;br /&gt;
To recruit a party member, set the recruit flag from your plot table in the relevant dialogue. Adding or subtracting followers from the active party is automatically tracked via this machinery, and the plot flags can be interrogated in all your scripts and conversations if you need to know who is currently in the party and who is in camp.&lt;br /&gt;
&lt;br /&gt;
Defined flags can be added as you need them to the script and plot table but there is no point having flags that you will not use, so as with all Defined Flags this is an as-you-go decision, but quite easy to do.&lt;br /&gt;
&lt;br /&gt;
Hiring and firing of temporary party members at the start of a campaign (such as Ser Jory, or Jowan, or Soris, etc) can be handled by UT_HireFollower, and the party picker is not invoked (nor is the Party Camp an available destination).&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
If you haven't done so already, create a simple debugging area for your module where you can dump the player, all followers and a couple of conversation dummies, and set up a dialogue in which you can invoke all required flags and conditions and see if they actually work as expected. (This setup can be used to test many other components as well.) Global machinery such as this can be painful to set up and get right (unless you are of an exceptionally methodical cast of mind), but it is worthwhile to ensure they are absolutely bullet-proof before you develop the specifics of your module.&lt;br /&gt;
&lt;br /&gt;
=== The KISS principle ===&lt;br /&gt;
&lt;br /&gt;
This is an &amp;quot;out-of-the-box&amp;quot; solution, and once set up is quite robust. If you want variants not catered for here, do NOT try to modify what you already have working.&lt;br /&gt;
&lt;br /&gt;
'''Use-case:''' You want a follower (example tag: dairren) to be recruited without a set specialisation and one level higher than the PC.&lt;br /&gt;
&lt;br /&gt;
Go to your packages gda and set the spec field to 0. In the character's plot table (you should have at least one for each follower) create a flag which we will call BLAH_BLAH. In the table's plot scipt insert the following very simple event handler:&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;dascript&amp;gt;case BLAH_BLAH:&lt;br /&gt;
         {&lt;br /&gt;
           SetCreatureProperty(oDairren, 38, 1.00); //awards the spec point; field from the properties gda&lt;br /&gt;
           int aLevel = GetLevel(oHero); //some simple arithmetic to find out the XP we need to award&lt;br /&gt;
           int bLevel = (aLevel+1);&lt;br /&gt;
           int aPoints = RW_GetXPNeededForLevel(aLevel);&lt;br /&gt;
           int bPoints = RW_GetXPNeededForLevel(bLevel);&lt;br /&gt;
           int targetPoints = (bPoints - aPoints);&lt;br /&gt;
           RewardXP(oDairren, targetPoints, FALSE, TRUE); //award the XP, and we're done&lt;br /&gt;
           break;&lt;br /&gt;
	 }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
The flag can be set in the same conversation as the recruit flag, so long as it comes afterwards. This way you not only maintain the integrity of your core machinery, but keep exceptions/variations for particular characters where they belong -- with that character's plot tables and scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Obadiah</name></author>	</entry>

	<entry>
		<id>http://datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16466</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16466"/>
				<updated>2011-07-13T16:07:05Z</updated>
		
		<summary type="html">&lt;p&gt;Obadiah: /* Capture the EVENT_TYPE_PARTYMEMBER_ADDED Event */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Simple Follower Creation ==&lt;br /&gt;
&lt;br /&gt;
Follow these steps to create a follower that&lt;br /&gt;
&lt;br /&gt;
- Levels up with a default package&lt;br /&gt;
&lt;br /&gt;
- Can be chosen from the party picker&lt;br /&gt;
&lt;br /&gt;
- Can gain XP&lt;br /&gt;
&lt;br /&gt;
This guide assumes you know how to create a creature and are comfortable with basic scripting.&lt;br /&gt;
&lt;br /&gt;
You should only use this simple method if you are sure there will be empty space in the active party when your follower is recruited.&lt;br /&gt;
&lt;br /&gt;
A more comprehensive approach when there are more than three potential party members is discussed in the FAQ below. It's worth taking the time to understand the basics first, though. &lt;br /&gt;
&lt;br /&gt;
=== Create the creature ===&lt;br /&gt;
&lt;br /&gt;
Create a creature to act as your follower.  Set its name, appearance, gender, head morph, conversation, inventory etc as you want them to behave in-game.&lt;br /&gt;
&lt;br /&gt;
Set an appropriate '''Tag''' (you'll be using it a lot).  I suggest &amp;quot;party_charname&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Make sure you choose a '''Class'''.  For most followers this should be Rogue, Warrior or Wizard.&lt;br /&gt;
&lt;br /&gt;
[[File:class.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Under Package/Scaling set:&lt;br /&gt;
&lt;br /&gt;
'''General Package Type''' to be '''Party Members'''&lt;br /&gt;
&lt;br /&gt;
'''Package''' to be an appropriate value (probably &amp;quot;Generic - Wizard&amp;quot; or similar)&lt;br /&gt;
&lt;br /&gt;
'''Package AI''' (there should only be one choice)&lt;br /&gt;
&lt;br /&gt;
'''Rank''' to be '''Player'''&lt;br /&gt;
&lt;br /&gt;
[[File:package.jpg]]&lt;br /&gt;
&lt;br /&gt;
Save and export your character as normal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Overlay char_stage ===&lt;br /&gt;
&lt;br /&gt;
In the official campaign, the party picker uses a special area called char_stage. Whether you're extending the official campaign or making a standalone campaign, there is a function that allows you to overlap the offical stage with your own, so that both stages are active simultaneously in game.&lt;br /&gt;
&lt;br /&gt;
In your resource palette, right-click char_stage under the Global folder and select Duplicate to make a copy of the stage with a new resource name, e.g. my_char_stage. In the resource properties, ensure that both Module and Owner Module are set to your module, and the folder of your choice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:area_palette.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create a new waypoint for your follower to appear on the party picker.  This waypoint '''must''' have a tag in the form of &amp;quot;char_&amp;quot; followed by the exact tag of your follower.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:char_stage.jpg]]&lt;br /&gt;
&lt;br /&gt;
In this example the tag of my follower is '''bc_party_miera''' so her waypoint tag must be '''char_bc_party_miera'''&lt;br /&gt;
&lt;br /&gt;
For a standalone module (such as in this example), put your waypoint wherever you please.  The illustrated one is directly on top of Morrigan's.  For an add-in to the main campaign, you should position your wp appropriately relative to the core party members.&lt;br /&gt;
&lt;br /&gt;
Save and export the area.&lt;br /&gt;
&lt;br /&gt;
Add the following to your module event script:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
case EVENT_TYPE_MODULE_GETCHARSTAGE:&lt;br /&gt;
{&lt;br /&gt;
   // Overlay the existing stage with my stage&lt;br /&gt;
   // &amp;quot;my_char_stage&amp;quot; is the resource name of the overlay area&lt;br /&gt;
   // &amp;quot;partypicker&amp;quot; is the name of the default GDA&lt;br /&gt;
   SetPartyPickerStage(&amp;quot;my_char_stage&amp;quot;, &amp;quot;partypicker&amp;quot;);&lt;br /&gt;
   break;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create m2DAs for the Party Picker ===&lt;br /&gt;
&lt;br /&gt;
You will need to create two Excel spreadsheets.&lt;br /&gt;
&lt;br /&gt;
The first should be named (both worksheet and file) '''partypicker_''' with a unique suffix.  In this example, my first spreadsheet is named partypicker_fofbc.xls with a worksheet name of partypicker_fofbc - the suffix being the acronym of my module.&lt;br /&gt;
&lt;br /&gt;
Set up your columns as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:partypickerm2da.jpg]]&lt;br /&gt;
&lt;br /&gt;
The '''ID''' for your follower must be '''12 or higher'''.  11 is the highest value used in the base 2DA.  12 is fine for standalone modules, add-ins will probably want to use an arbitrarily high number to avoid potential conflicts.&lt;br /&gt;
&lt;br /&gt;
The '''Label''' should be the follower's name as you wish it to appear on the party picker.&lt;br /&gt;
&lt;br /&gt;
The '''Tag''' must be your follower's tag.&lt;br /&gt;
&lt;br /&gt;
All other values are non-functioning defaults and should be specified as in the image above unless you know explicitly what you're doing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NOTE - ON SELECTION ANIMATIONS'''&lt;br /&gt;
 &lt;br /&gt;
Add Animation and Remove Animation are actually Id numbers of different animations, taken from anim_base.gda&lt;br /&gt;
&lt;br /&gt;
Enter and Exit version of animations are generally the best ones to use, altough one can try others. NOT ALL ANIMATIONS WILL WORK, since some require special conditions.&lt;br /&gt;
Here are some examples you can use:&lt;br /&gt;
&lt;br /&gt;
819 - talk cursing&lt;br /&gt;
&lt;br /&gt;
629 - reading a book (doesn't work, since it probably requires a book object)&lt;br /&gt;
&lt;br /&gt;
844 - hands behind back (848 and 849 are Enter and Exit versions respectfully)&lt;br /&gt;
&lt;br /&gt;
850 - chest pounding salute&lt;br /&gt;
&lt;br /&gt;
811 - fist pounding&lt;br /&gt;
&lt;br /&gt;
277 - dance&lt;br /&gt;
&lt;br /&gt;
247 - cast area spell&lt;br /&gt;
&lt;br /&gt;
500 - vfx cast&lt;br /&gt;
&lt;br /&gt;
600 - surprised&lt;br /&gt;
&lt;br /&gt;
603 - praying&lt;br /&gt;
&lt;br /&gt;
607 - head bow&lt;br /&gt;
&lt;br /&gt;
609 - standing at attention&lt;br /&gt;
&lt;br /&gt;
651,652 - crouch pray (Enter and exit)&lt;br /&gt;
&lt;br /&gt;
808 - point forward&lt;br /&gt;
&lt;br /&gt;
825 - nodding&lt;br /&gt;
&lt;br /&gt;
840 - hand chop or frustration&lt;br /&gt;
&lt;br /&gt;
905,906 - crouch (Enter, Exit)&lt;br /&gt;
&lt;br /&gt;
919,920 - sit on ground (enter, exit)&lt;br /&gt;
&lt;br /&gt;
965 - kneel down loop&lt;br /&gt;
&lt;br /&gt;
972 - wipe nose&lt;br /&gt;
&lt;br /&gt;
976,977 - squat (Enter, Exit)&lt;br /&gt;
&lt;br /&gt;
986 - wipe eyes&lt;br /&gt;
&lt;br /&gt;
998,999 - hands clasped (Enter, exit)&lt;br /&gt;
&lt;br /&gt;
3029 - inspect nails&lt;br /&gt;
&lt;br /&gt;
3031,3032 - playful (enter, exit)&lt;br /&gt;
&lt;br /&gt;
3054,3056 - slouch (enter, exit)&lt;br /&gt;
255 - in-place fly&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NOTE - ON SELECTION VFX''' &lt;br /&gt;
&lt;br /&gt;
The VFX column is the ID of the vFX effect taken from vFx_base.gda. This one is a bit more tricky, since it also references the BlendTree value from the same file.&lt;br /&gt;
Find the ID of the spell effect and look for the BlendTreeName column (should the the 12th columun) and enter BOTH into the respective columns for your character in the partypicker file.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
ID      ---      BLENDTREENAME      ---   EFFECT&lt;br /&gt;
&lt;br /&gt;
6039    ---     fxm_energy_up_p    ---    Lady of the Forest pillar of light&lt;br /&gt;
&lt;br /&gt;
6040    ---     fxm_power_in_p      ---   Branka - power in&lt;br /&gt;
&lt;br /&gt;
3054    ---     fxc_lotf_c          ---   Lady of the Forest - swirling leaves&lt;br /&gt;
&lt;br /&gt;
3009    ---     fxc_succubus_c     ---    Succubus crust&lt;br /&gt;
&lt;br /&gt;
1549    ---     fxa_hly_imp_c       ---   Holy Impact crust&lt;br /&gt;
&lt;br /&gt;
1076    ---     fxa_spi_aur_mht_c   ---   Spirit - Aura Might crust&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second spreadsheet should be named '''party_picker_''' (note middle underscore).  Once again append your unique suffix (in this example party_picker_fofbc.xls with party_picker_fofbc as its worksheet).&lt;br /&gt;
&lt;br /&gt;
Set up your columns and data like so:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:party_pickerm2da.jpg]]&lt;br /&gt;
&lt;br /&gt;
'''ID''' and '''Tag''' should match what you did in the first spreadsheet.  Specify INVALID COLUMN for the third column.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you're familiar with m2DAs, generate them from these files, copy them to your module's override directory, and skip to the next step.  Otherwise, read on:&lt;br /&gt;
&lt;br /&gt;
- Go to '''\Program Files\Dragon Age\tools\ResourceBuild\Processors''' (or wherever you installed Dragon Age)&lt;br /&gt;
&lt;br /&gt;
- Copy '''ExcelProcessor.exe''' from that folder to whichever folder has the excel sheets you just created.&lt;br /&gt;
&lt;br /&gt;
- Drag and drop your xls files onto ExcelProcessor.  This will create .gda files.&lt;br /&gt;
&lt;br /&gt;
- Copy these .gda files to your module's export directory (probably \Documents\Bioware\Dragon Age\AddIns\yourModule\module\override\toolsetexport).  Make sure they are included in your .dazip when the time comes to build your module.&lt;br /&gt;
&lt;br /&gt;
If you are an OpenOffice user and have trouble with ExcelProcessor, you can use [http://social.bioware.com/project/755/ GDApp] to directly create the 2DAs.  It rocks!&lt;br /&gt;
&lt;br /&gt;
=== Capture the EVENT_TYPE_PARTYMEMBER_ADDED Event ===&lt;br /&gt;
&lt;br /&gt;
Amusingly enough, the Party Picker does not actually add followers to the party.  However it raises an event that allows you to do so.  Your module script needs to capture this event and execute some code.&lt;br /&gt;
&lt;br /&gt;
The following example shows what to do with the event.  The full script would work as a module script for an add-in (assuming it didn't need to do anything else), but otherwise you'll have to incorporate the event into your own module script.  &lt;br /&gt;
&lt;br /&gt;
If you're not sure how to set a module script, go to '''File''' then '''Manage Modules,''' select your module and click '''Properties.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEventType = GetEventType(ev);&lt;br /&gt;
    switch(nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);  //Allows the follower to gain XP&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));   //Ensures follower appears at PC's location.&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);  //Adds follower to the active party&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE)''' is the key statement to add the follower to the active party.  You must have this.&lt;br /&gt;
&lt;br /&gt;
'''SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0)''' is a bug-fix, as followers hired with UT_HireFollower() do not receive XP by default.  This statement fixes that, and I consider it best practice to keep it in this event to ensure it is always set.  You will not wish to do this if you want a follower that should not gain XP to be on the party picker.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that you do not need to intercept the corresponding event for a party member being removed - the party picker handles spawning/despawning, and thus will successfully remove members.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remember to save and export your module script.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you're not sure how to set a module script, go to '''File''' then '''Manage Modules,''' select your module and click '''Properties.'''  The module script is in the General category, as seen below:&lt;br /&gt;
&lt;br /&gt;
[[File:module_script.jpg]]&lt;br /&gt;
&lt;br /&gt;
You can set this to any script you've created.  See [[Scripting tutorial]] and [[Character generation]] for more background and some simple examples of event-handling scripts.  In general, you will want to make sure standalone module scripts pass events through to module_core (as in the [[Character generation]] examples) and add-in scripts do not (as in the example above).&lt;br /&gt;
&lt;br /&gt;
=== Create Your Hiring Script ===&lt;br /&gt;
&lt;br /&gt;
Now all that remains is to actually hire the follower :)&lt;br /&gt;
&lt;br /&gt;
Create a script to handle the hiring (which will most likely be fired from a conversation).  The script is quite simple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
        object oFollower = GetObjectByTag(&amp;quot;bc_party_miera&amp;quot;); //Use CreateObject() if the creature isn't present in the module yet&lt;br /&gt;
&lt;br /&gt;
        UT_HireFollower(oFollower);   //Hires the follower&lt;br /&gt;
&lt;br /&gt;
        SetPartyPickerGUIStatus(2);&lt;br /&gt;
&lt;br /&gt;
        ShowPartyPickerGUI();  //Shows the Party Picker; necessary for the follower to gain XP&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure you use your own follower's tag and not the example one :)&lt;br /&gt;
&lt;br /&gt;
This script fires the party picker after hiring the follower.  That is absolutely necessary via this method, as we have put the XP fix onto an event fired by the party picker.  You cannot put the XP fix into this script, it must be called from a later one (the bug is caused by an errant call to an event in player_core, which will be executed AFTER this script).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The easiest way to use this script is directly from conversation, putting it as an action on a line of dialogue where the PC invites the follower to join them.  If you're not sure how to associate a script with a dialogue line, see the following image:&lt;br /&gt;
&lt;br /&gt;
[[File:hire_conv.jpg]]&lt;br /&gt;
&lt;br /&gt;
Create your dialogue as normal, select the line you want to fire the script, and click the '''Plots and Scripting''' tab.  Use the '''Script''' file chooser in the Action section to browse to the script you created.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If everything worked, you should see something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:picker_success.jpg|thumb|200px|center]]&lt;br /&gt;
&lt;br /&gt;
== Advanced Follower Creation ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow these steps to have full control over the creation of your follower, with options such as:&lt;br /&gt;
&lt;br /&gt;
- Unique level-up template&lt;br /&gt;
&lt;br /&gt;
- Class and specialisation chosen via script&lt;br /&gt;
&lt;br /&gt;
- Any starting state&lt;br /&gt;
&lt;br /&gt;
- Level higher than the PC&lt;br /&gt;
&lt;br /&gt;
- Starts with a specialisation point rather than a specific specialisation&lt;br /&gt;
&lt;br /&gt;
- Set plot flags in the call to the hire script&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Prepare Creature, char_stage and Party Picker m2DAs ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Follow the same steps to create your follower creature, char_stage and Party Picker m2DAs as above.&lt;br /&gt;
&lt;br /&gt;
=== Create Party Plot ===&lt;br /&gt;
&lt;br /&gt;
While not necessary, it's very helpful to have plot flags set when a follower is hired or joins/leaves the active party.  This makes conversation interjections and the like very easy.&lt;br /&gt;
&lt;br /&gt;
Create a plot with appropriate flags.  There's no real need to associate journal text with them:&lt;br /&gt;
&lt;br /&gt;
[[File:follower_plot.jpg]]&lt;br /&gt;
&lt;br /&gt;
See FAQ for an alternative approach to plots when there are more than three potential party members.&lt;br /&gt;
&lt;br /&gt;
=== Add Plot Flags to Party Picker Event Intercept ===&lt;br /&gt;
&lt;br /&gt;
We then update our module script to make use of that plot, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_bc_create_party&amp;quot;   //make sure you include your own plot, not mine&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEventType = GetEventType(ev);&lt;br /&gt;
    switch(nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
            SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&lt;br /&gt;
&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));   //Ensures follower appears at PC's location.&lt;br /&gt;
            &lt;br /&gt;
            if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               //You must explicitly test for your follower's tag.&lt;br /&gt;
                WR_SetPlotFlag(PLT_BC_CREATE_PARTY, PARTY_MIERA_IN_PARTY, TRUE);     //Make sure you use your own flags!&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            break;&lt;br /&gt;
        }  &lt;br /&gt;
        &lt;br /&gt;
        case EVENT_TYPE_PARTYMEMBER_DROPPED:                    &lt;br /&gt;
        {&lt;br /&gt;
              object oFollower = GetEventObject(ev, 0); &lt;br /&gt;
              &lt;br /&gt;
              if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) { &lt;br /&gt;
                WR_SetPlotFlag(PLT_BC_CREATE_PARTY, PARTY_MIERA_IN_PARTY, FALSE);     //As above, but set false.&lt;br /&gt;
              }&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create a Level Up Template ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can skip this step if you're content to use one of the generic Rogue, Wizard or Warrior templates, but I don't recommend it.  Making a template that suits your character is easy and will almost always be better for the player than a generic one that spends points poorly.&lt;br /&gt;
&lt;br /&gt;
Go to \Program Files\Dragon Age\tools\Source\2DA (or wherever you installed Dragon Age).&lt;br /&gt;
&lt;br /&gt;
You should see a number of excel sheets of the form '''ALCharacter.xls''' (such as ALAlistair.xls, ALLeliana.xls, ALRogue_Default.xls etc).  Open the one closest to your character (ie Morrigan or Wynne for a wizard, Leliana or Zevran for a rogue).  Save a copy as '''ALYourcharacter.xls''' in whatever directory you're using to create your 2DAs, remembering to rename the worksheet '''ALYourcharacter''' (in this example, ALMiera.xls with ALMiera as its worksheet).&lt;br /&gt;
&lt;br /&gt;
It should look something like this:&lt;br /&gt;
&lt;br /&gt;
[[File:ALtable.jpg|thumb|500px|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Columns B''' and '''C''' are the talents/spells available to this character.  Do not change them.&lt;br /&gt;
&lt;br /&gt;
'''Columns F''' and '''G''' are the skills available to this character.  Do not change them.&lt;br /&gt;
&lt;br /&gt;
We will edit the remaining columns like so:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Setting Stat Weights ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The stat weights in '''column J''' determine how the follower will spend their attribute points, in a rough ratio.  So if Dexterity is set to 1.5 and Intelligence to 1, you should expect to see 3 points of Dex for every 2 points of Cunning in-game (note Intelligence is the label used in the toolset for Cunning).&lt;br /&gt;
&lt;br /&gt;
Simply change the values in J to reflect how you'd like the character to spend their points.  In this example we're creating a wizard, so we're not going to mess around:&lt;br /&gt;
&lt;br /&gt;
[[File:miera_stat_weights.jpg]]&lt;br /&gt;
&lt;br /&gt;
This character will only raise magic.  I set the value to 5 rather than something like 1 to provide room underneath for the other stats while still overwhelmingly favouring magic, but in practice I only really ever want that one stat. &lt;br /&gt;
&lt;br /&gt;
In a note left on this column in the existing templates, Bioware's Georg Zoeller writes, &amp;quot;This is the weight of each attribute (row id links into properties.xls.id). 1.0 means 'try to keep this attribute level' (spend 1 point per level). 0.5 means 'try to spend 1 point every two levels' and so on.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The default Mage, Rogue and Warrior templates include '''column L''' labeled &amp;quot;AttInit.&amp;quot; Editing these values seems to have no effect on followers set to use these templates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Setting Talent and Skill Priorities ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Columns D''' and '''E''' are the talents/spells that the character will buy, in preference order from top to bottom.&lt;br /&gt;
&lt;br /&gt;
'''Columns H''' and '''I''' are the skills that the character will buy, in preference order from top to bottom.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To change these, just copy the appropriate two cells from columns B&amp;amp;C or F&amp;amp;G over the ones you want to replace.&lt;br /&gt;
&lt;br /&gt;
For example, here we're copying Morrigan's template.  Morrigan has Spider Shape high in her preferences, which we do not want.&lt;br /&gt;
&lt;br /&gt;
[[File:AlMori_talent_pref.jpg]]&lt;br /&gt;
&lt;br /&gt;
We decide we'd prefer Flame Blast, so we find it in columns B&amp;amp;C and copy both cells:&lt;br /&gt;
&lt;br /&gt;
[[File:ALMori_copy.jpg]]&lt;br /&gt;
&lt;br /&gt;
Then we select the cells we want to replace in columns D&amp;amp;E and paste over them:&lt;br /&gt;
&lt;br /&gt;
[[File:ALMori_paste.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Continue this process until your priorities list for both skills and talents/spells is exactly as you want it.  Make sure you have at least as many priorities as the core follower you're copying - points that cannot be spent according to these priorities have a habit of vanishing.&lt;br /&gt;
&lt;br /&gt;
If you used any abilities from a specialisation, make sure you remember to set that specialisation with the function we'll introduce later.  The autolevel scripts will add specialisation abilities to a character regardless of whether they have that spec or not.&lt;br /&gt;
&lt;br /&gt;
==== Create a M2DA_base_ m2DA ====&lt;br /&gt;
&lt;br /&gt;
Dragon Age will need to know where to find your autolevel template.  We tell it by extending M2DA_base.gda&lt;br /&gt;
&lt;br /&gt;
Create a spreadsheet with the name and worksheet name in the form '''M2DA_base_''' with your unique suffix (in this example, M2DA_base_fofbc.xls with M2DA_base_fofbc as a worksheet).&lt;br /&gt;
&lt;br /&gt;
Set up its columns and data like so (note I used GDApp because Open Office wasn't cooperating for this one!):&lt;br /&gt;
&lt;br /&gt;
[[File:m2da_base_fofbc.jpg]]&lt;br /&gt;
&lt;br /&gt;
The '''ID''' should be very high to avoid conflicts.  I've arbitrarily chosen 50,000+ here.  Carefully note the ID you've chosen for your character, you will need it later.&lt;br /&gt;
&lt;br /&gt;
Set the '''Label''' and '''Worksheet''' to be the name of your autolevel template worksheet (ALCharactername if you've been following this).&lt;br /&gt;
&lt;br /&gt;
Set the '''PackageIDForAI''' to be 0, it shouldn't be needed for followers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you're done, use ExcelProcessor to make GDAs of both spreadsheets and copy them to your module's export folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
FOR AUTOLEVEL TO WORK AFTER RECRUITING:&lt;br /&gt;
&lt;br /&gt;
Look in packages.xls. &lt;br /&gt;
There is a column called LevelupTable. That links to a corresponding AL* table. For instance,  row 81 is for Leliana. Her LevelupTable value is 258. If you look that up in 2DA_base, you'll see it links to ALLeliana.&lt;br /&gt;
(alternatively, you could try packages_base.gda)&lt;br /&gt;
&lt;br /&gt;
=== Create a New Hire Function Include ===&lt;br /&gt;
&lt;br /&gt;
This section is probably only relevent if you have a specific need to override the functionality of player_core.&lt;br /&gt;
&lt;br /&gt;
Many vital steps of follower addition happen inside an event in player_core.  Followers tend to be extremely buggy (no skill tree, for example) if this event does not fire.&lt;br /&gt;
&lt;br /&gt;
However, that event is not very flexible.  In order to control it to our requirements, we need to replicate its functionality inside our own script.  This is probably much safer than messing with player_core directly!&lt;br /&gt;
&lt;br /&gt;
Create a new script file, naming it something like '''hireCustomFollower_h'''.  We will be including this wherever we want to hire a follower.&lt;br /&gt;
&lt;br /&gt;
Paste in the following script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;sys_chargen_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_rewards_h&amp;quot;&lt;br /&gt;
#include &amp;quot;approval_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_autolevelup_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/*  Jye Nicolson 5-Jan-2010&lt;br /&gt;
This function set duplicates the full functionality chain of UT_HireFollower, with the following exceptions:&lt;br /&gt;
&lt;br /&gt;
-  Followers can gain XP&lt;br /&gt;
-  Autolevel status can be set (default off)&lt;br /&gt;
-  Followers can be set to any starting state (default Available) and will still be properly initalised and added to the party pool&lt;br /&gt;
-  Autolevel tables for non-core followers can be explicitly set.&lt;br /&gt;
-  Class and Specialisation can be chosen via script&lt;br /&gt;
-  Followers without specialisations are granted a spec point by default.&lt;br /&gt;
&lt;br /&gt;
It should only ever be called once each for characters you intend to be full followers.&lt;br /&gt;
Much of the protective code handling summoned creatures etc. in player_core is not present here.&lt;br /&gt;
&lt;br /&gt;
Calling the function:&lt;br /&gt;
&lt;br /&gt;
Simple:&lt;br /&gt;
&lt;br /&gt;
hireCustomFollower(oFollower, CLASS_WARRIOR);&lt;br /&gt;
&lt;br /&gt;
Change the class to CLASS_WIZARD or CLASS_ROGUE as appropriate.  &lt;br /&gt;
This will hire your follower and make them available.  &lt;br /&gt;
They will auto level up with a default package, and receive a free spec point.&lt;br /&gt;
&lt;br /&gt;
Best Practice:&lt;br /&gt;
&lt;br /&gt;
hireCustomFollower(oFollower, CLASS_WARRIOR, PLT_YOUR_PARTY_PLOT, YOUR_FOLLOWER_JOINED_FLAG, ABILITY_TALENT_HIDDEN_CHAMPION);&lt;br /&gt;
&lt;br /&gt;
Where the plot and flag are those for your module (remember to create the plot and include it on the calling script), and ABILITY_TALENT_HIDDEN etc is the desired spec.&lt;br /&gt;
&lt;br /&gt;
You should also have a custom ALTable set up.  &lt;br /&gt;
See wiki for details, and remember to edit it in to GetCustomFollowerALTable below or pass it directly as an argument to hireCustomFollower.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Full argument list:&lt;br /&gt;
&lt;br /&gt;
void hireCustomFollower (&lt;br /&gt;
        object oFollower,   //Pass your follower object, mandatory&lt;br /&gt;
        &lt;br /&gt;
        int nForceClass,    //Pass a Class constant here, usually CLASS_ROGUE, CLASS_WARRIOR, CLASS_WIZARD.  Mandatory due to a bug.&lt;br /&gt;
        &lt;br /&gt;
        string sPlot = &amp;quot;&amp;quot;,   //It's recommended you have a plot flag to be set when the follower joins.  Pass the plot constant here.  Remember to #include in calling script&lt;br /&gt;
        &lt;br /&gt;
        int nPlotFlag = &amp;quot;&amp;quot;,  //And then pass the flag constant.  Will be set to TRUE if available.&lt;br /&gt;
        &lt;br /&gt;
        int nForceSpec = 0,  //This is the ID of the Specialisation you want.  Note they are NOT classes, but abilities.  The full list is:&lt;br /&gt;
                             //ABILITY_SPELL_HIDDEN_ARCANE_WARRIOR, ABILITY_SPELL_HIDDEN_BLOODMAGE, ABILITY_SPELL_HIDDEN_SHAPESHIFTER, ABILITY_SPELL_HIDDEN_SPIRIT_HEALER&lt;br /&gt;
                             //ABILITY_SPELL_HIDDEN_BARD, ABILITY_TALENT_HIDDEN_ASSASSIN, ABILITY_TALENT_HIDDEN_DUELIST, ABILITY_TALENT_HIDDEN_RANGER&lt;br /&gt;
                             //ABILITY_TALENT_HIDDEN_BERSERKER, ABILITY_TALENT_HIDDEN_CHAMPION, ABILITY_TALENT_HIDDEN_REAVER, ABILITY_TALENT_HIDDEN_TEMPLAR&lt;br /&gt;
                             //I recommended forcing a spec, particularly if your ALTable includes abilities from one.&lt;br /&gt;
        &lt;br /&gt;
        int nALTable = 0,    //This is the ID of an ALTable from 2DA_base.GDA or your module's m2DA_base_*.GDA  I recommended the latter, but you can edit that into GetCustomFollowerALTable below rather than passing it.&lt;br /&gt;
        &lt;br /&gt;
        int bInvokePicker = FALSE,  //Sets whether the party picker should be opened on hiring.  I think it's cleaner to call the picker outside this script, particularly if you have multiple hires at once.&lt;br /&gt;
        &lt;br /&gt;
        int nInitialState = FOLLOWER_STATE_AVAILABLE,  //This sets whether the follower joins the active party or not.  Options are:&lt;br /&gt;
                                                       //FOLLOWER_STATE_ACTIVE (put them in the active party)&lt;br /&gt;
                                                       //FOLLOWER_STATE_LOCKEDACTIVE (force them into the active party and keep them there, remember to change this later.&lt;br /&gt;
                                                       //FOLLOWER_STATE_AVAILABLE (make them available on the party picker (if you've set it up for them), but not in the active party)&lt;br /&gt;
                                                       //Plus some others you're unlikely to need at this time.  Defaults to AVAILABLE because having 4+ active followers is screwy.&lt;br /&gt;
                                                       &lt;br /&gt;
        string sCurrPlot = &amp;quot;&amp;quot;,  //If you set FOLLOWER_STATE_ACTIVE or FOLLOWER_STATE_LOCKEDACTIVE, the script will check to see if you passed this.&lt;br /&gt;
                                //It is recommended that you have a plot flag set for a given follower being in the active party, this makes conversation interjection etc. much easier.&lt;br /&gt;
&lt;br /&gt;
        int nCurrPlotFlag = 0,  //This flag will be set if FOLLOWER_STATE_ACTIVE or FOLLOWER_STATE_LOCKEDACTIVE are true&lt;br /&gt;
                                //AND sCurrPlot has a value AND nCurrPlotFlag is &amp;gt; 0.  &lt;br /&gt;
                                //ie if you added someone to the active party and have a plot flag to cope with it.&lt;br /&gt;
&lt;br /&gt;
        int nAutolevel = 0,     //Sets the Autolevel flag on the character sheet.  0 is off, 1 is on, 2 forces it on and removes it so the player can't turn it off.&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
        bFreeSpecPoint = TRUE,  //This grants a specialisation point to the follower if they do not have a specialisation.  &lt;br /&gt;
                                //It's important to set this false for classes that do not have specs, such as CLASS_DOG.&lt;br /&gt;
                                &lt;br /&gt;
        int nTargetLevel = 0,   //If you want a specific level, set this.  Generally not worthwhile unless you set it higher than the player, since they'll just get XP from the party picker anyway.&lt;br /&gt;
        &lt;br /&gt;
        int nMinLevel = 0       //Set this if there's a specific level you don't want the follower to go below.  Probably only useful if the PC might be very low level but not necessarily so. &lt;br /&gt;
        &lt;br /&gt;
        )&lt;br /&gt;
*/       &lt;br /&gt;
/* GetCustomFollowerALTable()  &lt;br /&gt;
This function is where you put your custom table assignments.&lt;br /&gt;
&lt;br /&gt;
You should explicitly test for the tag of your follower (not mine!) and assign a value to nTable from your m2DA extension to M2DA_base &lt;br /&gt;
&lt;br /&gt;
See wiki for details on how to do this, or ignore it to get the default Warrior/Rogue/Wizard AL tables.&lt;br /&gt;
&lt;br /&gt;
NOTE: you MUST explicitly set a table for non-Warrior/Rogue/Wizards, eg dogs.  Use TABLE_AL_DOG for a default Mabari.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
int GetCustomFollowerALTable(object oFollower) {&lt;br /&gt;
    int nTable = _GetTableToUseForAL(oFollower);&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               &lt;br /&gt;
        nTable = 50143;   &lt;br /&gt;
    }   &lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_jysavin&amp;quot;) {&lt;br /&gt;
        nTable = 50144;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_geldual&amp;quot;) {&lt;br /&gt;
        nTable = 50145;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_braghon&amp;quot;) {&lt;br /&gt;
        nTable = 50146;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return nTable;    &lt;br /&gt;
}   &lt;br /&gt;
&lt;br /&gt;
// This just cleans up the main function a little&lt;br /&gt;
&lt;br /&gt;
int GetCustomFollowerTargetLevel(object oFollower, object oHero, int nPackage, int nMinLevel = 0) {&lt;br /&gt;
            int nPlayerLevel = GetLevel(oHero);&lt;br /&gt;
            int nTargetLevel = 0;&lt;br /&gt;
&lt;br /&gt;
            if((nPlayerLevel &amp;gt;= 13) || (nPlayerLevel == 1) || (!_UT_GetIsPlotFollower(oFollower))) {&lt;br /&gt;
               nTargetLevel = nPlayerLevel;&lt;br /&gt;
            } else {&lt;br /&gt;
               nTargetLevel = nPlayerLevel + 1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (nMinLevel == 0) {  //If nMinLevel is not specified, checks package 2DA for a value&lt;br /&gt;
              nMinLevel = GetM2DAInt(TABLE_PACKAGES, &amp;quot;MinLevel&amp;quot;, nPackage);&lt;br /&gt;
             }&lt;br /&gt;
            if(nMinLevel &amp;gt; 0 &amp;amp;&amp;amp; nMinLevel &amp;gt; nTargetLevel) {&lt;br /&gt;
               nTargetLevel = nMinLevel;&lt;br /&gt;
            }          &lt;br /&gt;
            &lt;br /&gt;
            return nTargetLevel;&lt;br /&gt;
    &lt;br /&gt;
}   &lt;br /&gt;
&lt;br /&gt;
// Moving this black box out :)  I don't really understand it, but it should function if you have tactics set up in a package.&lt;br /&gt;
&lt;br /&gt;
void InitCustomFollowerTactics(object oFollower, int nPackage) {&lt;br /&gt;
         int nTableID = GetM2DAInt(TABLE_PACKAGES, &amp;quot;FollowerTacticsTable&amp;quot;, nPackage);&lt;br /&gt;
         if (nTableID != -1)&lt;br /&gt;
            {&lt;br /&gt;
             int nRows = GetM2DARows(nTableID);&lt;br /&gt;
             int nMaxTactics = GetNumTactics(oFollower);&lt;br /&gt;
&lt;br /&gt;
             int nTacticsEntry = 1;&lt;br /&gt;
             int i;&lt;br /&gt;
             for (i = 1; i &amp;lt;= nRows &amp;amp;&amp;amp; nTacticsEntry &amp;lt;= nMaxTactics; ++i)&lt;br /&gt;
                {&lt;br /&gt;
                        int bAddEntry = FALSE;&lt;br /&gt;
                        int nTargetType = GetM2DAInt(nTableID, &amp;quot;TargetType&amp;quot;, i);&lt;br /&gt;
                        int nCondition = GetM2DAInt(nTableID, &amp;quot;Condition&amp;quot;, i);&lt;br /&gt;
                        int nCommandType = GetM2DAInt(nTableID, &amp;quot;Command&amp;quot;, i);&lt;br /&gt;
                        int nCommandParam = GetM2DAInt(nTableID, &amp;quot;SubCommand&amp;quot;, i);&lt;br /&gt;
&lt;br /&gt;
                        int nUseType = GetM2DAInt(TABLE_COMMAND_TYPES, &amp;quot;UseType&amp;quot;, nCommandType);&lt;br /&gt;
                        if (nUseType == 0)&lt;br /&gt;
                        {&lt;br /&gt;
                            bAddEntry = TRUE;&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            bAddEntry = HasAbility(oFollower, nCommandParam);&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        if (bAddEntry)&lt;br /&gt;
                        {&lt;br /&gt;
                            SetTacticEntry(oFollower, nTacticsEntry, TRUE, nTargetType, nCondition, nCommandType, nCommandParam);&lt;br /&gt;
                            ++nTacticsEntry;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
}  &lt;br /&gt;
&lt;br /&gt;
/* InitCustomFollowerSpec:&lt;br /&gt;
&lt;br /&gt;
This function tries to set the forced Specialisation.  If there is none, it checks the package for one.  &lt;br /&gt;
&lt;br /&gt;
If there isn't either of those, it grants a free spec point if bFreeSpecPoint is true.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void InitCustomFollowerSpec(object oFollower, int nPackage, int nForceSpec, int bFreeSpecPoint) {&lt;br /&gt;
    // Find specialization, and optionally add a spec point if none is found.&lt;br /&gt;
&lt;br /&gt;
        if (nForceSpec == 0) {&lt;br /&gt;
    &lt;br /&gt;
        int nSpecAbility = GetM2DAInt(TABLE_PACKAGES, &amp;quot;switch1_class&amp;quot;, nPackage); // followers can have only 1 advanced class&lt;br /&gt;
         if(nSpecAbility &amp;gt; 0)&lt;br /&gt;
         {&lt;br /&gt;
          AddAbility(oFollower, nSpecAbility);&lt;br /&gt;
         } else {&lt;br /&gt;
             if (bFreeSpecPoint) {&lt;br /&gt;
                 SetCreatureProperty(oFollower, 38, 1.00);&lt;br /&gt;
             }&lt;br /&gt;
         }                    &lt;br /&gt;
        &lt;br /&gt;
        } else {&lt;br /&gt;
         &lt;br /&gt;
             AddAbility(oFollower, nForceSpec);&lt;br /&gt;
            &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* hireCustomFollower()  (See doco at top of page)&lt;br /&gt;
&lt;br /&gt;
I strongly suggest you reorder the parameters if you're adding many followers with advanced options.&lt;br /&gt;
&lt;br /&gt;
Feel free to leave them alone if you only want to set class, plot, spec or don't mind long declarations.&lt;br /&gt;
&lt;br /&gt;
Note nForceClass is currently compulsory due to flakiness with GetCreatureCoreClass()&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void hireCustomFollower(object oFollower, int nForceClass, string sPlot = &amp;quot;&amp;quot;, int nPlotFlag = 0, int nForceSpec = 0, &lt;br /&gt;
int nALTable = 0, int bInvokePicker = FALSE, int nInitialState = FOLLOWER_STATE_AVAILABLE, string sCurrPlot = &amp;quot;&amp;quot;, &lt;br /&gt;
int nCurrPlotFlag = 0, int nAutolevel = 0, int bFreeSpecPoint = TRUE, int nTargetLevel = 0, int nMinLevel = 0) &lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
        object oHero = GetHero();&lt;br /&gt;
&lt;br /&gt;
        /* #################  BEGIN BASIC FOLLOWER JOIN BLOCK   ###################&lt;br /&gt;
&lt;br /&gt;
        This loosely replicates WR_SetFollowerState.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        */    &lt;br /&gt;
        &lt;br /&gt;
        if (nForceClass == 0) {&lt;br /&gt;
            nForceClass = GetCreatureCoreClass(oFollower);           //This is not working.  Hence nForceClass mandatory.&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
        SetGroupId(oFollower, GetGroupId(oHero));      //Puts the follower in the pc's Group.&lt;br /&gt;
        SetEventScript(oFollower, RESOURCE_SCRIPT_PLAYER_CORE);  //This makes them act like a player.&lt;br /&gt;
        SetFollowerState(oFollower, nInitialState);  //This sets whether they are available, in the active party etc.&lt;br /&gt;
&lt;br /&gt;
        /* #################  END BASIC FOLLOWER JOIN BLOCK ##################### */&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        /* #################  BEGIN PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION #################&lt;br /&gt;
         This replicates the EVENT_TYPE_PARTY_MEMBER_HIRED handler from player_core, stripped down for simplicity and allowing our custom options.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        */&lt;br /&gt;
&lt;br /&gt;
        Chargen_EnableTacticsPresets(oFollower);    //I assume this is important.&lt;br /&gt;
        &lt;br /&gt;
        SetLocalInt(oFollower, FOLLOWER_SCALED, 1);  //This should prevent the follower being rescaled by player_core or what have you&lt;br /&gt;
        &lt;br /&gt;
        int nPackage = GetPackage(oFollower);  //Gets the package, which will be used to find a number of 2DA IDs.&lt;br /&gt;
        int nPackageClass = GetM2DAInt(TABLE_PACKAGES, &amp;quot;StartingClass&amp;quot;, nPackage);  //I don't think this is used, even by player_core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        // set behavior according to package&lt;br /&gt;
        int nBehavior = GetM2DAInt(TABLE_PACKAGES, &amp;quot;FollowerBehavior&amp;quot;, nPackage);&lt;br /&gt;
&lt;br /&gt;
        if(nBehavior &amp;gt;= 0) {&lt;br /&gt;
            SetAIBehavior(oFollower, nBehavior);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        Chargen_InitializeCharacter(oFollower);      //We initialise the follower and choose race/class.&lt;br /&gt;
        &lt;br /&gt;
        Chargen_SelectRace(oFollower,GetCreatureRacialType(oFollower));&lt;br /&gt;
        Chargen_SelectCoreClass(oFollower,nForceClass);        &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         if (nTargetLevel == 0) {   //This block picks a target level if not specified&lt;br /&gt;
            &lt;br /&gt;
              nTargetLevel = GetCustomFollowerTargetLevel(oFollower, oHero, nPackage, nMinLevel);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         int nXp = RW_GetXPNeededForLevel(Max(nTargetLevel, 1));      //Here is where the XP is calculated and rewarded&lt;br /&gt;
         RewardXP(oFollower, nXp, FALSE, FALSE);&lt;br /&gt;
&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         // add hidden approval talents - (JN: I don't know how to set these yet, but when I figure it out this should make it work)&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         int nIndex = Approval_GetFollowerIndex(oFollower);&lt;br /&gt;
         Approval_AddFollowerBonusAbility(nIndex, 0);&lt;br /&gt;
        &lt;br /&gt;
          //Handle Specialisation&lt;br /&gt;
          InitCustomFollowerSpec(oFollower, nPackage, nForceSpec, bFreeSpecPoint);&lt;br /&gt;
&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
         // This spends all available attribute and stat points on the&lt;br /&gt;
         // creature according to the levelup table.  (JN:  this replicates AL_DoAutoLevelUp but with our choice of table)&lt;br /&gt;
         // -------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
         if (nALTable == 0) {&lt;br /&gt;
            nALTable = GetCustomFollowerALTable(oFollower);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         AL_SpendAttributePoints(oFollower, nALTable, FALSE);&lt;br /&gt;
         AL_SpendSkillPoints(oFollower, nALTable, TRUE);&lt;br /&gt;
         AL_SpendSpecializationPoints(oFollower, nALTable);&lt;br /&gt;
         AL_SpendTalentSpellPoints(oFollower, nALTable, TRUE);&lt;br /&gt;
&lt;br /&gt;
        // -------------------------------------------------------------------------&lt;br /&gt;
        // Update various UIs&lt;br /&gt;
        // -------------------------------------------------------------------------&lt;br /&gt;
        Chargen_SetNumTactics(oFollower);&lt;br /&gt;
        SetCanLevelUp(oFollower,Chargen_HasPointsToSpend(oFollower));&lt;br /&gt;
&lt;br /&gt;
        // load tactics&lt;br /&gt;
         InitCustomFollowerTactics(oFollower, nPackage);&lt;br /&gt;
&lt;br /&gt;
         /* #################  END PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION ################# */     &lt;br /&gt;
             &lt;br /&gt;
         &lt;br /&gt;
         SetAutoLevelUp(oFollower, nAutolevel);         //This is the autolevel flag on the character sheet.&lt;br /&gt;
         &lt;br /&gt;
         //Set plot flags&lt;br /&gt;
         &lt;br /&gt;
         if (!((sPlot == &amp;quot;&amp;quot;) || (nPlotFlag == 0))) {           //Joined Party&lt;br /&gt;
            WR_SetPlotFlag(sPlot, nPlotFlag, TRUE);   &lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         if ((nInitialState == FOLLOWER_STATE_ACTIVE) || (nInitialState == FOLLOWER_STATE_LOCKEDACTIVE)) {&lt;br /&gt;
            if (!((sCurrPlot == &amp;quot;&amp;quot;) || (nCurrPlotFlag == 0))) {&lt;br /&gt;
                WR_SetPlotFlag(sCurrPlot, nCurrPlotFlag, TRUE);   //Currently in Party&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
                     &lt;br /&gt;
        // Invoke picker if requested.&lt;br /&gt;
&lt;br /&gt;
        if (bInvokePicker) {&lt;br /&gt;
             SetPartyPickerGUIStatus(2);&lt;br /&gt;
             ShowPartyPickerGUI();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yeah, I know.  It can't really be any smaller.  Feel free to modify it if you're confident with scripting.&lt;br /&gt;
==== Add Your Custom Autolevel Template to GetCustomFollowerALTable() ====&lt;br /&gt;
While you can pass the ID you made for your autolevel template to that monster function as an argument, it's better to have them all in one place if you have multiple followers.&lt;br /&gt;
&lt;br /&gt;
GetCustomFollowerALTable() is the first function in our include, and you can add an explicit if test for your follower there to assign the correct table id (the one from your M2DA_base_ m2DA).  There is a function very much like it in sys_autolevel_h.nss for the core followers, so we'll copy Bioware's practice.&lt;br /&gt;
&lt;br /&gt;
Let's take a look at the function by itself:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int GetCustomFollowerALTable(object oFollower) {&lt;br /&gt;
    int nTable = _GetTableToUseForAL(oFollower);&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_miera&amp;quot;) {               &lt;br /&gt;
        nTable = 50143;   &lt;br /&gt;
    }   &lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_jysavin&amp;quot;) {&lt;br /&gt;
        nTable = 50144;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_geldual&amp;quot;) {&lt;br /&gt;
        nTable = 50145;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    if (GetTag(oFollower) == &amp;quot;bc_party_braghon&amp;quot;) {&lt;br /&gt;
        nTable = 50146;   &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return nTable;    &lt;br /&gt;
    &lt;br /&gt;
}  &lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So we have a test for each follower tag from my module, matching up to an ID which is assigned to nTable.  All you need to do is change a tag from my follower to yours, and my ID to the correct one from your M2DA_base_* m2DA.  Then you should delete the rest of the example if statements :)&lt;br /&gt;
&lt;br /&gt;
Save and export the script.  Ignore the compiler error about lack of main();&lt;br /&gt;
&lt;br /&gt;
=== Include Function In Your Hire Script and Call It ===&lt;br /&gt;
&lt;br /&gt;
So instead of a hire script that calls UT_HireFollower(), we want one that includes our shiny new function and calls it.&lt;br /&gt;
&lt;br /&gt;
Take a look at the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;plt_bc_create_party&amp;quot;   //Make sure you include your party handling plot&lt;br /&gt;
#include &amp;quot;hireCustomFollower_h&amp;quot;  // And include the function script - which will in turn include a bunch of stuff&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
                    //Initialising my objects, not super-relevant to the example &lt;br /&gt;
                     &lt;br /&gt;
                    object oHero = GetHero();&lt;br /&gt;
                    object oMiera = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_miera.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oJysavin = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_jysavin.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oBraghon = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_braghon.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
                    object oSpider = CreateObject(OBJECT_TYPE_CREATURE, R&amp;quot;bc_party_geldual.utc&amp;quot;, GetLocation(oHero));&lt;br /&gt;
&lt;br /&gt;
                    //Simplest hire call - adds to the party as a wizard.  Class is currently compulsory due to a bug.&lt;br /&gt;
                    hireCustomFollower(oMiera, CLASS_WIZARD);&lt;br /&gt;
&lt;br /&gt;
                    //Add to the party and set joining plot flags&lt;br /&gt;
                    hireCustomFollower(oJysavin, CLASS_WARRIOR, PLT_BC_CREATE_PARTY, PARTY_JYSAVIN_JOINED);&lt;br /&gt;
&lt;br /&gt;
                    //Add to the party, set plot flags, force a specialisation&lt;br /&gt;
                    hireCustomFollower(oBraghon, CLASS_ROGUE, PLT_BC_CREATE_PARTY, PARTY_BRAGHON_JOINED, ABILITY_TALENT_HIDDEN_ASSASSIN);&lt;br /&gt;
&lt;br /&gt;
                    //More complex example - Follower added as a unique class (Dog), not granted a specialisation or spec point.  &lt;br /&gt;
                    //Note unique classes must have an ALTable passed here or specified in GetCustomFollowerALTable() or they won't work&lt;br /&gt;
                    hireCustomFollower(oSpider, CLASS_DOG, PLT_BC_CREATE_PARTY, PARTY_GELDUAL_JOINED, 0, 0, FALSE, FOLLOWER_STATE_AVAILABLE, &amp;quot;&amp;quot;, 0, 0, FALSE);&lt;br /&gt;
                   &lt;br /&gt;
                    //Show the party picker to let the player choose from their new companions!&lt;br /&gt;
                    SetPartyPickerGUIStatus(2);&lt;br /&gt;
                    ShowPartyPickerGUI();                                                                                                                    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example shows several of the more simple ways of invoking the function.  Check the comments at the start of the function for a full list of arguments.&lt;br /&gt;
&lt;br /&gt;
I would suggest best practice for most followers would be to call as follows:&lt;br /&gt;
&lt;br /&gt;
'''hireCustomFollower(oFollower, CLASS, PLOT, PLOT_FLAG, SPECIALISATION)'''&lt;br /&gt;
&lt;br /&gt;
This will safely set the follower up as the desired class and specialisation (doubly important if there are spec abilities in their ALTable) while setting your plot flag for them being in the party.  hireCustomFollower(oFollower, CLASS, PLOT, PLOT_FLAG, SPECIALISATION, 0, TRUE) will do the same while invoking the Party Picker automatically.&lt;br /&gt;
&lt;br /&gt;
Note that the specialisations are abilities and not classes - you'll find them as ABILITY_HIDDEN_ constants.&lt;br /&gt;
&lt;br /&gt;
If it's all worked, you should find you can now add followers with a lot more flexibility!&lt;br /&gt;
&lt;br /&gt;
[[File:picker_advanced.jpg|thumb|500px|center]]&lt;br /&gt;
&lt;br /&gt;
== Common Follower Problems &amp;amp; FAQ ==&lt;br /&gt;
&lt;br /&gt;
====Why don't my followers gain XP?====&lt;br /&gt;
There is a bug in UT_HireFollower. Make a copy of UT_HireFollower in a function of your own, then make the following change:&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, TRUE);&lt;br /&gt;
to&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, bPreventLevelup);&lt;br /&gt;
&lt;br /&gt;
====When I choose followers from the Party Picker, they spawn into the area but do not join.====&lt;br /&gt;
&lt;br /&gt;
You need to intercept the EVENT_TYPE_PARTYMEMBER_ADDED event and set the follower to FOLLOWER_STATE_ACTIVE.  See Simple Follower Creation earlier in this document.&lt;br /&gt;
&lt;br /&gt;
====My followers don't have skill trees!====&lt;br /&gt;
&lt;br /&gt;
If a follower hasn't been through an initial chargen/autolevel event (via player_core/sys_autolevel_h) then the skill tree doesn't show.  You're probably trying to be clever and get around UT_HireFollower without going all the way (see monster function above ^_^).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====My followers don't have a class====&lt;br /&gt;
&lt;br /&gt;
GetCreatureCoreClass() seems flaky under some conditions.  It's best to explicitly set the class yourself; this is why class is currently a mandatory argument to hireCustomFollower()&lt;br /&gt;
&lt;br /&gt;
====Dog talents and equipment slots don't work====&lt;br /&gt;
Symptoms: dog talents appear on the talents screen but remain greyed out on level up. Warrior talents appear in the quickslots. Equipment slots are for humans, not dogs.&lt;br /&gt;
&lt;br /&gt;
Line 78 of packages_base in packages.xls (Dog) should have the LevelUpTable column set to 257 which is the ALDog table.&lt;br /&gt;
&lt;br /&gt;
The EquipmentLayout 2DA needs a new entry for the follower:&lt;br /&gt;
&lt;br /&gt;
 ID=same as partypicker 2DA	&lt;br /&gt;
 Tag=follower tag	&lt;br /&gt;
 AvailableEquipmentSlots=794624&lt;br /&gt;
 Layout=2	&lt;br /&gt;
 EnableWeaponSets=0&lt;br /&gt;
&lt;br /&gt;
If the creature is not using the appearance &amp;quot;Dog, Party Member&amp;quot;, it needs a new appearance line in APR_base. Most of the entries can be copied from the standard appearance (e.g. Wolf), but &lt;br /&gt;
&lt;br /&gt;
 MaxScaleLevel=-1&lt;br /&gt;
 DefaultArmor=&lt;br /&gt;
 AppearanceRestrictionGroup=1&lt;br /&gt;
&lt;br /&gt;
Otherwise, it won't be able to progress beyond a specified level. The player will receive an unwanted set of armour when the it is hired, and it won't be able to use Marabi crunch items. You may also need to tweak PERSPACE and/or BumpLevel if excessive clipping occurs.&lt;br /&gt;
&lt;br /&gt;
====Isn't there an easier way to do this?====&lt;br /&gt;
&lt;br /&gt;
Possibly.  There is a way of recruiting a follower by setting a plot flag.  However I don't understand it, and I expect it still doesn't allow custom autolevel templates, full control over specialisations etc.  There's still a fair bit of stuff hardcoded for the core followers, I'm not sure putting a custom follower through the same process as Al, Leli et al will have good results.&lt;br /&gt;
&lt;br /&gt;
The next section answers this question, up to a point.&lt;br /&gt;
&lt;br /&gt;
==== What if there are more than three potential followers? ====&lt;br /&gt;
This example handles larger numbers of followers, and doesn't force the player to use the party picker unless the party is already full.&lt;br /&gt;
&lt;br /&gt;
The prefix zzz, used throughout, can be replaced with whatever [[Prefixes_in_use | prefix]] you are using for your resources.&lt;br /&gt;
&lt;br /&gt;
If you're making a new campaign, to keep life simple, allocate a unique number to each follower. You could either use a creature variable or a script, e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Party member id (e.g. 1=Alicia, 2=Godwin...)&lt;br /&gt;
int zzzPartyMemberID(object oPartyMember)&lt;br /&gt;
{&lt;br /&gt;
  string sPartyMember = GetTag(oPartyMember);&lt;br /&gt;
&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_alicia&amp;quot;) return 1;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_godwin&amp;quot;) return 2;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_harold&amp;quot;) return 3;&lt;br /&gt;
  if (sPartyMember == &amp;quot;zzzcr_lara&amp;quot;  ) return 4;&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make two separate plots, e.g. zzzpt_hired for when a follower is first recruited, and zzzpt_party to flag whether they're currently in the party. Use flag values that correspond to the unique follower id, e.g. ZZZPT_HIRED_GODWIN will be 2.&lt;br /&gt;
&lt;br /&gt;
If you're modifying the official campaign, you won't be able to make this simplification - you'll need a set of plot flags for your new party members, similar to the official ones. The logic of what follows is still correct, it just means that instead of having one set of common code that works for everyone, you have to explicitly script each party member individually using their personal plot flags.&lt;br /&gt;
&lt;br /&gt;
Follower conversation is now very simple. In Godwin's dialogue, the hiring line will be conditional - when ZZZPT_HIRED_GODWIN is clear - and it will set ZZZPT_HIRED_GODWIN.  No conversation script is necessary. Instead, in the properties of the plot zzzpt_hired, we add a plot event script, as follows.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// PARTY HIRE PLOT SCRIPT&lt;br /&gt;
//&lt;br /&gt;
// This is called in conversation when a party member is hired for the first time.&lt;br /&gt;
// If the party is full, the party picker is displayed, which forces the PARTYMEMBER_ADDED&lt;br /&gt;
// module event.&lt;br /&gt;
//&lt;br /&gt;
// The flag value is never referenced, because the code is common for all party members.&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;events_h&amp;quot;&lt;br /&gt;
#include &amp;quot;global_objects_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;sys_rewards_h&amp;quot;&lt;br /&gt;
#include &amp;quot;log_h&amp;quot;&lt;br /&gt;
#include &amp;quot;utility_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plot_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;zzz_h&amp;quot;                  // A header containing the zzzPartyMemberID function&lt;br /&gt;
#include &amp;quot;plt_zzzpt_hired&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_zzzpt_party&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    event  eParms             = GetCurrentEvent();&lt;br /&gt;
    int    nType              = GetEventType(eParms);       // GET or SET&lt;br /&gt;
    string strPlot            = GetEventString(eParms, 0);  // Plot GUID&lt;br /&gt;
    int    nFlag              = GetEventInteger(eParms, 1); // Plot flag&lt;br /&gt;
    object oParty             = GetEventCreator(eParms);    // Plot table owner&lt;br /&gt;
    object oFollower          = GetEventObject(eParms, 0);  // Conversation owner (if any)&lt;br /&gt;
    int    nPlotType          = GetEventInteger(eParms, 5); // Plot type&lt;br /&gt;
&lt;br /&gt;
    int    bIsTutorial        = GetM2DAInt(TABLE_PLOT_TYPES, &amp;quot;IsTutorial&amp;quot;, nPlotType);&lt;br /&gt;
    int    bIsCodex           = GetM2DAInt(TABLE_PLOT_TYPES, &amp;quot;IsCodex&amp;quot;, nPlotType);&lt;br /&gt;
&lt;br /&gt;
    int    nResult            = FALSE;                      // return value for DEFINED GET&lt;br /&gt;
    object oPC                = GetPartyLeader();&lt;br /&gt;
&lt;br /&gt;
    plot_GlobalPlotHandler(eParms); // any global plot operations, including debug info&lt;br /&gt;
&lt;br /&gt;
    if (nType == EVENT_TYPE_SET_PLOT) // actions -&amp;gt; normal flags only&lt;br /&gt;
    {&lt;br /&gt;
        int nValue    = GetEventInteger(eParms, 2); // 0=Clear 1=Set&lt;br /&gt;
        int nOldValue = GetEventInteger(eParms, 3); // Current flag value&lt;br /&gt;
&lt;br /&gt;
        if (nValue)&lt;br /&gt;
          {&lt;br /&gt;
            if (GetArraySize(GetPartyList(oPC)) &amp;lt; 4)&lt;br /&gt;
              {&lt;br /&gt;
                // Code from UT_HireFollower with level up bug fixed&lt;br /&gt;
                SetAutoLevelUp(oFollower, 2);&lt;br /&gt;
                SetGroupId(oFollower, GetGroupId(GetHero()));&lt;br /&gt;
                WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, FALSE);  &lt;br /&gt;
                // End of code from UT_HireFollower&lt;br /&gt;
                AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
                WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), TRUE);&lt;br /&gt;
              }&lt;br /&gt;
            else&lt;br /&gt;
              {&lt;br /&gt;
                WR_SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE, FALSE);&lt;br /&gt;
                SetEventScript(oFollower, RESOURCE_SCRIPT_PLAYER_CORE);&lt;br /&gt;
                SendPartyMemberHiredEvent(oFollower, TRUE);&lt;br /&gt;
//                SetPartyPickerGUIStatus(PP_GUI_STATUS_USE);&lt;br /&gt;
//                ShowPartyPickerGUI();&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
     }&lt;br /&gt;
     else // EVENT_TYPE_GET_PLOT -&amp;gt; defined conditions only&lt;br /&gt;
     {&lt;br /&gt;
        switch(nFlag)&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    plot_OutputDefinedFlag(eParms, nResult);&lt;br /&gt;
    return nResult;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We still need to handle the party picker events in our module event script:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         // PARTY MEMBER ADDED - Allow XP gain. Come here, follow me, flag as party member.&lt;br /&gt;
         case EVENT_TYPE_PARTYMEMBER_ADDED:&lt;br /&gt;
         {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
            AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
            WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&lt;br /&gt;
            WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), TRUE);&lt;br /&gt;
            break;&lt;br /&gt;
         }&lt;br /&gt;
         // PARTY MEMBER DROPPED - flag as not party member.&lt;br /&gt;
         case EVENT_TYPE_PARTYMEMBER_DROPPED:&lt;br /&gt;
        {&lt;br /&gt;
            object oFollower = GetEventObject(ev, 0);&lt;br /&gt;
            WR_SetPlotFlag(PLT_ZZZPT_PARTY, zzzPartyMemberID(oFollower), FALSE);&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
When we need to refer to a particular follower explicitly, we can still do so - for example, the flag ZZZPT_PARTY_GODWIN will tell use whether Godwin is currently in the party or not.&lt;br /&gt;
&lt;br /&gt;
==== How do I turn off sustained abilities when a follower is dismissed? ====&lt;br /&gt;
'''Please note:''' The 1.04 DA:O patch is bugged and removed/broke several features of the toolkit, if you are using it please follow [http://social.bioware.com/forum/1/topic/71/index/3172230/1#3172537 these steps] to re-enable them as one is required for the script below to compile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is a potential exploit in what we've done so far. If a follower casts a sustained spell like Flaming Weapons, it affects all party members. When the follower is dismissed, the remaining party members continue to benefit from the spell.&lt;br /&gt;
&lt;br /&gt;
We can prevent this by deactivating modal abilities before opening the party picker. Add these snippets to the module event script:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;ability_h&amp;quot;&lt;br /&gt;
void zDeactivateModalAbilities();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         case EVENT_TYPE_PARTYPICKER_INIT:&lt;br /&gt;
           {&lt;br /&gt;
             // Deactivate party modal abilities. This ensures that the party no longer benefits&lt;br /&gt;
             // from spells like Flaming Weapons if the caster is dismissed from the party.&lt;br /&gt;
             zDeactivateModalAbilities();&lt;br /&gt;
             break;&lt;br /&gt;
           }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The function looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Deactivate party's modal abilities&lt;br /&gt;
&lt;br /&gt;
void zDeactivateModalAbilities()&lt;br /&gt;
{&lt;br /&gt;
  object    oPC            = GetHero();&lt;br /&gt;
  object [] oFollowerTable = GetPartyList(oPC);&lt;br /&gt;
  object    oFollower;&lt;br /&gt;
  int       nPartySize     = GetArraySize(oFollowerTable);&lt;br /&gt;
  int []    nAbilityTable;&lt;br /&gt;
  int       nAbilityCount;&lt;br /&gt;
  int       nAbility;&lt;br /&gt;
  int       i              = -1;&lt;br /&gt;
  int       j;&lt;br /&gt;
&lt;br /&gt;
  while (++i &amp;lt; nPartySize)&lt;br /&gt;
    {&lt;br /&gt;
      oFollower      = oFollowerTable[i];&lt;br /&gt;
      nAbilityTable  = GetAbilityList(oFollower);&lt;br /&gt;
      nAbilityCount  = GetArraySize(nAbilityTable);&lt;br /&gt;
      j              = -1;&lt;br /&gt;
&lt;br /&gt;
      while (++j &amp;lt; nAbilityCount)&lt;br /&gt;
        {&lt;br /&gt;
          nAbility = nAbilityTable[j];&lt;br /&gt;
&lt;br /&gt;
          if (Ability_IsAbilityActive(oFollower, nAbility))&lt;br /&gt;
            if (Ability_IsModalAbility(nAbility))&lt;br /&gt;
              Ability_DeactivateModalAbility(oFollower, nAbility);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If other ways of dismissing party members are permitted, the same function can be used.&lt;br /&gt;
&lt;br /&gt;
== Advanced Follower Creation: An Alternative Approach ==&lt;br /&gt;
&lt;br /&gt;
While these things are to a large extent a matter of taste, I see no reason to reinvent the wheel when there is a perfectly good wheel at hand. The following describes how to adapt the existing machinery for the recruitment and tracking of your own party members.&lt;br /&gt;
&lt;br /&gt;
First create the setup as described above in Simple Follower Creation, except for the scripts and plot tables. In addition, create the GDA extensions for a level-up table and the M2DA which points to those tables, as described in Advanced Follower Creation above.&lt;br /&gt;
&lt;br /&gt;
Now ...&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Create a party plot table ===&lt;br /&gt;
&lt;br /&gt;
Have a look at the gen00pt_party plot table and create a similar table for your own followers. Don't bother with the Defined Flags for the moment, just the Main Flags will do, ie recruited, in-camp and in-party for each follower. (Critical Note: Do not duplicate the plot table, create one from scratch. This is the case for ALL plot tables because of a show-stopping bug which means a new GUID is not assigned on Duplicate of a plot.)&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Create a party script ===&lt;br /&gt;
&lt;br /&gt;
Duplicate the gen00pt_party script and rename for your module (conventionally plot tables and their plot scripts have the same name). Delete (or comment out) the Defined Flags section at the end and any lines dealing with logging and tutorials. Change names to those of your party members. If you are using gifting, approval or forced inclusion you may wish to retain those sections of code, but additional machinery will be needed for these facilities to work. For approval you can specify a starting level of approval here for each follower if you want it to be other than zero (as per the existing section dealing with Dog). Note that the custom hire function at the head of the script allows you to specify whether or not to invoke the party picker on recruitment. You may not want to do so for the first couple of followers (but see below). You should already have defined all required constants in a separate file for your module, eg &amp;lt;module prefix&amp;gt;_constants_h. If not, do so now and include it, as well as your plot table, at the head of the script. Delete includes that only refer to the main campaign. (If this is all Greek to you, spend a couple of hours examining the set-up of the Demo, which is packaged with the toolset, and go through the introductory tutorials referenced on the main page of this wiki).&lt;br /&gt;
&lt;br /&gt;
Looking at the new party script, notice that the follower-in-camp function is not defined. This is because for some arcane reason it is defined in party_h, and unhappily references the main campaign's plot table. So we will have to create a new function to replace it, change the other function's flag reference (for the sake of neatness), and change the call in the main body of the script. (You may decide later for other reasons to replicate and customise party_h, but that won't interfere with re-creating this function here.)&lt;br /&gt;
&lt;br /&gt;
Our two functions at the head of the script should be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;void SetFollowerInParty(object oFollower, string sPlot, int nCampFlag)&lt;br /&gt;
{&lt;br /&gt;
    WR_SetPlotFlag(sPlot, nCampFlag, FALSE);&lt;br /&gt;
    WR_SetObjectActive(oFollower, TRUE);&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE);&lt;br /&gt;
    command cJump = CommandJumpToObject(GetPartyLeader());&lt;br /&gt;
    WR_AddCommand(oFollower, cJump);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SetFollowerInCamp(object oFollower, string sPlot, int nPartyFlag)&lt;br /&gt;
{&lt;br /&gt;
    WR_SetPlotFlag(sPlot, nPartyFlag, FALSE);&lt;br /&gt;
    WR_SetObjectActive(oFollower, FALSE);&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE, FALSE);&lt;br /&gt;
}&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the line in the in-camp sections for each follower should now be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;SetFollowerInCamp(o&amp;lt;follower&amp;gt;, strPlot, &amp;lt;follower&amp;gt;_IN_PARTY);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Step 3: Create package GDAs and reference them in you 2DA_base extension ===&lt;br /&gt;
&lt;br /&gt;
Look at the packages_base GDA and create an extension GDA with one line for each follower based on a main campaign follower that is most like your own follower, eg a sword-shield warrior can be a copy of Alistair, a battle mage a copy of Morrigan, etc. You can look at the Excel version of this GDA to more easily see what the fields mean. It is here that you can specify what if any specialisation will be assigned on hire and the level at which this spec point becomes available. (The IDs for each spec are in the 4000-range of ABI_base.)&lt;br /&gt;
&lt;br /&gt;
Most importantly, it is here also that you define the ID of both your level-up table and the AIP table you are about to create.&lt;br /&gt;
&lt;br /&gt;
Now create aip_follower_&amp;lt;follower name&amp;gt; gda tables, again based on a existing tables most like your own followers. No changes should be required to the copies you create.&lt;br /&gt;
&lt;br /&gt;
In the m2da_base_&amp;lt;your module&amp;gt; extension you have already created, add lines for your AIP tables with a package ID referencing the IDs you assigned in your packages extension table.&lt;br /&gt;
&lt;br /&gt;
Carefully check that all IDs in your GDAs are correct and cross-reference properly, and save the GDAs to your override directory.&lt;br /&gt;
&lt;br /&gt;
Desirable but not obligatory (except for non-humanoid characters), is an extension to the Portraits gda. Finally the Equipment Layout gda will need an extension for non-humanoids, who use a different equipment mask.&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Module script addition ===&lt;br /&gt;
&lt;br /&gt;
Modify your own module script to point to the new plot table and your own followers. To see an example of the required code for the two new sections look at the relevant section of module_core, which are for EVENT_TYPE_PARTYMEMBER_ADDED and EVENT_TYPE_PARTYMEMBER_DROPPED.&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
The recruit flag is set in a conversation (usually, but it could be a script) and that event is then processed by the plot script, which among other things sets both the in-camp and in-party flags, and fires up the party picker by default. If the player then selects the follower in the picker, the in-camp flag is unset (or vice versa if the follower is not selected to join). Subsequently, if the character is selected (or unselected) in the picker, the event is picked up by the module script, which sets the relevant plot flag as true, and that plot event is then sent to the plot scipt which sets the other flag as false. &lt;br /&gt;
&lt;br /&gt;
(Note that if the party picker is turned off for a particular follower's recruit event, that follower will be placed in the active party regardless of the number of members, so ONLY do this for a follower who cannot be recruited when there are already 3 possible followers.)&lt;br /&gt;
&lt;br /&gt;
On recruitment, player_core rebuilds the character according to the specifications laid out in the GDAs, so no further scripting is required.&lt;br /&gt;
&lt;br /&gt;
=== Uses ===&lt;br /&gt;
&lt;br /&gt;
To recruit a party member, set the recruit flag from your plot table in the relevant dialogue. Adding or subtracting followers from the active party is automatically tracked via this machinery, and the plot flags can be interrogated in all your scripts and conversations if you need to know who is currently in the party and who is in camp.&lt;br /&gt;
&lt;br /&gt;
Defined flags can be added as you need them to the script and plot table but there is no point having flags that you will not use, so as with all Defined Flags this is an as-you-go decision, but quite easy to do.&lt;br /&gt;
&lt;br /&gt;
Hiring and firing of temporary party members at the start of a campaign (such as Ser Jory, or Jowan, or Soris, etc) can be handled by UT_HireFollower, and the party picker is not invoked (nor is the Party Camp an available destination).&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
If you haven't done so already, create a simple debugging area for your module where you can dump the player, all followers and a couple of conversation dummies, and set up a dialogue in which you can invoke all required flags and conditions and see if they actually work as expected. (This setup can be used to test many other components as well.) Global machinery such as this can be painful to set up and get right (unless you are of an exceptionally methodical cast of mind), but it is worthwhile to ensure they are absolutely bullet-proof before you develop the specifics of your module.&lt;br /&gt;
&lt;br /&gt;
=== The KISS principle ===&lt;br /&gt;
&lt;br /&gt;
This is an &amp;quot;out-of-the-box&amp;quot; solution, and once set up is quite robust. If you want variants not catered for here, do NOT try to modify what you already have working.&lt;br /&gt;
&lt;br /&gt;
'''Use-case:''' You want a follower (example tag: dairren) to be recruited without a set specialisation and one level higher than the PC.&lt;br /&gt;
&lt;br /&gt;
Go to your packages gda and set the spec field to 0. In the character's plot table (you should have at least one for each follower) create a flag which we will call BLAH_BLAH. In the table's plot scipt insert the following very simple event handler:&lt;br /&gt;
&lt;br /&gt;
	&amp;lt;dascript&amp;gt;case BLAH_BLAH:&lt;br /&gt;
         {&lt;br /&gt;
           SetCreatureProperty(oDairren, 38, 1.00); //awards the spec point; field from the properties gda&lt;br /&gt;
           int aLevel = GetLevel(oHero); //some simple arithmetic to find out the XP we need to award&lt;br /&gt;
           int bLevel = (aLevel+1);&lt;br /&gt;
           int aPoints = RW_GetXPNeededForLevel(aLevel);&lt;br /&gt;
           int bPoints = RW_GetXPNeededForLevel(bLevel);&lt;br /&gt;
           int targetPoints = (bPoints - aPoints);&lt;br /&gt;
           RewardXP(oDairren, targetPoints, FALSE, TRUE); //award the XP, and we're done&lt;br /&gt;
           break;&lt;br /&gt;
	 }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
The flag can be set in the same conversation as the recruit flag, so long as it comes afterwards. This way you not only maintain the integrity of your core machinery, but keep exceptions/variations for particular characters where they belong -- with that character's plot tables and scripts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Obadiah</name></author>	</entry>

	<entry>
		<id>http://datoolset.net/mw/index.php?title=Tutorials&amp;diff=16115</id>
		<title>Tutorials</title>
		<link rel="alternate" type="text/html" href="http://datoolset.net/mw/index.php?title=Tutorials&amp;diff=16115"/>
				<updated>2011-05-07T16:56:02Z</updated>
		
		<summary type="html">&lt;p&gt;Obadiah: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page lists links to step-by-step tutorials, both on this wiki and on external sites.&lt;br /&gt;
&lt;br /&gt;
==Introductory tutorials ==&lt;br /&gt;
&lt;br /&gt;
In the course of these tutorials we'll go through all the steps needed to create a basic adventure.&lt;br /&gt;
&lt;br /&gt;
{|align=right&lt;br /&gt;
|{{TutorialRef|&amp;lt;nowiki&amp;gt;Boxes like these contain links,&amp;lt;/nowiki&amp;gt;|&amp;lt;nowiki&amp;gt;to topics taking you to further information&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|{{sidebox|&lt;br /&gt;
*Boxes like this contain a checklist of important steps.&lt;br /&gt;
*They're intended as a reminder and as a navigational aid.&lt;br /&gt;
}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
*[[Introductory tutorial]] - An overview of the toolset as a whole&lt;br /&gt;
*[[Module tutorial]] - how to create a module to work in.&lt;br /&gt;
&lt;br /&gt;
This set of tutorials forms a series, each building on or filling in omissions by the last:&lt;br /&gt;
*[[Area tutorial]]&lt;br /&gt;
*[[Placeable tutorial]]&lt;br /&gt;
*[[Item tutorial]]&lt;br /&gt;
*[[Creature tutorial]]&lt;br /&gt;
*[[Conversation tutorial]]&lt;br /&gt;
&lt;br /&gt;
Once you've become familiar with the basics introduced on those tutorials you might have a better grounding for:&lt;br /&gt;
*[[Cutscene tutorial]]&lt;br /&gt;
*[[Map tutorial]] (which also introduces you to [[2DA]] editing)&lt;br /&gt;
*[[Level Editor Tutorial]]&lt;br /&gt;
*[[Scripting tutorial]]&lt;br /&gt;
**[[Useful Scripts]] &amp;lt;!-- for anyone not familar with scripts, this will be very helpful. However i extracted this from the Overview page which seemes inappropriate --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Various small Tutorials, in a unsorted manner. &lt;br /&gt;
*[[How-tos]]&lt;br /&gt;
*[[VFX Tutorial]]&lt;br /&gt;
&lt;br /&gt;
== Demo module ==&lt;br /&gt;
&lt;br /&gt;
The toolset currently ships with a simple demo module pre-loaded into its database.&lt;br /&gt;
&lt;br /&gt;
*[[Demo module]] - how to export and run the demo module.&lt;br /&gt;
&lt;br /&gt;
== Custom content tutorials == &lt;br /&gt;
*[[Tutorial: Using DLC areas in your mods]]&lt;br /&gt;
*[[Tutorial: Adding custom items to custom modules]]&lt;br /&gt;
*[[Tutorial: Adding a Custom Model to Toolset]]&lt;br /&gt;
*[[Tutorial: Creating a custom placeable from a model]]&lt;br /&gt;
*[[Tutorial: Reskinning an Item]]&lt;br /&gt;
*[[Tutorial: Creating recolors of existing items]]&lt;br /&gt;
*[[Tutorial: Understanding Tints: Overriding Defaults &amp;amp; Creating New Ones]]&lt;br /&gt;
*[[Tutorial: Adding a New Weapon Type]]&lt;br /&gt;
*[[Tutorial: Adding custom heraldry to a shield]]&lt;br /&gt;
*[[Tutorial: Usable campaign items]]&lt;br /&gt;
*[[Adding a New Spell Tutorial]]&lt;br /&gt;
*[[UI Tutorial (draft)]]&lt;br /&gt;
&lt;br /&gt;
== Character generation tutorials ==&lt;br /&gt;
*[[Backgrounds tutorial|Background/Origin Tutorial]]&lt;br /&gt;
*[[Add A New Class Tutorial]]&lt;br /&gt;
*[[High-Level Character Generation]]&lt;br /&gt;
&lt;br /&gt;
== Companion Tutorials ==&lt;br /&gt;
*[[Follower tutorial]] (Simple and advanced, requires scripting knowledge)&lt;br /&gt;
*[[Follower_guidelines]] (contains general guidelines and compatibility information)&lt;br /&gt;
&lt;br /&gt;
== Other Tutorials ==&lt;br /&gt;
*[[ToolSet: Area Layouts]]&lt;br /&gt;
*[[Adding a Location to the Single Player Campaign Tutorial]]&lt;br /&gt;
*[[Noob to pro]] (Step by step guide to making a new standalone campaign)&lt;br /&gt;
*[[Module Priority Tutorial]] How to set module. Priority for multiple mods with similar files, so they don't interfere&lt;br /&gt;
*[[Plot]] Information on configuring plot flags for journal and codex entries&lt;br /&gt;
&lt;br /&gt;
== External Tutorials ==&lt;br /&gt;
*[http://dragonagemodding.wordpress.com Beyond Ferelden] has many in-depth tutorials by jwvanderbeck.&lt;br /&gt;
*[http://www.youtube.com/watch?v=TwQNRBFLhrE Playable Area and Conversation] video tutorial by [http://social.bioware.com/64020/ st4rdog].&lt;br /&gt;
*[http://www.youtube.com/watch?v=CaHldJcUTz8 Simple Conversation Cameras] video tutorial by [http://social.bioware.com/64020/ st4rdog].&lt;br /&gt;
*[http://www.youtube.com/watch?v=QOQJ2heQto4 Cutscene and Trigger] video tutorial by [http://social.bioware.com/64020/ st4rdog].&lt;br /&gt;
*[http://www.youtube.com/watch?v=szWKgj2ZuXo Custom Level and Room Building] video tutorial by [http://social.bioware.com/64020/ st4rdog].&lt;br /&gt;
*[http://www.youtube.com/watch?v=DKJ7F14n8o8 Downloading and Installing the Toolset] video tutorial by [http://social.bioware.com/74287/ DragonAge22].&lt;br /&gt;
*[http://www.youtube.com/watch?v=iMPBsulv9xI Creating a Room] video tutorial by [http://social.bioware.com/74287/ DragonAge22].&lt;br /&gt;
*[http://www.youtube.com/watch?v=g3kx2CaarHo How to Make an Interior Level with Lighting] video tutorial by [http://social.bioware.com/group/60/ Darkworld Development Team].&lt;br /&gt;
*[http://www.youtube.com/watch?v=O6TeZeE1Lc8 Making a Room] video tutorial by BigDrip681.&lt;br /&gt;
*[http://social.bioware.com/5339/blog/576/ Custom Player Items In Single Player] by [http://social.bioware.com/5339/ weriK].&lt;br /&gt;
*[http://social.bioware.com/5339/blog/651/ The Secret Behind Item Statistics] by [http://social.bioware.com/5339/ weriK].&lt;br /&gt;
*[http://social.bioware.com/project/923/ Guide for installing/uninstalling/updating Mods] Beginner Guide to get started with using Mods by [http://social.bioware.com/237411/ Alexspeed].&lt;br /&gt;
*[http://www.jezelf.co.uk/tutorials.htm Photoshop Map making tutorials] Credits to Jason Elford, brought to DAT wiki by [http://social.bioware.com/48156/ Arixsus]&lt;br /&gt;
*[http://social.bioware.com/project/527/ Video Tutorials by SilentCid] Multiple in-depth video tutorials of the DA Toolset&lt;br /&gt;
*[http://www.youtube.com/view_play_list?p=EF29DD1AACEBA92A Qkrch's Video Tutorials] Toolset tutorial complete series for the experienced builder (Spanish &amp;amp; English)&lt;br /&gt;
*[http://www.theengineeringguild.co.uk/da-new-campaign-location-tutorial World Editing and Area Creation] Tutorial by [http://social.bioware.com/profile/7848 giskard44] where he walks you through a module creation process for an single player addin.&lt;br /&gt;
*[http://social.bioware.com/203442/blog/1352/ Custom Item Materials] by [http://social.bioware.com/203442/ Chains-Gore].&lt;br /&gt;
*[http://bg2redux.student.utwente.nl/trac/wiki/TutorialLightmapping Lighting Tutorial with Troubleshooting section] (aimed at beginners)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
*[[Compatibility]]&lt;br /&gt;
*[[Dragon Age 2]]&lt;br /&gt;
*Can't find what you need? See [[Wiki Improvement Requests]]&lt;br /&gt;
{{Languages|Tutorials}}&lt;br /&gt;
[[Category:Tutorials| ]]&lt;/div&gt;</summary>
		<author><name>Obadiah</name></author>	</entry>

	</feed>