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

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Talk:Follower_tutorial&amp;diff=16490</id>
		<title>Talk:Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Talk:Follower_tutorial&amp;diff=16490"/>
				<updated>2011-07-21T18:08:38Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Handling followers more robustly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Handling followers more robustly ==&lt;br /&gt;
&lt;br /&gt;
Just a few things&lt;br /&gt;
* I don't think the described behaviour is a bug in [[UT_HireFollower]](). It's documented that &amp;quot;This function will do nothing for plot followers&amp;quot;. It was never intended for use with normal followers, and the code even checks the object tag against the single player campaign's companions. It'll fail to check against your own module's custom followers, though, so it'll do something, but that something isn't always what you want either.&lt;br /&gt;
&lt;br /&gt;
* Plot script gen00pt_party.nss and party_h have some plot-companion handling functions. I wouldn't really give it a short treatment at the bottom under &amp;quot;Advanced Follower Creation&amp;quot; if it's a solid approach. See things like Party_GetFollowerByTag in party_h with an interesting function and comment:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
object Party_GetFollowerByTag(string sTag)&lt;br /&gt;
{&lt;br /&gt;
    // We have to retrieve the follower like this. Trying to do it with&lt;br /&gt;
    // GetObjectByTag proved to mess up lots of stuff. -- yaron.&lt;br /&gt;
    object [] arParty = GetPartyPoolList();&lt;br /&gt;
    int i;&lt;br /&gt;
    int nSize = GetArraySize(arParty);&lt;br /&gt;
    object oCurrent;&lt;br /&gt;
    for(i = 0; i &amp;lt; nSize; i++)&lt;br /&gt;
    {&lt;br /&gt;
        oCurrent = arParty[i];&lt;br /&gt;
        if(GetTag(oCurrent) == sTag)&lt;br /&gt;
            return oCurrent;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return UT_GetNearestObjectByTag(GetMainControlled(), sTag, TRUE);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* It's probably worth going through those scripts and adapting them for general tutorial use. That way we can benefit from whatever gotchas have already been solved.&lt;br /&gt;
&lt;br /&gt;
--[[User:FollowTheGourd|FollowTheGourd]] 17:52, 1 January 2011 (UTC)&lt;br /&gt;
-------------------&lt;br /&gt;
As the author of the &amp;quot;alternative approach&amp;quot; section, my own view is that this should effectively replace that whole section with the monstrous hire script, which really belongs in a how-I-did-it page rather than in a tutorial. However, I am currently up to my armpits in work on my own mod and just don't  currently have the bandwidth to undertake the redraft. --[[User:Gaxkang55|Gaxkang55]] 04:10, 8 January 2011 (UTC)&lt;br /&gt;
-------------------&lt;br /&gt;
I have some sympathy with that. Indeed, I suspect that most of the additions could be integrated into one &amp;quot;best practice&amp;quot; approach. However, I hesitate to carve this up without some informed debate. I'll volunteer to redraft if a few people are willing to join a group discussion first. [[User:Proleric1|Proleric1]] 12:06, 8 January 2011 (UTC)&lt;br /&gt;
-------------------&lt;br /&gt;
Would be happy to be part of the discussion. Perhaps FollowTheGourd might join the party as well :-) --[[User:Gaxkang55|Gaxkang55]] 08:19, 10 January 2011 (UTC)&lt;br /&gt;
-------------------&lt;br /&gt;
Just to say I haven't forgotten about this. Too many distractions recently! Will launch the redraft discussion shortly. [[User:Proleric1|Proleric1]] 06:16, 7 February 2011 (UTC)&lt;br /&gt;
-------------------&lt;br /&gt;
I'm no longer in a position to redraft this. Perhaps someone else would like to have a go. [[User:Proleric1|Proleric1]] 18:08, 21 July 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
== ==&lt;br /&gt;
&lt;br /&gt;
great tutorial. my only problem is: my companion, Erik has different skills and doesn't seem to follow his autolevel template. --[[User:Mono0x32440|Mono0x32440]] 17:46, 25 February 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Follower's Portrait ==&lt;br /&gt;
&lt;br /&gt;
I cannot figure out how to change the default grey backgrounded portrait for the new followers. It would be nice to have pose and background options.&lt;br /&gt;
&lt;br /&gt;
== Dog equipment slots ==&lt;br /&gt;
&lt;br /&gt;
Mention should be made of the fact that a dog follower needs to have the appropriate equipment slot mask. I will make the addition to the text if no-one has any objections/suggestions in a couple of days. --[[User:Gaxkang55|Gaxkang55]] 09:38, 21 October 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
I don't think that happened, so I've done it now. [[User:Proleric1|Proleric1]] 10:12, 2 January 2011 (UTC)&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16465</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16465"/>
				<updated>2011-07-12T06:52:00Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* What if there are more than three potential followers? */&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;
            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>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Inventory&amp;diff=16416</id>
		<title>Inventory</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Inventory&amp;diff=16416"/>
				<updated>2011-07-09T06:38:15Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Armor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A creature or container object can contain one or more [[item]]s in inventory. &lt;br /&gt;
&lt;br /&gt;
If a container is destroyed the contents of its inventory are transferred to a [[Bodybag]].&lt;br /&gt;
&lt;br /&gt;
Each item can have the following properties set:&lt;br /&gt;
&lt;br /&gt;
*Subgroup&lt;br /&gt;
*Slot - Sets whether the creature has equipped the item. &amp;quot;Not equipped&amp;quot; leaves the item in the general inventory, &amp;quot;Main&amp;quot; puts the item into the creature's main hand, and &amp;quot;off-hand&amp;quot; puts the item into the creature's off hand.&lt;br /&gt;
*Set - Items that are part of a set are meant to be given as a group. !!This is handled in the giving/taking script?!!&lt;br /&gt;
*StackSize - how many copies of this item are present in a stack&lt;br /&gt;
*Droppable - a checkbox that indicates whether the item is dropped when the creature is killed&lt;br /&gt;
*Stealable - a checkbox that indicates whether the item can be stolen from the creature&lt;br /&gt;
&lt;br /&gt;
[[File:Creature inventory.png|center|thumb|400px|A typical creature inventory screen]]&lt;br /&gt;
&lt;br /&gt;
[[Merchant]]s also have an inventory.&lt;br /&gt;
&lt;br /&gt;
See [[Treasure system]] for auto-generated loot.&lt;br /&gt;
&lt;br /&gt;
== Inventory Count - basic syntax ==&lt;br /&gt;
&lt;br /&gt;
How do you know if the user has enough inventory space before adding items?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
 //Get max inventory size&lt;br /&gt;
 int iMaxInventorySize = GetMaxInventorySize(GetHero());&lt;br /&gt;
 object[] oInv = GetItemsInInventory(GetHero(), GET_ITEMS_OPTION_BACKPACK, 0, &amp;quot;&amp;quot;, 1);&lt;br /&gt;
   &lt;br /&gt;
 PrintToLog(&amp;quot;Max Inventory size:&amp;quot; + IntToString(iMaxInventorySize));&lt;br /&gt;
 PrintToLog(&amp;quot;Current Inventory count:&amp;quot; + IntToString(GetArraySize(oInv)));&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This returned 102 items in my inventory out of a total of 120.&lt;br /&gt;
&lt;br /&gt;
== Inventory Subgroup Codes ==&lt;br /&gt;
&lt;br /&gt;
===Armor===&lt;br /&gt;
*351000 - Mage Robe / Clothing&lt;br /&gt;
*331000 - Light Armor   &lt;br /&gt;
*332000 - Medium Armor    &lt;br /&gt;
*333000 - Heavy Armor    &lt;br /&gt;
*334000 - Massive Armor&lt;br /&gt;
&lt;br /&gt;
===Glove===&lt;br /&gt;
*311000 - Light Gloves&lt;br /&gt;
*312000 - Medium Gloves&lt;br /&gt;
*311000 - Heavy Gloves&lt;br /&gt;
*314000 - Massive Gloves&lt;br /&gt;
&lt;br /&gt;
===Boots===&lt;br /&gt;
*321000 - Light Boots&lt;br /&gt;
*322000 - Medium Boots&lt;br /&gt;
*323000 - Heavy Boots&lt;br /&gt;
*324000 - Massive Boots&lt;br /&gt;
&lt;br /&gt;
===Helmets===&lt;br /&gt;
*301000 - Light Helmet&lt;br /&gt;
*302000 - Medium Helmet&lt;br /&gt;
*303000 - Heavy Helmet&lt;br /&gt;
*304000 - Massive Helmet&lt;br /&gt;
*351500 - Mage Helmet&lt;br /&gt;
&lt;br /&gt;
===Shields===&lt;br /&gt;
*343000 - Kite Shield&lt;br /&gt;
*342000 - Large Shield    &lt;br /&gt;
*341000 - Small Shield&lt;br /&gt;
*344000 - Tower Shield&lt;br /&gt;
&lt;br /&gt;
===Magic Staff===&lt;br /&gt;
*221000 - Staff&lt;br /&gt;
&lt;br /&gt;
===Melee Weapons===&lt;br /&gt;
*201000 - Waraxes&lt;br /&gt;
*202000 - Battleaxes&lt;br /&gt;
*203000 - Daggers&lt;br /&gt;
*204000 - Greatswords&lt;br /&gt;
*205000 - Longswords&lt;br /&gt;
*206000 - Maces&lt;br /&gt;
*207000 - Mauls&lt;br /&gt;
&lt;br /&gt;
===Ranged Weapons===&lt;br /&gt;
*211000 - Shortbows&lt;br /&gt;
*212000 - Longbows&lt;br /&gt;
*213000 - Crossbows&lt;br /&gt;
*214000 - Ammo&lt;br /&gt;
&lt;br /&gt;
===Other===&lt;br /&gt;
*411000 - Amulets&lt;br /&gt;
*421000 - Belts&lt;br /&gt;
*431000 - Rings&lt;br /&gt;
&lt;br /&gt;
===Special===&lt;br /&gt;
*361000 - Collar&lt;br /&gt;
*362000 - Warpaint&lt;br /&gt;
&lt;br /&gt;
[[Category:Inventory]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16379</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16379"/>
				<updated>2011-06-22T07:01:09Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* What if there are more than three potential followers? */&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;
            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;
            SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&lt;br /&gt;
            SetImmortal(oFollower, FALSE);&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>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16378</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16378"/>
				<updated>2011-06-15T16:45:20Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* What if there are more than three potential followers? */&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;
            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;
            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>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16377</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16377"/>
				<updated>2011-06-15T16:41:46Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Why don't my followers gain XP? */&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;
            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;
                UT_HireFollower(oFollower);&lt;br /&gt;
                SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
                AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
                SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&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;
            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>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=PrintToLog&amp;diff=16162</id>
		<title>PrintToLog</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=PrintToLog&amp;diff=16162"/>
				<updated>2011-05-30T07:19:15Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{dafunction&lt;br /&gt;
|name=PrintToLog&lt;br /&gt;
|brief=Prints a timestamped entry to the log file.&lt;br /&gt;
|param1type=string&lt;br /&gt;
|param1name=sMessage&lt;br /&gt;
|param1desc=The string entry to print to the log file.&lt;br /&gt;
|returntype=void&lt;br /&gt;
|returndesc=&lt;br /&gt;
|sourcefile=script.ldf&lt;br /&gt;
|sourcemodule=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- This section contains the full description from the functions comments. Do not change unless you are confident these are incomplete or incorrect. --&amp;gt;&lt;br /&gt;
Prints an entry to the log file. Note this will only be visible if Script logging is enabled. To enable script logging open the &amp;lt;code&amp;gt;&amp;lt;DragonAgeInstallDirectory&amp;gt;\bin_ship\[[ECLog.ini]]&amp;lt;/code&amp;gt; file and set &amp;lt;code&amp;gt;Script=1&amp;lt;/code&amp;gt; in the &amp;lt;code&amp;gt;[LogTypes]&amp;lt;/code&amp;gt; section. If this file doesn't exist, create it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- == Remarks == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains additional comments, observations and known issues. --&amp;gt;&lt;br /&gt;
&amp;lt;!-- == Examples == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains examples transcluded from the snippet library. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&amp;lt;!-- This section contains links to articles, functions or constant groups. --&amp;gt;&lt;br /&gt;
[[PrintInteger]], [[PrintFloat]], [[PrintString]], [[PrintObject]], [[PrintVector]]&lt;br /&gt;
[[Category: Print &amp;amp; log functions]]&lt;br /&gt;
[[Category:Logging]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16161</id>
		<title>Follower tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Follower_tutorial&amp;diff=16161"/>
				<updated>2011-05-28T18:32:07Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Dog talents and equipment slots don't work */&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;
            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. For now the best/easiest approach to take might be to make a copy of UT_HireFollower in an include file and rename it something like UT_HireFollower_Fixed, 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;
(Note: Be aware if you use the name UT_HireFollower_Fixed you may end up finding your include file conflicting with someone else who has named it the same in their include.)&lt;br /&gt;
&lt;br /&gt;
Alternately you need to clear a flag in a separate script to the one in which they're hired.&lt;br /&gt;
&lt;br /&gt;
You must use the '''SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);''' statement in a script you can be sure will run soon after your hiring script.&lt;br /&gt;
&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;
                UT_HireFollower(oFollower);&lt;br /&gt;
                SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);&lt;br /&gt;
                AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));&lt;br /&gt;
                SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);&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;
            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>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=2DA_ranges_in_use&amp;diff=16160</id>
		<title>2DA ranges in use</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=2DA_ranges_in_use&amp;diff=16160"/>
				<updated>2011-05-28T08:18:53Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* APR_base */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page is meant to enumerate row ID ranges that are used by the main game and by various popular addins, to avoid accidental overlap. See also [[Prefixes in use]] and [[Compatibility]].&lt;br /&gt;
&lt;br /&gt;
Note that there's no need for 2DA row IDs to be sequential, so you can use very large row ID numbers to reduce the chances of collision.&lt;br /&gt;
&lt;br /&gt;
Version 1.0 of the toolset had a bug in ExcelProcessor that caused problems with high row ID numbers, but this has been fixed in subsequent releases. See [[Bug: ExcelProcessor doesn't handle row IDs above 8.3 million correctly|the bug report]].&lt;br /&gt;
&lt;br /&gt;
As of now there is a bug that prevents ID's above 255 to be used for some M2DA's. See [[Bug: High M2DA ID ranges might work in the toolset, but not in game|Bug report]] for a list of tables affected.&lt;br /&gt;
&lt;br /&gt;
Another [[Bug: DLC conflicts with standalone campaigns|bug]] affects the rewards M2DA.&lt;br /&gt;
&lt;br /&gt;
== ABI_base ==&lt;br /&gt;
&lt;br /&gt;
According to the [[ABI_base]] page under the ''tooltipstrref'' column, anything over 500000 is considered a debuff. This would limit the range a fair amount.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 200262'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000 - 38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 50000 - 50001&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/861/ Advanced Tactics]&lt;br /&gt;
|-&lt;br /&gt;
| 51000 - 51002&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/1888/ Advanced Quickbar]&lt;br /&gt;
|-&lt;br /&gt;
| 450000 - 450300&lt;br /&gt;
| ladydesire's [http://social.bioware.com/project/815/ Tevinter Warden class]&lt;br /&gt;
|-&lt;br /&gt;
| 466000 - 466100&lt;br /&gt;
| Apolyon6k's [http://social.bioware.com/project/3842/ The magic of innocence]&lt;br /&gt;
|-&lt;br /&gt;
| 901974-903000 and 401974-403000(modal)&lt;br /&gt;
| Idomeneas' [http://social.bioware.com/project/3152/ Valeria Addon]&lt;br /&gt;
|-&lt;br /&gt;
| 1337000 - 1337008&lt;br /&gt;
| amcnow's [http://social.bioware.com/project/3823/ Respecification]&lt;br /&gt;
|-&lt;br /&gt;
| 2560000 - 2560500&lt;br /&gt;
| Timelord's [http://social.bioware.com/project/1845/ Blood and Lyrium]&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680250&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000 - 40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 300000-300047&lt;br /&gt;
| rebel5555's [http://social.bioware.com/project/2646/ 2 Handed Weapon Abilities for Arcane Warriors]&lt;br /&gt;
|-&lt;br /&gt;
| 300000-300047&lt;br /&gt;
| rebel5555's [http://social.bioware.com/project/3637/ Dual Weapon Abilities for Arcane Warriors]&lt;br /&gt;
|-&lt;br /&gt;
| 300000-300047&lt;br /&gt;
| rebel5555's [http://social.bioware.com/project/2644/ Weapon and Shield Abilities for Arcane Warriors]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== AI_TacticsPresets ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 9'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| 10 - 15&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/861/ Advanced Tactics]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
== ambient_ai ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| 1000000-1001000&lt;br /&gt;
| [http://social.bioware.com/project/178/ Crown of Creation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== ANIM_base ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| 65000 - 65002&lt;br /&gt;
| BioSpirit's [http://social.bioware.com/project/1647/ Hilltop Under Siege]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== APR_base ==&lt;br /&gt;
&lt;br /&gt;
Note that there is a bug involving this 2DA: [[Bug: APR base maximum M2DA row ID is 65535 in the toolset]]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 90'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000 - 38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 40000 - 40010&lt;br /&gt;
| Alschemid - [http://social.bioware.com/project/3175/ Horses] and [http://social.bioware.com/project/3666/ Sandbox]&lt;br /&gt;
|-&lt;br /&gt;
| 55000 - 57000&lt;br /&gt;
| World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
| 64000 - 64999&lt;br /&gt;
| [http://social.bioware.com/project/178/ Crown of Creation]&lt;br /&gt;
|-&lt;br /&gt;
| 65000 - 65001&lt;br /&gt;
| BioSpirit's [http://social.bioware.com/project/1647/ Hilltop Under Siege]&lt;br /&gt;
|-&lt;br /&gt;
| 65010 - 65025&lt;br /&gt;
| Mutantspicy Oracle and Enchanted Armor [Dragonage Nexus]&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 1100000&lt;br /&gt;
| DA Workshop / by frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== areadata ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== armor_massive_variation ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 8'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| 50-50&lt;br /&gt;
| Alschemid - [http://social.bioware.com/project/3666/ Sandbox]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: the highest working tested ID for this variation is 141. See [http://social.bioware.com/wiki/datoolset/index.php/Bug:_High_M2DA_ID_ranges_might_work_in_the_toolset,_but_not_in_game bug report]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== BITM_base and ItemStats_ ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 30000 - 30500&lt;br /&gt;
| Ambaryerno - [http://social.bioware.com/project/415/ Arms and Armor]&lt;br /&gt;
|-&lt;br /&gt;
| 37000-38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 40000 - 40200&lt;br /&gt;
| DA Workshop / by frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 57000-59000&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
| 77000-79000&lt;br /&gt;
| [Sanguine Sunrise by LukaCrosszeria [http://social.bioware.com/project/4024/ Sanguine Sunrise]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 50000 - 50100&lt;br /&gt;
| Feline Fuelled Games - (by Silk) [http://www.felinefuelledgames.de/ Feline Fuelled Games]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== CLA_base ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 25'''&lt;br /&gt;
| '''Bioware&lt;br /&gt;
|-&lt;br /&gt;
| 10000 - 10012&lt;br /&gt;
| Ladydesire&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== crafting_recipe_types ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 7'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680020&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== crafting_recipes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 91'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5682000&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== engineevents ==&lt;br /&gt;
&lt;br /&gt;
Those ranges relates to custom events types/ID and not to engineevents based [[Event_override|events overriding]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 500 - 500&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/861/ Advanced Tactics]&lt;br /&gt;
|-&lt;br /&gt;
| 510 - 511&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/1888/ Advanced Quickbar]&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680050&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== guitypes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 600 - 600&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/861/ Advanced Tactics]&lt;br /&gt;
|-&lt;br /&gt;
| 601 - 601&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/1888/ Advanced Quickbar]&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 666000 - 666020&lt;br /&gt;
| Apolyon6k's [http://social.bioware.com/project/3842/ The magic of innocence]&lt;br /&gt;
|-&lt;br /&gt;
| 1337000 - 1337001&lt;br /&gt;
| amcnow's [http://social.bioware.com/project/3823/ Respecification]&lt;br /&gt;
|-&lt;br /&gt;
| 1974100-1974200&lt;br /&gt;
| Idomeneas' [http://social.bioware.com/project/3152/ Valeria Addon]&lt;br /&gt;
|-&lt;br /&gt;
| 2560000 - 2560050&lt;br /&gt;
| Timelord's [http://social.bioware.com/project/1845/ Blood and Lyrium]&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680010&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Heraldry ==&lt;br /&gt;
There is a [[Bug:_High_M2DA_ID_ranges_might_work_in_the_toolset,_but_not_in_game | bug]] with this table. The range 0-255 is known to work.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 1001000&lt;br /&gt;
| [http://social.bioware.com/project/178/ Crown of Creation] (using 201 onwards temporarily) &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== itemprps ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 10022'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000-38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 77000-79000&lt;br /&gt;
| Sanguine Sunrise by LukaCrosszeria [http://social.bioware.com/project/4024/ Sanguine Sunrise]&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 2000000&lt;br /&gt;
| DA Workshop / by frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 2555000-2555010&lt;br /&gt;
| PavelNovotny - [http://social.bioware.com/project/517/ Gay Bars of Ferelden]&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680050&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 7570000-7770000&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
| 536873321 - 536873322&lt;br /&gt;
| Elys' [http://social.bioware.com/project/522/ Mysterious Gifts]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 2560000-2560050&lt;br /&gt;
| Timelord's [http://social.bioware.com/project/1845/ Blood and Lyrium]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== itemsets ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 30'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 2555000-2555010&lt;br /&gt;
| PavelNovotny - [http://social.bioware.com/project/517/ Gay Bars of Ferelden]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680500&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 7570000-7770000&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
| 1405261000 - 1405261999&lt;br /&gt;
| nezroy - [http://social.bioware.com/project/1834/ Warden Shields], [http://www.dragonagenexus.com/downloads/file.php?id=793 Leliana Item Set]&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 2000000&lt;br /&gt;
| DA Workshop / by frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 7771000 - 7771500&lt;br /&gt;
| [http://social.bioware.com/project/2157/ Dark Times: The Confederacy of Malkuth] (reserved by Starlight on Questorion's behalf)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== ItemVariations (all) ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 30'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000'''&lt;br /&gt;
| '''Bioware - reserved (guessed)'''&lt;br /&gt;
|-&lt;br /&gt;
| 12000 - 12100&lt;br /&gt;
| [http://social.bioware.com/project/1923/ Adonnay's Weaponry] (reserved by mikemike37 on his behalf)&lt;br /&gt;
|-&lt;br /&gt;
| 77 - 99&lt;br /&gt;
| Sanguine Sunrise by LukaCrosszeria [http://social.bioware.com/project/4024/ Sanguine Sunrise]&lt;br /&gt;
|-&lt;br /&gt;
| 140 - 160&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 101000 - 400000&lt;br /&gt;
| [http://social.bioware.com/project/2157/ Dark Times: The Confederacy of Malkuth] (reserved by Starlight on Questorion's behalf)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
note: ItemVariations are affected by the bug which prevents ID's above 255 from appearing properly in the game. See [[Bug: High M2DA ID ranges might work in the toolset, but not in game|Bug report]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== M2DA_base ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1016, 2000 - 2010, 10011 - 10142, ...? '''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 5000 - 5014&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/861/ Advanced Tactics]&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000 - 38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 77000 - 79000&lt;br /&gt;
| [http://social.bioware.com/project/4024/ Sanguine Sunrise] by LukaCrosszeria &lt;br /&gt;
|-&lt;br /&gt;
| 100000 - 100000&lt;br /&gt;
| Anakin's [http://social.bioware.com/project/1907/ Event Manager]&lt;br /&gt;
|-&lt;br /&gt;
| 690000 - 690100&lt;br /&gt;
| [http://www.dragonagenexus.com/downloads/file.php?id=1617 Karma's Origins Companions]&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 1100000&lt;br /&gt;
| DA Workshop / by frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 1337000 - 1337001&lt;br /&gt;
| amcnow's [http://social.bioware.com/project/3823/ Respecification]&lt;br /&gt;
|-&lt;br /&gt;
| 2300000 - 2300100&lt;br /&gt;
| [http://social.bioware.com/project/178/ Crown of Creation] (M2DA prefix: COC)&lt;br /&gt;
|-&lt;br /&gt;
| 2560000 - 2560050&lt;br /&gt;
| Timelord's [http://social.bioware.com/project/1845/ Blood and Lyrium]&lt;br /&gt;
|-&lt;br /&gt;
| 5000000 - 5000010&lt;br /&gt;
| Noob766's [http://social.bioware.com/project/3827/ Companion Compatibility pack]&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680050&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 5680050 - 5680055&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/3185/ Flexible craft UI]&lt;br /&gt;
|-&lt;br /&gt;
| 5681000 - 5681005&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/2896/ DACrafting framework]&lt;br /&gt;
|-&lt;br /&gt;
| 6000000 - 6000050&lt;br /&gt;
| TreDawn - [http://social.bioware.com/project/1750/ Nesiara Companion]&lt;br /&gt;
|-&lt;br /&gt;
| 6660000 - 6660050&lt;br /&gt;
| Apolyon6k - [http://social.bioware.com/project/3842/ The magic of innocence]&lt;br /&gt;
|-&lt;br /&gt;
| 7000000 - 7000050&lt;br /&gt;
| FtG - [http://social.bioware.com/project/1688/ UI Mod]&lt;br /&gt;
|-&lt;br /&gt;
| 7000051 - 7000055&lt;br /&gt;
| FtG - [http://social.bioware.com/project/3663/ Custom Loading Screen]&lt;br /&gt;
|-&lt;br /&gt;
| 7000056 - 7000071&lt;br /&gt;
| FtG - [http://social.bioware.com/forum/1/topic/75/index/5569843 Portrait dialogue and custom tokens (test release)]&lt;br /&gt;
|-&lt;br /&gt;
| 7000075-7000080&lt;br /&gt;
| FtG - [http://ftg.wikidot.com/ftg-quickbar Quickbar]&lt;br /&gt;
|-&lt;br /&gt;
| 7570000 - 7770000&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone] &lt;br /&gt;
|-&lt;br /&gt;
| 7777770 - 7777799&lt;br /&gt;
| Magic - [http://social.bioware.com/project/1429/ Void Walker] (M2DA prefix: VWK)&lt;br /&gt;
|-&lt;br /&gt;
| 9000000 - 9000050&lt;br /&gt;
| Ambaryerno - [http://social.bioware.com/project/415/ Arms and Armor]&lt;br /&gt;
|- &lt;br /&gt;
| 30000000 - 40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 1140150041 - 1140150091&lt;br /&gt;
| DLAN_Immortality - [http://social.bioware.com/project/789/ Ser Gilmore NPC]&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| 1553521700 - 1553521750&lt;br /&gt;
| Alschemid - [http://social.bioware.com/project/3666/ Sandbox]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== materialrules ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000-38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 536873321 - 536873323&lt;br /&gt;
| Elys' [http://social.bioware.com/project/522/ Mysterious Gifts]&lt;br /&gt;
|-&lt;br /&gt;
| 1405261000 - 1405261999&lt;br /&gt;
| nezroy - [http://social.bioware.com/project/1834/ Warden Shields], [http://www.dragonagenexus.com/downloads/file.php?id=793 Leliana Item Set]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== materialtypes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 88'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000-38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680300&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 536873321 - 536873340&lt;br /&gt;
| Elys' [http://social.bioware.com/project/522/ Mysterious Gifts]&lt;br /&gt;
|-&lt;br /&gt;
| 1405261000 - 1405261999&lt;br /&gt;
| nezroy - [http://social.bioware.com/project/1834/ Warden Shields], [http://www.dragonagenexus.com/downloads/file.php?id=793 Leliana Item Set]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== PartyPicker ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 11'''&lt;br /&gt;
| '''Bioware - Main campaign'''&lt;br /&gt;
|-&lt;br /&gt;
| '''????'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 101-199&lt;br /&gt;
| [http://social.bioware.com/project/178/ Crown of Creation]&lt;br /&gt;
|-&lt;br /&gt;
| 200 - 299&lt;br /&gt;
| DA Workshop / Author: frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 300 - 350&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
| 1974-1980&lt;br /&gt;
| Idomeneas' [http://social.bioware.com/project/3152/ Valeria Addon]&lt;br /&gt;
|-&lt;br /&gt;
| 5711-5720&lt;br /&gt;
| [http://social.bioware.com/project/3926/ Castle Drakhaoul] by Marshal57'&lt;br /&gt;
|-&lt;br /&gt;
| 6660 - 6665&lt;br /&gt;
| Apolyon6k's [http://social.bioware.com/project/3842/ The magic of innocence]&lt;br /&gt;
|-&lt;br /&gt;
| 77000 - 79000&lt;br /&gt;
| [http://social.bioware.com/project/4024/ Sanguine Sunrise] by LukaCrosszeria &lt;br /&gt;
|-&lt;br /&gt;
| 6900000 - 6900200&lt;br /&gt;
| [http://www.dragonagenexus.com/downloads/file.php?id=1617 Karma's Origins Companions]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== PRCSCR ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000 - 38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 77000 - 79000&lt;br /&gt;
| [http://social.bioware.com/project/4024/ Sanguine Sunrise] by LukaCrosszeria &lt;br /&gt;
|-&lt;br /&gt;
| 690000 - 690100&lt;br /&gt;
| [http://www.dragonagenexus.com/downloads/file.php?id=1617 Karma's Origins Companions]&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 1100000&lt;br /&gt;
| DA Workshop / by frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 1337000&lt;br /&gt;
| amcnow's [http://social.bioware.com/project/3823/ Respecification]&lt;br /&gt;
|-&lt;br /&gt;
| 2000000 - 2000050&lt;br /&gt;
| [http://www.dragonagenexus.com/downloads/file.php?id=942 Oracle,mutantspicy's magic vault, and other custom armors]&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680020&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 6000000 - 6000050&lt;br /&gt;
| TreDawn - [http://social.bioware.com/project/1750/ Nesiara Companion]&lt;br /&gt;
|-&lt;br /&gt;
| 7570000 - 7770000&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
| 10100000&lt;br /&gt;
| Camp [http://social.bioware.com/project/463/ storage chest]&lt;br /&gt;
|-&lt;br /&gt;
| 10100011 - 10100013&lt;br /&gt;
| Didymos' [http://social.bioware.com/project/2620/ Camp Merchant Chest]&lt;br /&gt;
|-&lt;br /&gt;
| 10100014 - 10100016&lt;br /&gt;
| Didymos' [http://social.bioware.com/project/2717/ Item Sets Fix]&lt;br /&gt;
|-&lt;br /&gt;
| 10100100 - 10100110&lt;br /&gt;
| Eshme's [http://social.bioware.com/project/1929/ Sleeping Tent]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000 - 40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 42006090 - 42006100&lt;br /&gt;
| [http://www.dragonagenexus.com/downloads/file.php?id=1120 Morrigan Restoration Patch]&lt;br /&gt;
|-&lt;br /&gt;
| 1000197400 - 1000197410&lt;br /&gt;
| Idomeneas' [http://social.bioware.com/project/3152/ Valeria Addon]&lt;br /&gt;
|-&lt;br /&gt;
| 1109197751 - 1109197799&lt;br /&gt;
| Schwinni - [http://dragonagenexus.com/downloads/file.php?id=1020 Awakening Runes Fixes], [http://dragonagenexus.com/downloads/file.php?id=1112 Awakening Blackblade Armor Dragon Drop Fix]&lt;br /&gt;
|-&lt;br /&gt;
| 1140150041 - 1140150091&lt;br /&gt;
| DLAN_Immortality - [http://social.bioware.com/project/789/ Ser Gilmore NPC]&lt;br /&gt;
|-&lt;br /&gt;
| 1405261000 - 1405261999&lt;br /&gt;
| nezroy - [http://social.bioware.com/project/1834/ Warden Shields], [http://www.dragonagenexus.com/downloads/file.php?id=793 Leliana Item Set]&lt;br /&gt;
|-&lt;br /&gt;
| 1553521700 - 1553521710&lt;br /&gt;
| Alschemid - [http://social.bioware.com/project/3666/ Sandbox]&lt;br /&gt;
|-&lt;br /&gt;
| 1672464532 - 1672464542&lt;br /&gt;
| DLAN_Immortality - [http://social.bioware.com/project/2991/ Ser Gilmore NPC Awakening]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== placeable_types ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 14000 - 16000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 17000 - 19000&lt;br /&gt;
| Standalone modules (see discussion tab)&lt;br /&gt;
|-&lt;br /&gt;
| 37000-38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 43050-43061&lt;br /&gt;
| Eshme's [http://social.bioware.com/project/1929/ Sleeping Tent]  (Greater 65535 is showing bugs so this is until it is fixed)&lt;br /&gt;
|-&lt;br /&gt;
| 43062-43065&lt;br /&gt;
| BioSpirit's [http://social.bioware.com/project/1647/ Hilltop Under Siege]&lt;br /&gt;
|-&lt;br /&gt;
| 56000-56200&lt;br /&gt;
| [http://social.bioware.com/project/2472/#details Mikes Invisible Boxes]&lt;br /&gt;
|-&lt;br /&gt;
| 2696549 - 2696700&lt;br /&gt;
| PavelNovotny - [http://social.bioware.com/project/517/ Gay Bars of Ferelden] (NOTE: I'm using the 6000-6200 range until Bioware fixes the bug which prevents m2da ID ranges above 900000 from showing up in game.)&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| 7570000-7770000&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 1100000&lt;br /&gt;
| DA Workshop / Author: frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 1974-1978&lt;br /&gt;
| Idomeneas' [http://social.bioware.com/project/3152/ Valeria Addon] (They are low so they'll show in game, recall the toolset bug)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== popups ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 1000001-1001000&lt;br /&gt;
| [http://social.bioware.com/project/178/ Crown of Creation]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== PRJ_base ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680050&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
== String ID ==&lt;br /&gt;
It is not generally necessary to register String ID ranges here. The values generated by the toolset are sufficiently random to minimise the risk of collision. Exception : the Community Contest reserved the range below so that the builders will stick to that and can import VO without having to renumber the VO files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 10000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 89000000  - 89999999&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== tint_override ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| 500 - 520&lt;br /&gt;
| PavelNovotny - [http://social.bioware.com/project/517/ Gay Bars of Ferelden]&lt;br /&gt;
|-&lt;br /&gt;
| 6900 - 6920&lt;br /&gt;
| [http://www.dragonagenexus.com/downloads/file.php?id=1617 Karma's Origins Companions]&lt;br /&gt;
|-&lt;br /&gt;
| 1000001-1001000&lt;br /&gt;
| [http://social.bioware.com/project/178/ Crown of Creation]&lt;br /&gt;
|-&lt;br /&gt;
| 30000000-40000000&lt;br /&gt;
| MCC's Senderfall: The Last Bastion (To author: unreasonable range, please correct)&lt;br /&gt;
|-&lt;br /&gt;
| 1109197701 - 1109197750&lt;br /&gt;
| Schwinni - [http://dragonagenexus.com/downloads/file.php?id=1064 Helmets without wings and retints]&lt;br /&gt;
|-&lt;br /&gt;
| 1553521700 - 1553521750&lt;br /&gt;
| Alschemid - [http://social.bioware.com/project/3666/ Sandbox]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== ts_material ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| 1405261000 - 1405261999&lt;br /&gt;
| nezroy - [http://social.bioware.com/project/1834/ Warden Shields], [http://www.dragonagenexus.com/downloads/file.php?id=793 Leliana Item Set]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== TS_Category ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680005&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 1000001 - 1100000&lt;br /&gt;
| DA Workshop / by frosti [http://www.dragon-age-workshop.de/forum/viewforum.php?f=19/ Icewind Dale Remake]&lt;br /&gt;
|-&lt;br /&gt;
| 7570000-7770000&lt;br /&gt;
| [World of Grone (by Shodushi) [http://social.bioware.com/project/2194/ World of Grone]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== vfx_base ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 1000000'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| 24000 - 26000&lt;br /&gt;
| [http://social.bioware.com/wiki/datoolset/index.php/Community_Contest_Main_Page Community Contest]&lt;br /&gt;
|-&lt;br /&gt;
| 37000-38000&lt;br /&gt;
| [http://bg2redux.student.utwente.nl/trac/wiki Baldur's Gate Redux]&lt;br /&gt;
|-&lt;br /&gt;
| 5680000 - 5680010&lt;br /&gt;
| Phaenan's [http://social.bioware.com/project/672/ The Winter Forge]&lt;br /&gt;
|-&lt;br /&gt;
| 5680011 - 5680019&lt;br /&gt;
| BioSpirit's [http://social.bioware.com/project/1647/ Hilltop Under Siege]&lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== worldmaps (has to be less than 256) ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Range&lt;br /&gt;
! Used by&lt;br /&gt;
|-&lt;br /&gt;
| '''0 - 6'''&lt;br /&gt;
| '''Bioware - reserved'''&lt;br /&gt;
|-&lt;br /&gt;
| '''151 - 151'''&lt;br /&gt;
| Alschemid - [http://social.bioware.com/project/3666/ Sandbox]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| '''210 - 220'''&lt;br /&gt;
| [http://social.bioware.com/project/1845/ Blood and Lyrium]&lt;br /&gt;
|}&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Useful_Scripts&amp;diff=16158</id>
		<title>Useful Scripts</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Useful_Scripts&amp;diff=16158"/>
				<updated>2011-05-27T14:44:29Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Move Inventory (e.g. remove and store player's equipment) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox script}}&lt;br /&gt;
&lt;br /&gt;
This page lists how to accomplish tasks that are relatively simple and commonly needed, but that otherwise require deep scripting knowledge to figure out intuitively how to do.&lt;br /&gt;
&lt;br /&gt;
Feel free to add new sections describing any tricks or techniques you think is worth documenting. If the page becomes too large it can be split up into specific topics.&lt;br /&gt;
&lt;br /&gt;
See also: [[PRCSCR Script Templates]]&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
== Run a cutscene from a trigger ==&lt;br /&gt;
&lt;br /&gt;
Create a script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;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;
 &lt;br /&gt;
void main ()&lt;br /&gt;
{&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEventType = GetEventType(ev);&lt;br /&gt;
    int bEventHandled = FALSE;&lt;br /&gt;
    switch (nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        case EVENT_TYPE_ENTER:&lt;br /&gt;
        {&lt;br /&gt;
            object oCreature = GetEventCreator(ev);&lt;br /&gt;
            if(GetObjectActive(OBJECT_SELF)&lt;br /&gt;
               &amp;amp;&amp;amp; IsPartyMember(oCreature)) &lt;br /&gt;
            { &lt;br /&gt;
                resource rCutscene = R&amp;quot;my_cutscene.cut&amp;quot;;&lt;br /&gt;
                CS_LoadCutscene(rCutscene);&lt;br /&gt;
                SetObjectActive(OBJECT_SELF, FALSE);&lt;br /&gt;
            }         &lt;br /&gt;
         }&lt;br /&gt;
         break;&lt;br /&gt;
    }&lt;br /&gt;
    if (!bEventHandled) //If this event wasn't handled by this script, let the core script try&lt;br /&gt;
    {&lt;br /&gt;
        HandleEvent(ev, RESOURCE_SCRIPT_TRIGGER_CORE);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And set it as the event script for the trigger that you want to have run the cutscene.&lt;br /&gt;
&lt;br /&gt;
== Add a follower to the player's party ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
if(IsPartyMember(oCreature)) {&lt;br /&gt;
  object oFollower = GetObjectByTag(&amp;quot;myfollower&amp;quot;);&lt;br /&gt;
  UT_HireFollower(oCreature, oFollower);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comment : originally, the above example used the function IsPlayer, which doesn't seem to exist.&lt;br /&gt;
&lt;br /&gt;
Note that with Toolset v1.0.982.0, calling UT_HireFollower() will result in a follower who's unable to gain xp. This happens due to the call of&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
  WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, '''TRUE''');&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
to the function&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
  void WR_SetFollowerState(object oCreature, int nState, int nSendEvent = TRUE, int nMinLevel = 0, '''int bPreventLevelup''' = FALSE)&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
To enable the xp gain, the flag CREATURE_REWARD_FLAGS needs to be cleared from the follower after the hired event was processed (there the flag is set). For now the best/easiest approach to take might be to make a copy of UT_HireFollower in an include file and rename it something like UT_HireFollower_Fixed, then make the following change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, TRUE);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
to&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, bPreventLevelup);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Have an enemy play possum and then get up to fight ==&lt;br /&gt;
&lt;br /&gt;
Set the creature's CREATURE_SPAWN_DEAD variable to 2.&lt;br /&gt;
&lt;br /&gt;
When it's time for the creature to rise and attack, execute the following script commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
...&lt;br /&gt;
WR_SetObjectActive(oCreature, TRUE);&lt;br /&gt;
SetCommandable(oCreature, TRUE);&lt;br /&gt;
// Make sure to set this flag back to 0 to avoid problems with savegames.&lt;br /&gt;
SetLocalInt(oCreature, CREATURE_SPAWN_DEAD, 0);&lt;br /&gt;
UT_CombatStart(oCreature, oPC);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Insert content into an existing area ==&lt;br /&gt;
&lt;br /&gt;
If you want to add new content on to an existing area (for example, putting a new character or area transition door into an area that exists in the single-player campaign) there are two different ways to do it. One is to override the existing area with a new area of your own design that duplicates the original with the exception of your additions. This is straightforward to do but can interact poorly with other add-ons - you can only have one version of an area active at a time. '''[To Editor: Edit in a Custom Module or the existing Single Player Campaign Module?]'''&lt;br /&gt;
&lt;br /&gt;
A more elegant and extensible approach is to use a [[PRCSCR]]_-prefixed M2DA. The PRCSCR M2DA has a very simple structure and a simple but profound effect:&lt;br /&gt;
&lt;br /&gt;
*ID - a unique integer identifier for each row&lt;br /&gt;
*AreaListName - a string that identifies a specific area list, or the special keyword &amp;quot;any&amp;quot;.&lt;br /&gt;
*Script - the name of a script file.&lt;br /&gt;
&lt;br /&gt;
Whenever a player enters an area in an area list in this M2DA the associated script will be run. A modder can therefore include a script with his mod that will be run when the player enters an existing area that he didn't create. This script can freely add or remove placeables and creatures and perform whatever other modifications to the area that a script is capable of doing.&lt;br /&gt;
&lt;br /&gt;
Note that the script will be run every time the player enters the area, so you'll want to have an associated plot flag to ensure that the changes are only made once.&lt;br /&gt;
&lt;br /&gt;
The following example is a script that adds a new character from an add-on module to an existing area in the main game:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// this is the name of a precreated plot file &amp;quot;joblos_quest&amp;quot; prefixed with the special &amp;quot;plt_&amp;quot;&lt;br /&gt;
// &amp;quot;plt_&amp;quot; + quest name allows you to reference the flag names as constants.&lt;br /&gt;
#include &amp;quot;plt_joblos_quest&amp;quot; &lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    //Check whether we've added Joblo already.&lt;br /&gt;
    if (WR_GetPlotFlag(PLT_JOBLOS_QUEST, JOBLO_ADDED_TO_TOWN) == FALSE)&lt;br /&gt;
    {&lt;br /&gt;
        object oTown = GetObjectByTag(&amp;quot;lot100ar_lothering&amp;quot;); //An area's tag is the same as its resource name&lt;br /&gt;
        vector vJobloLocation = Vector(126.745f, 120.724f, 0.460568f); // See below for how to get these coordinates&lt;br /&gt;
&lt;br /&gt;
        CreateObject(&lt;br /&gt;
            OBJECT_TYPE_CREATURE,&lt;br /&gt;
            R&amp;quot;joblo.utc&amp;quot;,&lt;br /&gt;
            Location(oTown, vJobloLocation, 180.0f); //See below for how to get the value for orientation&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
        WR_SetPlotFlag(&amp;quot;joblos_quest&amp;quot;, JOBLO_ADDED_TO_TOWN, TRUE);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since you can't add [[waypoint]]s to an existing area you'll need to enter the position and orientation values for the target location manually. You can find them by creating a local copy of the area in question and temporarily adding a waypoint to copy down the coordinates and orientation you'll need.&lt;br /&gt;
&lt;br /&gt;
== Move Inventory (e.g. remove and store player's equipment) ==&lt;br /&gt;
&lt;br /&gt;
Here's a fairly general function for moving items from one creature / placeable to another.&lt;br /&gt;
&lt;br /&gt;
Applications might include&lt;br /&gt;
&lt;br /&gt;
 * Moving a player's equipped items, inventory and money to a chest while they are in jail (with an option to prevent them being naked).&lt;br /&gt;
 * Replacing an NPC's equipment with a new set from a nearby invisible placeable.&lt;br /&gt;
 * Removing all items from an NPC except their equipment. &lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
  const int ITEM_TYPE_AMMO = 7;&lt;br /&gt;
/**&lt;br /&gt;
* @brief Move inventory from one object to another&lt;br /&gt;
*&lt;br /&gt;
* @param oSource         - object to move inventory from&lt;br /&gt;
* @param oTarget         - object to move inventory to&lt;br /&gt;
* @param bUnequipSource  - TRUE if any items that the source has equipped should be moved&lt;br /&gt;
* @param bEquipTarget    - TRUE if target should equip items received if possible&lt;br /&gt;
* @param bRemoveClothing - TRUE if chest slot should be unequipped when bUnequipSource is TRUE&lt;br /&gt;
* @param bMoveMoney      - TRUE if creature money should move from source to target&lt;br /&gt;
*&lt;br /&gt;
* The target will acquire the items even if its maximum inventory is exceeded.&lt;br /&gt;
* If the source contains more than one item for an inventory slot, the outcome of equipping&lt;br /&gt;
* on the target is unpredictable.&lt;br /&gt;
* If money is moved from a creature to a placeable, money items are created.&lt;br /&gt;
*&lt;br /&gt;
* @returns void&lt;br /&gt;
**/&lt;br /&gt;
void zzzMoveInventory(object oSource, object oTarget, int bUnequipSource=FALSE, int bEquipTarget=FALSE,&lt;br /&gt;
                      int bRemoveClothing=FALSE, int bMoveMoney=FALSE);&lt;br /&gt;
void zzzMoveInventory(object oSource, object oTarget, int bUnequipSource=FALSE, int bEquipTarget=FALSE,&lt;br /&gt;
                      int bRemoveClothing=FALSE, int bMoveMoney=FALSE)&lt;br /&gt;
{&lt;br /&gt;
  object [] oItemTable;&lt;br /&gt;
  object    oClothing       = OBJECT_INVALID;&lt;br /&gt;
  object    oItem;&lt;br /&gt;
  int       nItemCount;&lt;br /&gt;
  int       nGetItemsOption = GET_ITEMS_OPTION_BACKPACK;&lt;br /&gt;
  int       nMoney;&lt;br /&gt;
  int       nStack;&lt;br /&gt;
  object    oMoney;&lt;br /&gt;
  int       i               = -1;&lt;br /&gt;
&lt;br /&gt;
  if (bUnequipSource) nGetItemsOption = GET_ITEMS_OPTION_ALL;&lt;br /&gt;
&lt;br /&gt;
  if (GetObjectType(oSource) == OBJECT_TYPE_CREATURE)&lt;br /&gt;
    if (!bRemoveClothing)&lt;br /&gt;
      oClothing = GetItemInEquipSlot(INVENTORY_SLOT_CHEST, oSource);&lt;br /&gt;
&lt;br /&gt;
  oItemTable = GetItemsInInventory(oSource, nGetItemsOption);&lt;br /&gt;
  nItemCount = GetArraySize(oItemTable);&lt;br /&gt;
&lt;br /&gt;
  while (++i &amp;lt; nItemCount)&lt;br /&gt;
    {&lt;br /&gt;
      oItem = oItemTable[i];&lt;br /&gt;
&lt;br /&gt;
      if (oItem != oClothing)&lt;br /&gt;
      {&lt;br /&gt;
        MoveItem(oSource, oTarget, oItem);&lt;br /&gt;
&lt;br /&gt;
        if (bEquipTarget &amp;amp;&amp;amp; (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE))&lt;br /&gt;
          switch(GetItemType(oItem))&lt;br /&gt;
            {&lt;br /&gt;
              case ITEM_TYPE_WEAPON_RANGED:&lt;br /&gt;
                {EquipItem(oTarget, oItem, INVENTORY_SLOT_MAIN, 1); break;}&lt;br /&gt;
              case ITEM_TYPE_WEAPON_MELEE:&lt;br /&gt;
                {EquipItem(oTarget, oItem, INVENTORY_SLOT_MAIN, 0); break;}&lt;br /&gt;
              case ITEM_TYPE_SHIELD:&lt;br /&gt;
                {EquipItem(oTarget, oItem, INVENTORY_SLOT_OFFHAND, 0); break;}&lt;br /&gt;
              case ITEM_TYPE_AMMO:&lt;br /&gt;
                {EquipItem(oTarget, oItem, INVENTORY_SLOT_RANGEDAMMO, 1); break;}&lt;br /&gt;
              default : EquipItem(oTarget, oItem);&lt;br /&gt;
             } &lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
  if (bMoveMoney)&lt;br /&gt;
    {&lt;br /&gt;
      nMoney = GetCreatureMoney(oSource);&lt;br /&gt;
&lt;br /&gt;
      if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE)&lt;br /&gt;
        AddCreatureMoney(nMoney, oTarget);&lt;br /&gt;
      else&lt;br /&gt;
        while (nMoney)&lt;br /&gt;
          {&lt;br /&gt;
            oMoney = CreateItemOnObject(R&amp;quot;gen_im_copper.uti&amp;quot;, oTarget, 1, &amp;quot;&amp;quot;, TRUE);&lt;br /&gt;
            nStack = GetMaxItemStackSize(oMoney);&lt;br /&gt;
            if (nStack &amp;gt; nMoney) nStack = nMoney;&lt;br /&gt;
            SetItemStackSize(oMoney, nStack);&lt;br /&gt;
            nMoney -= nStack;&lt;br /&gt;
          }&lt;br /&gt;
      SetCreatureMoney(0, oSource);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create a lootable placeable that vanishes when looted ==&lt;br /&gt;
&lt;br /&gt;
For a player-usable placeable, use the following event script to make it give its contents to the player and then vanish when clicked on.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&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_USE:&lt;br /&gt;
        {&lt;br /&gt;
            //MoveAllItems(OBJECT_SELF, GetHero());&lt;br /&gt;
            AddCreatureMoney (1000000, GetHero(), TRUE);&lt;br /&gt;
            Safe_Destroy_Object(OBJECT_SELF);&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wanted to use standard resources you could achieve the same thing (though not destroying the placeable) simply by adding &amp;quot;_autoloot&amp;quot; to the end of the placeable's tag.&lt;br /&gt;
&lt;br /&gt;
== Move the player to a new area after a cutscene plays ==&lt;br /&gt;
&lt;br /&gt;
Stand-alone cutscenes have an &amp;quot;end script&amp;quot; parameter that sets a script to run once the cutscene ends. Use a script such as the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   DoAreaTransition(&amp;quot;destination_area_tag&amp;quot;, &amp;quot;destination_waypoint_tag&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Override Events (e.g. those in player_core) ==&lt;br /&gt;
&lt;br /&gt;
Look here: [[Event override]]&lt;br /&gt;
&lt;br /&gt;
{{Languages}}&lt;br /&gt;
[[category:tutorials]]&lt;br /&gt;
[[Category:Scripts]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Treasure_system&amp;diff=16148</id>
		<title>Treasure system</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Treasure_system&amp;diff=16148"/>
				<updated>2011-05-22T07:09:05Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Overrides */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Treasure System only works on creatures and placeable containers (not bags). Creatures will fire the Treasure System when they die, and placeables will fire it when they spawn.&lt;br /&gt;
&lt;br /&gt;
There are 2 specific pieces of information that the Treasure System uses to determine what treasure an object drops. The first piece of information is the combat Rank of the object. Placeables are never involved in combat, but will have to have something entered in the field for the system to work. A Lieutenant-ranked chest will drop treasure equivalent to a Lieutenant-ranked creature. Rank determines the quantity and quality of the treasure dropped. The second piece of information is the Treasure Category of the object. This determines what set of treasure tables the system will look at for this object.&lt;br /&gt;
&lt;br /&gt;
If either the Rank or Treasure Category is set to Invalid (value 0), the Treasure System will not drop anything. Items placed manually on the object will appear normally.&lt;br /&gt;
&lt;br /&gt;
If there doesn't seem to be a treasure table that applies to a specific object, contact the designer in charge of the system to get a new table added.&lt;br /&gt;
&lt;br /&gt;
== Overrides ==&lt;br /&gt;
&lt;br /&gt;
There are a number of override variables on objects that will change the way the Treasure System functions. For each of these variables, a value less than 0 turns off that part of the system, a value of 0 ignores the override, and a value greater than 0 uses that value instead of the one on the creature. Each variable has a short explanation of what overriding does.&lt;br /&gt;
&lt;br /&gt;
{{variable table start}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_CATEGORY |int|0| A value here directly relates to ID values in the TS_Category 2DA.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_EQUIPMENT |float|0| A value here determines the chance of any particular piece of equipped items dropping. Set this to a negative number to prevent the treasure system from using the default value from the auto scaling table.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_HIGH|float|0| high chance }}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_ITEM|float|0| item chance }}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_MONEY |int|0| A value here overrides the TS_MoneyValue value in the autoscale 2DA.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_RANK |int|0| A value here directly relates to ID values in the autoscale 2DA.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_REACTIVE|float|0|Reactive chance, only present in the creature variable table{{undocumented}} }}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_SCALING |int|0| A value here has no additional effect. This is currently only useful to turn off scaling.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_STEALING |int|0| A value here directly relates to ID values in the TS_Stealing 2DA.}}&lt;br /&gt;
{{variable table row|TS_TREASURE_GENERATED|int|0| A value of -1 here ensures that there is never any treasure, period.}}&lt;br /&gt;
{{variable table end}}&lt;br /&gt;
&lt;br /&gt;
== Stealing ==&lt;br /&gt;
&lt;br /&gt;
Stealing from a creature functions the same as a normal treasure drop, except the loot is only ever a single Minor Item. No Money or Major Items will be dropped.&lt;br /&gt;
&lt;br /&gt;
The TS_OVERRIDE_STEALING variable allows special functionality to be added when a creature is stolen from. A value placed in the override is actually an ID lookup in the TS_Stealing 2DA. When that creature is stolen from (and a creature can normally only be successfully stolen from once), it gets the item resource referenced by that ID and adds it to the treasure gained from stealing.&lt;br /&gt;
&lt;br /&gt;
Stealing from creatures is mostly handled by systems, so there are only a couple places a designer can interact with it. First it will be useful to describe exactly what happens when the Stealing skill is used.&lt;br /&gt;
&lt;br /&gt;
When a character tries to use Stealing on another creature, it checks a variety of factors on the character and the target to determine success. If the target has already been stolen from, the character neither succeeds nor fails. If the character fails, the [[EVENT_TYPE_STEALING_FAILURE]] event is fired on the current area. If the character succeeds, the [[EVENT_TYPE_STEALING_SUCCESS]] event is fired on the current area and the FLAG_STOLEN_FROM variable on the target is set to TRUE. Additionally, a successful use of the Stealing skill causes the Treasure System to generate a single Minor Item on the character using the skill. This requires the target to be properly set up for the Treasure System.&lt;br /&gt;
&lt;br /&gt;
The [[EVENT_TYPE_STEALING_FAILURE]] and [[EVENT_TYPE_STEALING_SUCCESS]] events are intended for use in the Infamy system and will be used in the Stealing Reactivity pass.&lt;br /&gt;
&lt;br /&gt;
The FLAG_STOLEN_FROM variable can be set on a creature manually to allow them to be immune to stealing attempts. This can be used to shield plot characters from the skill, though Stealing won't actually remove any items from their inventory. Additionally, you can set the flag to FALSE through scripting to allow the player to steal from a target more than once. Creatures with this flag set will not fire [[EVENT_TYPE_STEALING_FAILURE]] or [[EVENT_TYPE_STEALING_SUCCESS]] events, so they won't interact with the Infamy system.&lt;br /&gt;
&lt;br /&gt;
=== Specific Items ===&lt;br /&gt;
&lt;br /&gt;
The Treasure System has functionality added to allow you to get specific items when stealing from a character. The TS_OVERRIDE_STEALING variable on creatures allows you to set associate a creature with a specific ID value in the TS_Stealing 2DA. Each ID value references a specific item resource name. When a character with this variable set is stolen from, that specific item resource will be added to the treasure the player receives.&lt;br /&gt;
&lt;br /&gt;
The target does not have to have a valid Rank or Treasure Category for this item to drop. This is so you can drop only the specific item and nothing else.&lt;br /&gt;
&lt;br /&gt;
== TS_System.xls and related 2das ==&lt;br /&gt;
&lt;br /&gt;
See [[TS_System.xls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Creatures]]&lt;br /&gt;
[[Category:Placeables]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Placeable&amp;diff=16147</id>
		<title>Placeable</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Placeable&amp;diff=16147"/>
				<updated>2011-05-22T07:07:12Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Variables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;float:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| {{Resource palette}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Interactive Objects are the objects placed in the designer toolset that the end-user can interact with. They are also known as placeable objects.&lt;br /&gt;
&lt;br /&gt;
Designers place interactive objects in area using the Area Editor.  Placeable and trigger templates must be created prior to being placed in an area.  In the toolset, doors are considered to be just another form of placeables.&lt;br /&gt;
&lt;br /&gt;
Interactive objects are placed in the Area Editor of the Designer toolest. They can be interacted with by the player in-game.&lt;br /&gt;
&lt;br /&gt;
Like all objects, interactive objects receive only one [[Event (dascript type)|event]]. Information encoded in this event can be used to determine if this is a default action or a secondary action (for example, determining whether the player is picking the placeable's lock or simply bashing it open).&lt;br /&gt;
&lt;br /&gt;
== Locked Objects ==&lt;br /&gt;
&lt;br /&gt;
Any interactive object can be locked (though generally it only makes sense to do so with containers and doors). If the character's lockpicking skill is higher than the lock, the lock is opened.&lt;br /&gt;
&lt;br /&gt;
Interactive objects cannot be trapped in the manner that Neverwinter objects were trapped (i.e., no trapped chests or doors). Instead, a placeable object can be set as the trigger for an associated trap object; Dragon Age generally does this via floor plates that trigger when stepped on.&lt;br /&gt;
&lt;br /&gt;
== Destroying Objects ==&lt;br /&gt;
&lt;br /&gt;
All interactive objects need a destroyed animation. If a container is destroyed the contents of its inventory are transferred to a Bodybag. Some of the items may be destroyed (scripting determines the chance of this).&lt;br /&gt;
&lt;br /&gt;
== Types of Interactive Objects ==&lt;br /&gt;
&lt;br /&gt;
The function that a placeable performs when interacted with is defined by its appearance, as listed in [[Placeables.xls]].&lt;br /&gt;
&lt;br /&gt;
=== Doors ===&lt;br /&gt;
Doors can be opened and closed by the player. They restrict access between portions of an area.&lt;br /&gt;
* Examples: Door, Cage Door, Secret door&lt;br /&gt;
* Default Action: When a character clicks on the door it opens with an animation.&lt;br /&gt;
* Secondary Action: The character attacks the door with his equipped weapon&lt;br /&gt;
* Doors are special and get [[Door|their own page]] describing additional details.&lt;br /&gt;
=== Trigger-Animating ===&lt;br /&gt;
These are items that a player clicks on to activate something elsewhere on a level. Usually this means a locked or secret door somewhere on the level, though sometimes it might summon a monster or sound the alarm for the entire level.&lt;br /&gt;
* Examples: Lever, gong, turning wheel.  &lt;br /&gt;
* Default Action: When a character clicks on the object, it plays an animation and an effect. The effect can be a script, a sound, a spell or a combination.  &lt;br /&gt;
* Secondary Action: The character attacks the object with his equipped weapon.&lt;br /&gt;
=== Container-Animating ===&lt;br /&gt;
These are common containers where a player can find treasure. These objects play a simple ‘open’ animation when left clicked. &lt;br /&gt;
* Examples: Chest, Armoire, Safe.  &lt;br /&gt;
* Default Action: An open animation is played. The container’s inventory is shown on a GUI. If the container is locked, then the character’s lock picking skill is compared against the lock’s complexity.  &lt;br /&gt;
* Secondary Action: The character attacks the container with his equipped weapon.&lt;br /&gt;
=== Container-Static ===&lt;br /&gt;
These are common containers where a player can find treasure. These containers have no ‘open’ animation.  &lt;br /&gt;
* Examples: Bookshelf, bush (with material components), corpse.  &lt;br /&gt;
* Default Action: The container’s inventory is shown on a GUI. Static containers cannot be locked.  &lt;br /&gt;
* Secondary Action: The character attacks the container with his equipped weapon.&lt;br /&gt;
=== Cage ===&lt;br /&gt;
These are cages where animals or prisoners are kept. Players can release prisoners as an act of good will or simply to interrogate them for information. Animals can be released to act as temporary allies.  &lt;br /&gt;
*Examples: Animal cage, gaol.  &lt;br /&gt;
*Default Action: An open animation is played. If the cage is locked, then the character’s lock picking skill is compared against the lock’s complexity.  &lt;br /&gt;
*Secondary Action: The character attacks the cage with his equipped weapon.&lt;br /&gt;
=== Informational ===&lt;br /&gt;
These are notes or signs that a player can click on to learn important information about the game. They range from simply location signs to notes giving information about a plot. &lt;br /&gt;
*Examples: Road sign, note on wall.  &lt;br /&gt;
*Default Action: A GUI pops up displaying the text of the message.  &lt;br /&gt;
*Secondary Action: Nothing happens.&lt;br /&gt;
=== Selectable Trap ===&lt;br /&gt;
These are traps that originate from visible (and thus selectable and destroyable) objects. They can also can be disarmed by disarming their floor trigger - i.e., sinking floor piece - (see Trap Triggers). &lt;br /&gt;
*Examples: Archer statue that fires arrows (after player steps on floor piece). Dragon statue that breathes fire(after player steps on floor piece).   &lt;br /&gt;
*Default Action: Trap triggers, targeting the character that selected it.  &lt;br /&gt;
*Secondary Action: The character attacks the trap with his equipped weapon.&lt;br /&gt;
=== Non-Selectable Trap ===&lt;br /&gt;
These are hidden traps that spring from the walls, floor or ceiling. These traps cannot be selected or destroyed directly BUT they can be disarmed by disarming their floor trigger - i.e., sinking floor piece - (see Trap Triggers). &lt;br /&gt;
*Examples: Pendulum blade, scything blade.   &lt;br /&gt;
*Default Action: Cannot target trap.  &lt;br /&gt;
*Secondary Action: Cannot target trap.&lt;br /&gt;
=== Trap Trigger ===&lt;br /&gt;
All traps need to be associated with a floor trigger. When a character walks over a floor trigger, the trap will activate. If two or more characters are selected, the one with the highest trap skill is the one that moves to disarm the trap.&lt;br /&gt;
*Examples: Sinking floor piece.   &lt;br /&gt;
*Default Action: If the character has the ‘Traps’ skill, then he plays a ‘disarm’ animation and his skill is compared against the difficulty of the trap. Characters without the traps skill cannot select the trap trigger.   &lt;br /&gt;
*Secondary Action: The character attacks the trigger with his equipped weapon. This triggers the trap.&lt;br /&gt;
=== Area Effect Item/Informational ===&lt;br /&gt;
These are objects that a character can attack, triggering an event that has an immediate effect on the battlefield. When a character attacks one of these objects, the object usually falls over and deals damage to any creature in its area of effect. If a player just left clicks on one of these objects, he will receive a text message.   &lt;br /&gt;
*Examples: Weakened pillar (pillar collapses into rubble), old rotting tree (tree falls over), chandelier (rope is cut, chandelier smashes into floor and vanishes), marble statue (statue tips over), window (window smashes, leaving glass all over floor), boulder (rolls along preset path).   &lt;br /&gt;
*Default Action: A GUI pops up displaying the text of a message.   &lt;br /&gt;
*Secondary Action: The character attacks the trigger with his equipped weapon. If the player has the appropriate strength, then the item plays its ‘area effect damage’ animation.&lt;br /&gt;
=== Area Effect Item/Container ===&lt;br /&gt;
These These are objects that a character can attack, triggering an event that has an immediate effect on the battlefield. When a character attacks one of these objects, the object usually falls over and deals damage to any creature in its area of effect. If a player just left clicks on one of these objects, it will act as a container.   &lt;br /&gt;
*Examples: Bag of flour (explodes into cloud of flour), wagon with barrels (wagon tips and barrels spill over floor), bookcase (bookcase tips over).   &lt;br /&gt;
*Default Action: The container’s inventory is shown on a GUI.   &lt;br /&gt;
*Secondary Action: The character attacks the trigger with his equipped weapon. If the player has the appropriate strength, then the item plays its ‘area effect damage’ animation.&lt;br /&gt;
=== Furniture ===&lt;br /&gt;
Characters can either sit down or lie down on these objects. &lt;br /&gt;
*Examples: Chair, couch, bed, bench.   &lt;br /&gt;
*Default Action: The character either sits down or lies down on the furniture object. As soon as the player clicks to move, he will stand up.  &lt;br /&gt;
*Secondary Action: The character attacks the object with his equipped weapon.&lt;br /&gt;
=== Puzzle ===&lt;br /&gt;
The player clicks and triggers an interactive dialog with the object &lt;br /&gt;
*Examples: any puzzle object.   &lt;br /&gt;
*Default Action: Trigger dialog.  &lt;br /&gt;
*Secondary Action: The character attacks the object with his equipped weapon.&lt;br /&gt;
=== Area Transition ===&lt;br /&gt;
These are visible or invisible objects used to transition between areas.&lt;br /&gt;
*Examples: Large Gate  &lt;br /&gt;
*Default Action: Transition into destination area.  &lt;br /&gt;
*Secondary Action: Nothing happens.&lt;br /&gt;
&lt;br /&gt;
== How will designers assign appearances to interactive objects? ==&lt;br /&gt;
*This will be done through the Toolset appearance field. It refers placeables.2da&lt;br /&gt;
*Each placeable has a Type.&lt;br /&gt;
*Each TYPE corresponds to an Animation State Type (example, the AnimCnt_Door sheet in placeables.2da controls the door states). This controls the type of animations available to this object. There should be 10-15 types or so&lt;br /&gt;
**Death&lt;br /&gt;
**Damaged&lt;br /&gt;
**Normal State&lt;br /&gt;
**Others...&lt;br /&gt;
*Each Animation State Type refers to a list of animations in the Animations 2da ([[ANIM_Placeables.xls]])&lt;br /&gt;
&lt;br /&gt;
== How will battle-field damage work? ==&lt;br /&gt;
*Interactive Objects will not have DECALS or BATTLE-SCARING. &lt;br /&gt;
*Interactive Objects will have a Damage state, in addition to the Death state that they all have. Example damage states:&lt;br /&gt;
**A chest might have a chunk of wood taken out of its front&lt;br /&gt;
**A cask of ale might start leaking ale&lt;br /&gt;
&lt;br /&gt;
== Use Points ==&lt;br /&gt;
Objects will have use points to indicate where people using them stand. There will be multiple use points on an object.&lt;br /&gt;
&lt;br /&gt;
Use points will need to be activated relative to what state they are in (i.e., an overturned pillar will have different action points than an upright pillar).&lt;br /&gt;
&lt;br /&gt;
Use points may also need to be labeled and are activated relative to a players position. This seems likely how are doors will work. Since we decided that doors in Dragon Age will function like real-world doors, they will always open in the same direction every time. This means that the use point I use is NOT relative to the state, but instead to the position of the character. We might need use points labeled.&lt;br /&gt;
&lt;br /&gt;
This system will probably also be used by creatures (a dragon might have Front-Claw Use Point, Tail Use Point et cetera)&lt;br /&gt;
&lt;br /&gt;
== How Will Sitting and Sleeping Work? ==&lt;br /&gt;
* All things that can be sat on will need a consistent Height and Width&lt;br /&gt;
* All things that can be slept on will need a consistent Height and Width&lt;br /&gt;
* Animals will not be able to sit or sleep on anything&lt;br /&gt;
* Animation will create sit &amp;amp; sleep animations for Elves, Dwarves, Humans&lt;br /&gt;
* The player can’t sit —  only ambient NPCs.&lt;br /&gt;
&lt;br /&gt;
The current planned interactive object animation system should be able to handle the &amp;quot;sitting&amp;quot; and &amp;quot;lying down&amp;quot;  of creatures.&lt;br /&gt;
&lt;br /&gt;
== What happens if no animations exist for an action? ==&lt;br /&gt;
Example: E.g A creature uses an object for which there is no proper animation, like a Dog opens a chest.&lt;br /&gt;
&lt;br /&gt;
The chest will still open but if no animations were created to show Dog opening the chest, none will play.&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
&lt;br /&gt;
For var_placeable:&lt;br /&gt;
&lt;br /&gt;
{{variable table start}}&lt;br /&gt;
{{variable table row| PLC_AT_DEST_AREA_TAG | string |none| resource name of an area transition door's destination area}}&lt;br /&gt;
{{variable table row| PLC_AT_DEST_TAG | string |none| resource name of the waypoint within that area to send the PC to. }}&lt;br /&gt;
{{variable table row|PLC_AT_WORLD_MAP_ACTIVE_1 to 5 | string |none| resource name of pins on the world map that should be made active when the player uses this area transition to reach the world map. }}&lt;br /&gt;
{{variable table row|PLC_CODEX_FLAG | int | -1 | Flag within the CODEX_PLOT plot that is set when this placeable is examined. }}&lt;br /&gt;
{{variable table row|PLC_CODEX_PLOT | string |none| resource name of a plot containing a codex page that is given to the player when this placeable is examined. }}&lt;br /&gt;
{{variable table row|PLC_COUNTER_1 to 3 | int |0| generic counter variables }}&lt;br /&gt;
{{variable table row|PLC_DO_ONCE_A and B | int |0| flags for behaviors that happen only once }}&lt;br /&gt;
{{variable table row|PLC_FLIP_COVER_USE_COUNT | int |0| Flip cover has been removed from the default ruleset }}&lt;br /&gt;
{{variable table row|PLC_SPAWN_NON_INTERACTIVE | int |0| }}&lt;br /&gt;
{{variable table row|PLC_TRAP_* | || see [[Trap system]] }}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_* | || See [[Treasure system]] }}&lt;br /&gt;
{{variable table row|TS_TREASURE_GENERATED | int || See [[Treasure system]]  }}&lt;br /&gt;
{{variable table end}}&lt;br /&gt;
&lt;br /&gt;
If you use the var_placeable_react 2da instead, the above variables are all included and the following are added:&lt;br /&gt;
&lt;br /&gt;
{{variable table start}}&lt;br /&gt;
{{variable table row|PLC_REACT_DESTROY_SET_FLAG | int || When placeable is destroyed set this flag }}&lt;br /&gt;
{{variable table row|PLC_REACT_DESTROY_SET_PLOT | string ||  When placeable is destroyed set this plot}}&lt;br /&gt;
{{variable table row|PLC_REACT_INVENTORY_REMOVED_SET_FLAG | int || When the PC takes something from the placeable fire this flag}}&lt;br /&gt;
{{variable table row|PLC_REACT_INVENTORY_REMOVED_SET_PLOT | string || When the PC takes something from the placeable fire this plot}}&lt;br /&gt;
{{variable table row|PLC_REACT_OVERRIDE_USE_BEHAVIOR | int |0| Makes it so what's supposed to happen when you use the placeable doesn't happen (e.g. a door doesn't open)}}&lt;br /&gt;
{{variable table row|PLC_REACT_REPEAT | int | 1 | Whether or not the placeable reaction script will fire multiple times (default to TRUE)}}&lt;br /&gt;
{{variable table row|PLC_REACT_USE_SET_FLAG | int |0| When placeable is used fire this flag}}&lt;br /&gt;
{{variable table row|PLC_REACT_USE_SET_PLOT | string || When placeable is used fire this plot}}&lt;br /&gt;
{{variable table end}}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
&lt;br /&gt;
{{inspector start}}&lt;br /&gt;
{{inspector section|General}}&lt;br /&gt;
{{inspector row|Appearance| Appearance type for the placeable }}&lt;br /&gt;
{{inspector row|Character| One or more placeables can be mapped to a single character. }}&lt;br /&gt;
{{inspector row|Comments| General information about this placeable. }}&lt;br /&gt;
{{inspector row|Conversation| Default conversation resource for this placeable. }}&lt;br /&gt;
{{inspector row|Group| The placeable's group as specified in groups.2da. Each group can be either hostile or non-hostile towards each other. }}&lt;br /&gt;
{{inspector row|Name| Name of the placeable as seen in the game. }}&lt;br /&gt;
{{inspector row|NameRequiresReTranslation| A true/false flag used during game development for [[localization]] work }}&lt;br /&gt;
{{inspector row|Plot| True/false, if true the placeable cannot be damaged or affected by any hostile effect. }}&lt;br /&gt;
{{inspector row|PopupText| {{undocumented}} }}&lt;br /&gt;
{{inspector row|PopupTextRequiresReTranslation| A true/false flag used during game development for [[localization]] work }}&lt;br /&gt;
{{inspector row|Rank| Placeables are never involved in combat, but their combat rank is still used by the [[treasure system]] when generating treasure. }}&lt;br /&gt;
{{inspector row|Resource Name| A unique string identifier the tooleset and the game both use to refer to this resource. }}&lt;br /&gt;
{{inspector row|Script| Event script assigned to the resource. }}&lt;br /&gt;
{{inspector row|Tag| A non-unique string identifier used mostly by scripts and other resources to refer to this resource. }}&lt;br /&gt;
{{inspector row|Team| Numeric identifier of the team the placeable belongs to. Team numbers are often used in scripting. }}&lt;br /&gt;
{{inspector row|Treasure Category| Determines what variety of treasure is generated by the [[treasure system]] }}&lt;br /&gt;
{{inspector row|Variable 2da| Allows selecting a variable table. Only the values in this table can be set and retrieved by scripting. }}&lt;br /&gt;
{{inspector row|Variables| Displays the table selected in the &amp;quot;Variable 2da&amp;quot; field. Allows setting initial states for parameters. }}&lt;br /&gt;
&lt;br /&gt;
{{inspector section|Key}}&lt;br /&gt;
{{inspector row|Auto Remove Key| Sets whether the game will remove a key from inventory once used to open this placeable. }}&lt;br /&gt;
{{inspector row|Key Required| Sets whether or not a key is the only way to open this placeable }}&lt;br /&gt;
{{inspector row|Key Tag| The tag of the key needed to open this placeable }}&lt;br /&gt;
&lt;br /&gt;
{{inspector section|Sound}}&lt;br /&gt;
{{inspector row|Close to Open Sound| Sound emitted when the object changes from a closed state to an opened state }}&lt;br /&gt;
{{inspector row|Destroyed Sound| Sound emitted when the object is destroyed }}&lt;br /&gt;
{{inspector row|Hit Sound| Sound emitted when the object is hit for damage }}&lt;br /&gt;
{{inspector row|Locked Sound| Sound emitted when an attempt is made to open a locked object }}&lt;br /&gt;
{{inspector row|Open to Close Sound| Sound emitted when the object changes from an opened to a closed state. }}&lt;br /&gt;
{{inspector row|Used Sound| Sound emitted when the object is &amp;quot;used&amp;quot; (generically). }}&lt;br /&gt;
&lt;br /&gt;
{{inspector section|Stats}}&lt;br /&gt;
{{inspector row|Health| Amount of health the placeable currently has}}&lt;br /&gt;
{{inspector row|Initial State| The animation state the placeable will be in when first spawned. }}&lt;br /&gt;
{{inspector row|Interactive| Sets whether or not this placeable can be clicked on during the game. }}&lt;br /&gt;
{{inspector row|Inventory List| Opens the inventory panel and enables user to assign items to the placeable's inventory }}&lt;br /&gt;
{{inspector row|Max Health| The maximum amount of health this placeable can have.}}&lt;br /&gt;
{{inspector row|Pick Lock Level| The difficulty level to pick the lock }}&lt;br /&gt;
&lt;br /&gt;
{{inspector section|Trap}}&lt;br /&gt;
{{inspector row|Is Trapped| Sets whether or not a trap trigger is linked to this placeable }}&lt;br /&gt;
{{inspector row|Trap Detection Difficulty| Sets the skill level required to detect this trap. }}&lt;br /&gt;
{{inspector row|Trap Disarm Difficulty| Sets the skill level required to disarm this trap. }}&lt;br /&gt;
&lt;br /&gt;
{{inspector end}}&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
*[[Chanter's board]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Placeables]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Treasure_system&amp;diff=16146</id>
		<title>Treasure system</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Treasure_system&amp;diff=16146"/>
				<updated>2011-05-22T07:03:04Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Overrides */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Treasure System only works on creatures and placeable containers (not bags). Creatures will fire the Treasure System when they die, and placeables will fire it when they spawn.&lt;br /&gt;
&lt;br /&gt;
There are 2 specific pieces of information that the Treasure System uses to determine what treasure an object drops. The first piece of information is the combat Rank of the object. Placeables are never involved in combat, but will have to have something entered in the field for the system to work. A Lieutenant-ranked chest will drop treasure equivalent to a Lieutenant-ranked creature. Rank determines the quantity and quality of the treasure dropped. The second piece of information is the Treasure Category of the object. This determines what set of treasure tables the system will look at for this object.&lt;br /&gt;
&lt;br /&gt;
If either the Rank or Treasure Category is set to Invalid (value 0), the Treasure System will not drop anything. Items placed manually on the object will appear normally.&lt;br /&gt;
&lt;br /&gt;
If there doesn't seem to be a treasure table that applies to a specific object, contact the designer in charge of the system to get a new table added.&lt;br /&gt;
&lt;br /&gt;
== Overrides ==&lt;br /&gt;
&lt;br /&gt;
There are a number of override variables on objects that will change the way the Treasure System functions. For each of these variables, a value less than 0 turns off that part of the system, a value of 0 ignores the override, and a value greater than 0 uses that value instead of the one on the creature. Each variable has a short explanation of what overriding does.&lt;br /&gt;
&lt;br /&gt;
{{variable table start}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_CATEGORY |int|0| A value here directly relates to ID values in the TS_Category 2DA.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_EQUIPMENT |float|0| A value here determines the chance of any particular piece of equipped items dropping. Set this to a negative number to prevent the treasure system from using the default value from the auto scaling table.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_HIGH|float|0| high chance }}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_ITEM|float|0| item chance }}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_MONEY |int|0| A value here overrides the TS_MoneyValue value in the autoscale 2DA.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_RANK |int|0| A value here directly relates to ID values in the autoscale 2DA.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_REACTIVE|float|0|Reactive chance, only present in the creature variable table{{undocumented}} }}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_SCALING |int|0| A value here has no additional effect. This is currently only useful to turn off scaling.}}&lt;br /&gt;
{{variable table row|TS_OVERRIDE_STEALING |int|0| A value here directly relates to ID values in the TS_Stealing 2DA.}}&lt;br /&gt;
{{variable table row|TS_TREASURE_GENERATED|int|0| A value here ensures the creature never has any treasure, period.}}&lt;br /&gt;
{{variable table end}}&lt;br /&gt;
&lt;br /&gt;
== Stealing ==&lt;br /&gt;
&lt;br /&gt;
Stealing from a creature functions the same as a normal treasure drop, except the loot is only ever a single Minor Item. No Money or Major Items will be dropped.&lt;br /&gt;
&lt;br /&gt;
The TS_OVERRIDE_STEALING variable allows special functionality to be added when a creature is stolen from. A value placed in the override is actually an ID lookup in the TS_Stealing 2DA. When that creature is stolen from (and a creature can normally only be successfully stolen from once), it gets the item resource referenced by that ID and adds it to the treasure gained from stealing.&lt;br /&gt;
&lt;br /&gt;
Stealing from creatures is mostly handled by systems, so there are only a couple places a designer can interact with it. First it will be useful to describe exactly what happens when the Stealing skill is used.&lt;br /&gt;
&lt;br /&gt;
When a character tries to use Stealing on another creature, it checks a variety of factors on the character and the target to determine success. If the target has already been stolen from, the character neither succeeds nor fails. If the character fails, the [[EVENT_TYPE_STEALING_FAILURE]] event is fired on the current area. If the character succeeds, the [[EVENT_TYPE_STEALING_SUCCESS]] event is fired on the current area and the FLAG_STOLEN_FROM variable on the target is set to TRUE. Additionally, a successful use of the Stealing skill causes the Treasure System to generate a single Minor Item on the character using the skill. This requires the target to be properly set up for the Treasure System.&lt;br /&gt;
&lt;br /&gt;
The [[EVENT_TYPE_STEALING_FAILURE]] and [[EVENT_TYPE_STEALING_SUCCESS]] events are intended for use in the Infamy system and will be used in the Stealing Reactivity pass.&lt;br /&gt;
&lt;br /&gt;
The FLAG_STOLEN_FROM variable can be set on a creature manually to allow them to be immune to stealing attempts. This can be used to shield plot characters from the skill, though Stealing won't actually remove any items from their inventory. Additionally, you can set the flag to FALSE through scripting to allow the player to steal from a target more than once. Creatures with this flag set will not fire [[EVENT_TYPE_STEALING_FAILURE]] or [[EVENT_TYPE_STEALING_SUCCESS]] events, so they won't interact with the Infamy system.&lt;br /&gt;
&lt;br /&gt;
=== Specific Items ===&lt;br /&gt;
&lt;br /&gt;
The Treasure System has functionality added to allow you to get specific items when stealing from a character. The TS_OVERRIDE_STEALING variable on creatures allows you to set associate a creature with a specific ID value in the TS_Stealing 2DA. Each ID value references a specific item resource name. When a character with this variable set is stolen from, that specific item resource will be added to the treasure the player receives.&lt;br /&gt;
&lt;br /&gt;
The target does not have to have a valid Rank or Treasure Category for this item to drop. This is so you can drop only the specific item and nothing else.&lt;br /&gt;
&lt;br /&gt;
== TS_System.xls and related 2das ==&lt;br /&gt;
&lt;br /&gt;
See [[TS_System.xls]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Creatures]]&lt;br /&gt;
[[Category:Placeables]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=CommandUnsheatheWeapons&amp;diff=16145</id>
		<title>CommandUnsheatheWeapons</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=CommandUnsheatheWeapons&amp;diff=16145"/>
				<updated>2011-05-20T12:35:42Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{dafunction&lt;br /&gt;
|name=CommandUnsheatheWeapons&lt;br /&gt;
|brief=This function is an unsheathe weapons command constructor.&lt;br /&gt;
|returntype=command&lt;br /&gt;
|returndesc=a valid command&lt;br /&gt;
|sourcefile=script.ldf&lt;br /&gt;
|sourcemodule=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- This section contains the full description from the functions comments. Do not change unless you are confident these are incomplete or incorrect. --&amp;gt;&lt;br /&gt;
Makes the creature executing this command draw its weapons.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
&amp;lt;!-- This section contains additional comments, observations and known issues. --&amp;gt;&lt;br /&gt;
This command doesn't seem to work. It is not used in the OC or core scripts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- == Examples == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains examples transcluded from the snippet library. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- == See also == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains links to articles, functions or constant groups. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Commands functions]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=CommandUnsheatheWeapons&amp;diff=16144</id>
		<title>CommandUnsheatheWeapons</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=CommandUnsheatheWeapons&amp;diff=16144"/>
				<updated>2011-05-20T12:35:04Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Generated}}&lt;br /&gt;
{{dafunction&lt;br /&gt;
|name=CommandUnsheatheWeapons&lt;br /&gt;
|brief=This function is an unsheathe weapons command constructor.&lt;br /&gt;
|returntype=command&lt;br /&gt;
|returndesc=a valid command&lt;br /&gt;
|sourcefile=script.ldf&lt;br /&gt;
|sourcemodule=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- This section contains the full description from the functions comments. Do not change unless you are confident these are incomplete or incorrect. --&amp;gt;&lt;br /&gt;
Makes the creature executing this command draw its weapons.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
&amp;lt;!-- This section contains additional comments, observations and known issues. --&amp;gt;&lt;br /&gt;
This command doesn't seem to work. It is not used in the OC or core scripts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- == Examples == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains examples transcluded from the snippet library. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- == See also == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains links to articles, functions or constant groups. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Commands functions]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Custom_AI&amp;diff=16142</id>
		<title>Custom AI</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Custom_AI&amp;diff=16142"/>
				<updated>2011-05-18T12:53:59Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Custom AI allows the creature's event script to handle the creature's combat activities directly and prevents the usual default combat AI from running for it.&lt;br /&gt;
&lt;br /&gt;
== Custom AI state variable ==&lt;br /&gt;
&lt;br /&gt;
Custom AI is enabled via the AI_CUSTOM_AI_ACTIVE variable in a [[creature]]'s variable table, which also keeps track of the current 'state' the custom AI is in.&lt;br /&gt;
&lt;br /&gt;
When the game completes the [[command]] that a creature is currently executing, a creature whose AI_CUSTOM_AI_ACTIVE variable is set to a non-zero value will be sent an [[EVENT_TYPE_CUSTOM_COMMAND_COMPLETE]] event (older documentation said [[EVENT_TYPE_HANDLE_CUSTOM_AI]], but this doesn't seem to be the case).&lt;br /&gt;
&lt;br /&gt;
The event is sent after rules_core has processed the regular [[EVENT_TYPE_COMMAND_COMPLETE]] event, which may mean that [[Ambient behaviour]] has already issued another command.&lt;br /&gt;
&lt;br /&gt;
These are the available value ranges and predefined constants for AI_CUSTOM_AI_ACTIVE:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0 - 999 ||  Reserved for Basic Custom AI Modes &lt;br /&gt;
|-&lt;br /&gt;
| 1000 - 9999 ||  Free to use for Local Custom AI &lt;br /&gt;
|-&lt;br /&gt;
| 10000 - * ||  Reserved for Global Custom AI &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Basic custom AI modes that have been defined are:&lt;br /&gt;
&lt;br /&gt;
*CAI_DISABLED - Custom AI is disabled (normal AI takes over again)&lt;br /&gt;
*CAI_STASIS - Creature will become dormant and issue no commands&lt;br /&gt;
*CAI_INACTIVE - &lt;br /&gt;
*CAI_INITIATE - A default &amp;quot;starting state&amp;quot; that can be used for initialization.&lt;br /&gt;
&lt;br /&gt;
Global custom AI constants that have been defined are:&lt;br /&gt;
&lt;br /&gt;
*CAI_RUNNER_RUN - used by a creature who flees from the PC in the middle of combat for some reason or another.&lt;br /&gt;
*CAI_USEPLACEABLE_LYRIUM_VEIN&lt;br /&gt;
*CAI_USEPLACEABLE_BALISTA&lt;br /&gt;
&lt;br /&gt;
== Custom AI creature variables ==&lt;br /&gt;
&lt;br /&gt;
The default var_creature variable table has three variables that are intended for use by designers writing custom AI scripts. They are:&lt;br /&gt;
&lt;br /&gt;
{{variable table start}}&lt;br /&gt;
{{variable table row|AI_CUSTOM_AI_VAR_FLOAT | float || A float value that can be used by custom AI scripts for any purpose.}}&lt;br /&gt;
{{variable table row|AI_CUSTOM_AI_VAR_INT | int || An int value that can be used by custom AI scripts for any purpose.}}&lt;br /&gt;
{{variable table row|AI_CUSTOM_AI_VAR_STRING | string || A string value that can be used by custom AI scripts for any purpose}}&lt;br /&gt;
{{variable table end}}&lt;br /&gt;
&lt;br /&gt;
To make using them easier, the following functions are defined:&lt;br /&gt;
&lt;br /&gt;
*CAI_SetCustomAIFloat&lt;br /&gt;
*CAI_SetCustomAIInteger&lt;br /&gt;
*CAI_SetCustomAIString&lt;br /&gt;
*CAI_GetCustomAIFloat&lt;br /&gt;
*CAI_GetCustomAIInteger&lt;br /&gt;
*CAI_GetCustomAIString&lt;br /&gt;
&lt;br /&gt;
== Giving creatures commands ==&lt;br /&gt;
&lt;br /&gt;
It's very important that you ensure that every time the custom AI code is called the creature has a command in its command queue when the code is finished running. If it doesn't, the creature's AI code won't be called again and it will cease performing any actions from that point onward.&lt;br /&gt;
&lt;br /&gt;
The function AI_DetermineCombatRound(); is very useful and important when designing a custom AI. This function issues the creature a &amp;quot;default&amp;quot; command that's based on its capabilities and perceptions. For example, in a monster's custom AI this will generally mean attacking the player in some way.&lt;br /&gt;
&lt;br /&gt;
== Example code with comments ==&lt;br /&gt;
&lt;br /&gt;
Here is the skeleton of a basic [[EVENT_TYPE_HANDLE_CUSTOM_AI]] case for an event script. This code is for an extremely simple custom AI that causes a creature to do nothing except run an animation every five seconds during combat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;cai_h&amp;quot; //Include this file to use custom AI support functions&lt;br /&gt;
&lt;br /&gt;
const int CAI_USER_DEFINED_STATE_ANIMATION = 1000;&lt;br /&gt;
const int CAI_USER_DEFINED_STATE_DELAY = 1001;&lt;br /&gt;
//and so forth - use more descriptive names for your state constants to make the code easier to understand.&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
       case EVENT_TYPE_SPAWN:&lt;br /&gt;
        {&lt;br /&gt;
            //Setting the custom AI to &amp;quot;initiate&amp;quot; means the custom AI will be called&lt;br /&gt;
            //when the creature enters combat. You can use one of your own custom states&lt;br /&gt;
            //as the starting point instead, CAI_INITIATE is only 'special' in that it has&lt;br /&gt;
            //had a constant pre-defined for it already in the core library.&lt;br /&gt;
            CAI_SetCustomAI(OBJECT_SELF, CAI_INITIATE);&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        case EVENT_TYPE_HANDLE_CUSTOM_AI:&lt;br /&gt;
        {&lt;br /&gt;
            // Determine which custom AI state the creature is in.&lt;br /&gt;
            int nCustomAI = CAI_GetCustomAI(OBJECT_SELF);&lt;br /&gt;
&lt;br /&gt;
            Log_Trace(LOG_CHANNEL_TEMP, GetCurrentScriptName(), &amp;quot;Firing custom AI event: &amp;quot; + ToString(nCustomAI));&lt;br /&gt;
&lt;br /&gt;
            //Fall-through for if the custom AI command failed.&lt;br /&gt;
            //This addresses issues with creatures that run appear/disappear animations&lt;br /&gt;
            //when they're made active or inactive.&lt;br /&gt;
            if (GetEventInteger(ev,2)==COMMAND_FAILED)&lt;br /&gt;
            {&lt;br /&gt;
                WR_AddCommand(OBJECT_SELF,CommandWait(0.01f),TRUE);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            switch ( nCustomAI )&lt;br /&gt;
            {&lt;br /&gt;
                case CAI_INITIATE:&lt;br /&gt;
                {&lt;br /&gt;
                    //insert whatever initialization code you need here, and then set the custom&lt;br /&gt;
                    //AI to another state.&lt;br /&gt;
&lt;br /&gt;
                    CAI_SetCustomAI(OBJECT_SELF, CAI_USER_DEFINED_STATE_ANIMATION);&lt;br /&gt;
                    AI_DetermineCombatRound(); //we didn't give the creature a command in this state, so call this to determine a default action.&lt;br /&gt;
                    bActionPerformed = TRUE;&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                case CAI_USER_DEFINED_STATE_ANIMATION:&lt;br /&gt;
                {&lt;br /&gt;
                    //creates a command to play an animation (index is to a row defined in the ANIM_base 2DA)&lt;br /&gt;
                    command cPlayAnim = CommandPlayAnimation(247);&lt;br /&gt;
&lt;br /&gt;
                    //Puts the animation at the front of the creature's command queue.&lt;br /&gt;
                    //Setting it as &amp;quot;static&amp;quot; means nothing will interrupt it, which&lt;br /&gt;
                    //is particularly useful for animations.&lt;br /&gt;
                    WR_AddCommand(OBJECT_SELF, cPlayAnim, TRUE, TRUE);&lt;br /&gt;
&lt;br /&gt;
                    //Set the next state we want to be in&lt;br /&gt;
                    CAI_SetCustomAI(OBJECT_SELF, CAI_USER_DEFINED_STATE_DELAY);&lt;br /&gt;
&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                &lt;br /&gt;
                case CAI_USER_DEFINED_STATE_DELAY:&lt;br /&gt;
                {&lt;br /&gt;
                     AddCommand(OBJECT_SELF, CommandWait(5)); //adds a wait command.&lt;br /&gt;
                     CAI_SetCustomAI(OBJECT_SELF, CAI_USER_DEFINED_STATE_ANIMATION); //we'll do this state next&lt;br /&gt;
                     break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                //Include this default case just in case something weird happens and the custom AI event is&lt;br /&gt;
                //run with an unexpected state.&lt;br /&gt;
                default: AI_DetermineCombatRound();&lt;br /&gt;
&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripts]]&lt;br /&gt;
[[Category:Creatures]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_EVENT_TYPE_CUSTOM_COMMAND_COMPLETE_not_being_handled&amp;diff=16141</id>
		<title>Bug: EVENT TYPE CUSTOM COMMAND COMPLETE not being handled</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_EVENT_TYPE_CUSTOM_COMMAND_COMPLETE_not_being_handled&amp;diff=16141"/>
				<updated>2011-05-18T12:36:49Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Comment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Version found:''' v1.0.1008.0&lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&lt;br /&gt;
== Comment ==&lt;br /&gt;
&lt;br /&gt;
This may be a spurious bug report.&lt;br /&gt;
&lt;br /&gt;
If the AI_CUSTOM_AI_ACTIVE variable on the creature template is set (see [[Custom AI]]), EVENT_TYPE_CUSTOM_COMMAND_COMPLETE is sent to the creature script.&lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16140</id>
		<title>Ambient behaviour</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16140"/>
				<updated>2011-05-18T12:34:59Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Movement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{infobox creature}}&lt;br /&gt;
&lt;br /&gt;
Ambient behaviour begins when the player moves within 50m of a creature and ceases when the player remains more than 50m away for at least 40s. Ambient behaviour alternates between a movement phase and an animation phase, simulating a bubble of activity around the player. In a movement phase, the creature (optionally) moves to a new destination (typically a [[waypoint]] but it could be any object) and turns to face the same direction as the destination object. In an animation phase, the creature (optionally) performs one or more animations either in sequence or at random. Exact behaviour is controlled by local variables set on either the creature instance or template (see table below). All other local variables with the prefix AMBIENT_* are used internally by the ambient behaviour system (see script [[sys_ambient_h]].nss) and should not be manually modified. Never directly modify AMBIENT_* local variables at run time using [[SetLocalInt]] - always use the functions [[Ambient_Start]], [[Ambient_Stop]], [[Ambient_OverrideBehaviour]], and [[Ambient_RestoreBehaviour]] instead. Ambient behaviour is persisted when a game is saved and automatically resumes when a game is loaded. &lt;br /&gt;
&lt;br /&gt;
== Local Variables (var_creature) ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_SYSTEM_STATE| int| 0| Bitmask controlling ambient system operation. (ergo, values below are in hexadecimal).&lt;br /&gt;
* 0x01 (AMBIENT_SYSTEM_ENABLED): Ambient behaviour enabled. For non-looping animations this is the only bit that need be set.&lt;br /&gt;
* 0x02 (AMBIENT_SYSTEM_SPAWNSTART: Begin ambient behaviour immediately after spawning. Generally, only infinitely looping animations require this.&lt;br /&gt;
* 0x04 (AMBIENT_SYSTEM_NOPLAYNEXT): Sets '''bPlayNext''' parameter to [[CommandPlayAnimation]] to false. Only infinitely looping animations require this.&lt;br /&gt;
* 0x08 (AMBIENT_SYSTEM_NOBLEND): Sets '''bBlendIn''' parameter to [[CommandPlayAnimation]] to false. Set this to force a creature to resume an infinitely looping animation after a conversation.&lt;br /&gt;
* 0x10 (AMBIENT_SYSTEM_ALWAYSON): Ambient behaviour never stops, regardless of distance to player. This should rarely, if ever, be used but at least the functionality exists if needed.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PATTERN| int | 0 | Dictates how the creature moves. Add 100 to the values below make creature run instead of walk. Add 10-90 for a random mix of running and walking (a higher value means more running).&lt;br /&gt;
*  0 (AMBIENT_MOVE_NONE): No ambient movement &lt;br /&gt;
*  1 (AMBIENT_MOVE_PATROL): Patrol waypoints (1, 2, 3, 2, 1, ...) &lt;br /&gt;
*  2 (AMBIENT_MOVE_LOOP): Loop through waypoints (1, 2, 3, 1, 2, 3, ...) &lt;br /&gt;
*  3 (AMBIENT_MOVE_WARP): Jump creature from the last waypoint to the first (1, 2, 3, jump to 1, 2, 3, ...) &lt;br /&gt;
*  4 (AMBIENT_MOVE_RANDOM): Move to a random waypoint other than the one the creature is currently at &lt;br /&gt;
*  5 (AMBIENT_MOVE_WANDER): Move to random location within 10m of home location &lt;br /&gt;
*  6 (AMBIENT_MOVE_WANDER_FAR): Move to random location within 30m of home location &lt;br /&gt;
*  7 (AMBIENT_MOVE_PATH_PATROL): Patrol all waypoints using [[CommandMoveToMultiLocations]] (1,2,3,2,1,...) &lt;br /&gt;
*  8 (AMBIENT_MOVE_PATH_LOOP): Loop through all waypoints using [[CommandMoveToMultiLocations]] (1,2,3. 1,2,3)&lt;br /&gt;
*  9 (AMBIENT_MOVE_ONCE): Walk through the waypoint set once (1-2-3)}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PREFIX| string | ap_&amp;lt;tag&amp;gt;| The prefix is used to determine the waypoints the creature can travel to. Note that ''&amp;lt;tag&amp;gt;'' is a placeholder filled in at run-time with the tag of the creature. Hence, for example, if AMBIENT_MOVE_PREFIX is ''ap_&amp;lt;tag&amp;gt;'' and the creature's tag is ''cr_dog'' then the system will look for waypoints with tags ''ap_cr_dog_01'', ''ap_cr_dog_02'', ''etc''. If no waypoint is found with the ''_01'' extension, the system will search instead for all waypoints with tags matching the AMBIENT_MOVE_PREFIX value exactly (i.e. ''ap_cr_dog''). This is useful in cases where you just want to add N waypoints all with the same tag.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_PATTERN| int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
*  0: No ambient animation pattern (ergo, no ambient animations).}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ| float | -1.0  | Animation frequency. The part left of the decimal specifies the minimum and the part right of the decimal specifies the maximum number of random animations to play during an animation phase. So, for example, a value of 1.3 will play between 1 and 3 random animations from the animation pattern listed in ambient_ai.xls. A value of -1.0 plays all animations in the animation pattern in the order they are listed in ambient_ai.xls. Animation pattens that are highlighted in green on the worksheeet should always be played in order (i.e. AMBIENT_ANIM_FREQ is -1.0).}}&lt;br /&gt;
{{Variable table row| AMBIENT_COMMAND | int | 0 |If non-zero, this value forces the creature to perform a specific command (instead of moving and animating).&lt;br /&gt;
*  0: Use standard ambient ambient behaviour system to perform movement and animations. &lt;br /&gt;
*  1: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 1-5 seconds between attack commands. &lt;br /&gt;
*  2: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 0-0.5 seconds between attack commands.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_PATTERN if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_FREQ_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_FREQ if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_STATE | int |0| Internal use by ambient behaviour system. Tracks number of animations left to play.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_COUNT | int |-1| Internal use by ambient behaviour system. Tracks total number of destination points for a creature.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_STATE | int |0| Internal use by ambient behaviour system. Tracks the last waypoint creature moved to and direction of travel.}}&lt;br /&gt;
{{Variable table row|AMBIENT_TICK_COUNT | int |0| Used internally, do not modify}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_OVERRIDE_COUNT|int|0|}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
== ambient_ai.xls ==&lt;br /&gt;
The actions used in an animation phase are listed in the ambient_anim_patterns worksheet of [[ambient_ai.xls]]. Each row defines an animation pattern, consisting of up to thirteen actions. Each action is composed of an animation (left of the decimal) and the number of loops it is played (right of decimal). For example, 619.02 will play a sleeping loop animation twice and 619.99 will play an infinitely looping sleeping animation. Non-looping animations require no loop-count (i.e. decimal) component. The list of all available animations is located in [[ANIM_base.xls]]. &lt;br /&gt;
&lt;br /&gt;
== sys_ambient_h ==&lt;br /&gt;
&lt;br /&gt;
The script [[sys_ambient_h]] contains the implementation of the ambient behaviour system. The AMBIENT_* local variables should never be directly modified at run-time. Instead, use the following functions to customize a creature's ambient behaviour through script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;	&lt;br /&gt;
// Normally this function is called automatically to begin or resume  ambient behaviour when a &lt;br /&gt;
// creature perceives the player. However, it can be called explicitly to force a creature to begin &lt;br /&gt;
// performing ambient behaviour or, if nAmbientEnable is 1, to enable ambient behaviour on a creature. &lt;br /&gt;
void Ambient_Start(object oCreature = OBJECT_SELF, int nAmbientEnable = 0, int nMovePattern = 0, string sMovePrefix = &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// Normally this function is called automatically to pause ambient behaviour after the party has &lt;br /&gt;
// been out of the creature's sight for a while. However, this function can be used to force a &lt;br /&gt;
// creature to temporarily cease ambient behaviour. Note that the creature will automatically  &lt;br /&gt;
// resume ambient behaviour when it perceives the player again. &lt;br /&gt;
void Ambient_Pause(object oCreature = OBJECT_SELF, int bCheckVisibility = TRUE);&lt;br /&gt;
&lt;br /&gt;
// Turns off ambient behaviour on a creature. The creature will resume ambient behaviour only &lt;br /&gt;
// after Ambient_Start() is called.&lt;br /&gt;
void Ambient_Stop(object oCreature = OBJECT_SELF);&lt;br /&gt;
&lt;br /&gt;
// Overrides the ambient animation pattern and animation frequency defined by the creature's template. &lt;br /&gt;
void Ambient_OverrideBehaviour(object oCreature, int nAnimPattern, float fAnimFreq);&lt;br /&gt;
&lt;br /&gt;
// Restores a creature's ambient animation behaviour to that defined in the creature's template.&lt;br /&gt;
void Ambient_RestoreBehaviour(object oCreature);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overriding Ambient Behaviour ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE | int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
* 0: no animations.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ_OVERRIDE | float | -1.0 | Animation frequency. The portion left of decimal specifies the minimum and the portion right of the decimal specifies the maximum number of animations to play during an animation phase. A value of -1.0 plays all animations in the animation pattern in the order listed in [[ambient_ai.xls]].}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_OVERRIDE_COUNT | int | | Used internally, do not modify}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
== Customising Ambient Behaviour ==&lt;br /&gt;
&lt;br /&gt;
=== Animations ===&lt;br /&gt;
&lt;br /&gt;
New ambient_anim_patterns can be added as an M2DA.&lt;br /&gt;
&lt;br /&gt;
Provisionally, it seems that some animations are cutscene-only. They don't work when scripted. This requires further investigation and documentation, as there is a [[Bug:_Some_animations_in_ANIM_base_won%27t_fire | bug]] which may account for some or all of this.&lt;br /&gt;
&lt;br /&gt;
=== Movement ===&lt;br /&gt;
&lt;br /&gt;
The system doesn't provide an explicit hook for a user-defined movement pattern.&lt;br /&gt;
&lt;br /&gt;
However, it does support walking once through a set of waypoints.&lt;br /&gt;
&lt;br /&gt;
We can implement any custom movement pattern as several sets of waypoints (each with its own prefix).&lt;br /&gt;
&lt;br /&gt;
For example, if we want to walk from A to B, then C or D and E depending on some condition, we might define the sets as ap1 (A, B), ap2 (C) and ap3 (D, E).&lt;br /&gt;
&lt;br /&gt;
We tell Ambient AI to walk waypoints prefixed ap1. On completion, we tell it to walk ap2 or ap3, depending on the condition.&lt;br /&gt;
&lt;br /&gt;
Intercepting the Ambient AI is tricky. By default, EVENT_TYPE_COMMAND_COMPLETE is handled directly by the rules_core script, which kicks off the next Ambient AI action before we can stop it. Presumably, this is for performance reasons.&lt;br /&gt;
&lt;br /&gt;
Set the AI_CUSTOM_AI_ACTIVE variable (see [[Custom AI]]) on the creature template to generate a new event (EVENT_TYPE_CUSTOM_COMMAND_COMPLETE) which can be handled in the creature script. If the creature is a non-combatant, CAI_INACTIVE (1) works fine.&lt;br /&gt;
 &lt;br /&gt;
Using AMBIENT_MOVE_ONCE, when the final waypoint is reached, Ambient AI will reset the move pattern to AMBIENT_MOVE_NONE before this new event fires.&lt;br /&gt;
&lt;br /&gt;
We can then trigger the next set of waypoints by including a snippet like this in our creature script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
        case EVENT_TYPE_CUSTOM_COMMAND_COMPLETE:&lt;br /&gt;
        {&lt;br /&gt;
         object oCreature = OBJECT_SELF;&lt;br /&gt;
&lt;br /&gt;
         // Do nothing unless we have arrived at our destination &lt;br /&gt;
&lt;br /&gt;
         if (GetLocalInt(oCreature, AMBIENT_MOVE_PATTERN) == AMBIENT_MOVE_NONE)&lt;br /&gt;
            {     &lt;br /&gt;
              int    nLastCommandType = GetEventInteger(ev, 0);&lt;br /&gt;
              int    nCommandStatus   = GetEventInteger(ev, 1);&lt;br /&gt;
              int    nLastSubCommand  = GetEventInteger(ev, 2);&lt;br /&gt;
              object oLastTarget      = OBJECT_INVALID;&lt;br /&gt;
              object oBlockingObject  = GetEventObject(ev, 2);  &lt;br /&gt;
&lt;br /&gt;
              // Check which path just finished&lt;br /&gt;
&lt;br /&gt;
              if (GetLocalString(oCreature, AMBIENT_MOVE_PREFIX) != &amp;quot;ap1_&amp;lt;tag&amp;gt;&amp;quot;) break;&lt;br /&gt;
&lt;br /&gt;
              // Stop Ambient AI for good order&lt;br /&gt;
&lt;br /&gt;
              Ambient_Stop(oCreature);&lt;br /&gt;
&lt;br /&gt;
              // Fix bug in Ambient_Start&lt;br /&gt;
&lt;br /&gt;
              SetLocalInt(oCreature, AMBIENT_MOVE_COUNT, AMBIENT_MOVE_COUNT_INVALID); &lt;br /&gt;
              SetLocalInt(oCreature, AMBIENT_MOVE_STATE,  AMBIENT_MOVE_NEXT);   &lt;br /&gt;
&lt;br /&gt;
              // Restart on new path           &lt;br /&gt;
&lt;br /&gt;
              Ambient_Start(oCreature, AMBIENT_SYSTEM_ENABLED, AMBIENT_MOVE_ONCE, &amp;quot;ap2_&amp;lt;tag&amp;gt;&amp;quot;);                &lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
          bEventHandled = TRUE;&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Note that when using any movement pattern other than AMBIENT_MOVE_ONCE, Ambient AI will issue the next movement command before EVENT_TYPE_CUSTOM_COMMAND_COMPLETE fires.&lt;br /&gt;
&lt;br /&gt;
== Bugs ==&lt;br /&gt;
&lt;br /&gt;
Changing the movement path for a creature is [[Bug:_Ambient_movement_erratic_when_a_new_path_is_specified | bugged]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Ambient behavior]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16139</id>
		<title>Ambient behaviour</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16139"/>
				<updated>2011-05-18T09:55:49Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Animations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{infobox creature}}&lt;br /&gt;
&lt;br /&gt;
Ambient behaviour begins when the player moves within 50m of a creature and ceases when the player remains more than 50m away for at least 40s. Ambient behaviour alternates between a movement phase and an animation phase, simulating a bubble of activity around the player. In a movement phase, the creature (optionally) moves to a new destination (typically a [[waypoint]] but it could be any object) and turns to face the same direction as the destination object. In an animation phase, the creature (optionally) performs one or more animations either in sequence or at random. Exact behaviour is controlled by local variables set on either the creature instance or template (see table below). All other local variables with the prefix AMBIENT_* are used internally by the ambient behaviour system (see script [[sys_ambient_h]].nss) and should not be manually modified. Never directly modify AMBIENT_* local variables at run time using [[SetLocalInt]] - always use the functions [[Ambient_Start]], [[Ambient_Stop]], [[Ambient_OverrideBehaviour]], and [[Ambient_RestoreBehaviour]] instead. Ambient behaviour is persisted when a game is saved and automatically resumes when a game is loaded. &lt;br /&gt;
&lt;br /&gt;
== Local Variables (var_creature) ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_SYSTEM_STATE| int| 0| Bitmask controlling ambient system operation. (ergo, values below are in hexadecimal).&lt;br /&gt;
* 0x01 (AMBIENT_SYSTEM_ENABLED): Ambient behaviour enabled. For non-looping animations this is the only bit that need be set.&lt;br /&gt;
* 0x02 (AMBIENT_SYSTEM_SPAWNSTART: Begin ambient behaviour immediately after spawning. Generally, only infinitely looping animations require this.&lt;br /&gt;
* 0x04 (AMBIENT_SYSTEM_NOPLAYNEXT): Sets '''bPlayNext''' parameter to [[CommandPlayAnimation]] to false. Only infinitely looping animations require this.&lt;br /&gt;
* 0x08 (AMBIENT_SYSTEM_NOBLEND): Sets '''bBlendIn''' parameter to [[CommandPlayAnimation]] to false. Set this to force a creature to resume an infinitely looping animation after a conversation.&lt;br /&gt;
* 0x10 (AMBIENT_SYSTEM_ALWAYSON): Ambient behaviour never stops, regardless of distance to player. This should rarely, if ever, be used but at least the functionality exists if needed.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PATTERN| int | 0 | Dictates how the creature moves. Add 100 to the values below make creature run instead of walk. Add 10-90 for a random mix of running and walking (a higher value means more running).&lt;br /&gt;
*  0 (AMBIENT_MOVE_NONE): No ambient movement &lt;br /&gt;
*  1 (AMBIENT_MOVE_PATROL): Patrol waypoints (1, 2, 3, 2, 1, ...) &lt;br /&gt;
*  2 (AMBIENT_MOVE_LOOP): Loop through waypoints (1, 2, 3, 1, 2, 3, ...) &lt;br /&gt;
*  3 (AMBIENT_MOVE_WARP): Jump creature from the last waypoint to the first (1, 2, 3, jump to 1, 2, 3, ...) &lt;br /&gt;
*  4 (AMBIENT_MOVE_RANDOM): Move to a random waypoint other than the one the creature is currently at &lt;br /&gt;
*  5 (AMBIENT_MOVE_WANDER): Move to random location within 10m of home location &lt;br /&gt;
*  6 (AMBIENT_MOVE_WANDER_FAR): Move to random location within 30m of home location &lt;br /&gt;
*  7 (AMBIENT_MOVE_PATH_PATROL): Patrol all waypoints using [[CommandMoveToMultiLocations]] (1,2,3,2,1,...) &lt;br /&gt;
*  8 (AMBIENT_MOVE_PATH_LOOP): Loop through all waypoints using [[CommandMoveToMultiLocations]] (1,2,3. 1,2,3)&lt;br /&gt;
*  9 (AMBIENT_MOVE_ONCE): Walk through the waypoint set once (1-2-3)}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PREFIX| string | ap_&amp;lt;tag&amp;gt;| The prefix is used to determine the waypoints the creature can travel to. Note that ''&amp;lt;tag&amp;gt;'' is a placeholder filled in at run-time with the tag of the creature. Hence, for example, if AMBIENT_MOVE_PREFIX is ''ap_&amp;lt;tag&amp;gt;'' and the creature's tag is ''cr_dog'' then the system will look for waypoints with tags ''ap_cr_dog_01'', ''ap_cr_dog_02'', ''etc''. If no waypoint is found with the ''_01'' extension, the system will search instead for all waypoints with tags matching the AMBIENT_MOVE_PREFIX value exactly (i.e. ''ap_cr_dog''). This is useful in cases where you just want to add N waypoints all with the same tag.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_PATTERN| int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
*  0: No ambient animation pattern (ergo, no ambient animations).}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ| float | -1.0  | Animation frequency. The part left of the decimal specifies the minimum and the part right of the decimal specifies the maximum number of random animations to play during an animation phase. So, for example, a value of 1.3 will play between 1 and 3 random animations from the animation pattern listed in ambient_ai.xls. A value of -1.0 plays all animations in the animation pattern in the order they are listed in ambient_ai.xls. Animation pattens that are highlighted in green on the worksheeet should always be played in order (i.e. AMBIENT_ANIM_FREQ is -1.0).}}&lt;br /&gt;
{{Variable table row| AMBIENT_COMMAND | int | 0 |If non-zero, this value forces the creature to perform a specific command (instead of moving and animating).&lt;br /&gt;
*  0: Use standard ambient ambient behaviour system to perform movement and animations. &lt;br /&gt;
*  1: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 1-5 seconds between attack commands. &lt;br /&gt;
*  2: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 0-0.5 seconds between attack commands.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_PATTERN if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_FREQ_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_FREQ if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_STATE | int |0| Internal use by ambient behaviour system. Tracks number of animations left to play.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_COUNT | int |-1| Internal use by ambient behaviour system. Tracks total number of destination points for a creature.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_STATE | int |0| Internal use by ambient behaviour system. Tracks the last waypoint creature moved to and direction of travel.}}&lt;br /&gt;
{{Variable table row|AMBIENT_TICK_COUNT | int |0| Used internally, do not modify}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_OVERRIDE_COUNT|int|0|}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
== ambient_ai.xls ==&lt;br /&gt;
The actions used in an animation phase are listed in the ambient_anim_patterns worksheet of [[ambient_ai.xls]]. Each row defines an animation pattern, consisting of up to thirteen actions. Each action is composed of an animation (left of the decimal) and the number of loops it is played (right of decimal). For example, 619.02 will play a sleeping loop animation twice and 619.99 will play an infinitely looping sleeping animation. Non-looping animations require no loop-count (i.e. decimal) component. The list of all available animations is located in [[ANIM_base.xls]]. &lt;br /&gt;
&lt;br /&gt;
== sys_ambient_h ==&lt;br /&gt;
&lt;br /&gt;
The script [[sys_ambient_h]] contains the implementation of the ambient behaviour system. The AMBIENT_* local variables should never be directly modified at run-time. Instead, use the following functions to customize a creature's ambient behaviour through script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;	&lt;br /&gt;
// Normally this function is called automatically to begin or resume  ambient behaviour when a &lt;br /&gt;
// creature perceives the player. However, it can be called explicitly to force a creature to begin &lt;br /&gt;
// performing ambient behaviour or, if nAmbientEnable is 1, to enable ambient behaviour on a creature. &lt;br /&gt;
void Ambient_Start(object oCreature = OBJECT_SELF, int nAmbientEnable = 0, int nMovePattern = 0, string sMovePrefix = &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// Normally this function is called automatically to pause ambient behaviour after the party has &lt;br /&gt;
// been out of the creature's sight for a while. However, this function can be used to force a &lt;br /&gt;
// creature to temporarily cease ambient behaviour. Note that the creature will automatically  &lt;br /&gt;
// resume ambient behaviour when it perceives the player again. &lt;br /&gt;
void Ambient_Pause(object oCreature = OBJECT_SELF, int bCheckVisibility = TRUE);&lt;br /&gt;
&lt;br /&gt;
// Turns off ambient behaviour on a creature. The creature will resume ambient behaviour only &lt;br /&gt;
// after Ambient_Start() is called.&lt;br /&gt;
void Ambient_Stop(object oCreature = OBJECT_SELF);&lt;br /&gt;
&lt;br /&gt;
// Overrides the ambient animation pattern and animation frequency defined by the creature's template. &lt;br /&gt;
void Ambient_OverrideBehaviour(object oCreature, int nAnimPattern, float fAnimFreq);&lt;br /&gt;
&lt;br /&gt;
// Restores a creature's ambient animation behaviour to that defined in the creature's template.&lt;br /&gt;
void Ambient_RestoreBehaviour(object oCreature);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overriding Ambient Behaviour ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE | int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
* 0: no animations.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ_OVERRIDE | float | -1.0 | Animation frequency. The portion left of decimal specifies the minimum and the portion right of the decimal specifies the maximum number of animations to play during an animation phase. A value of -1.0 plays all animations in the animation pattern in the order listed in [[ambient_ai.xls]].}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_OVERRIDE_COUNT | int | | Used internally, do not modify}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
== Customising Ambient Behaviour ==&lt;br /&gt;
&lt;br /&gt;
=== Animations ===&lt;br /&gt;
&lt;br /&gt;
New ambient_anim_patterns can be added as an M2DA.&lt;br /&gt;
&lt;br /&gt;
Provisionally, it seems that some animations are cutscene-only. They don't work when scripted. This requires further investigation and documentation, as there is a [[Bug:_Some_animations_in_ANIM_base_won%27t_fire | bug]] which may account for some or all of this.&lt;br /&gt;
&lt;br /&gt;
=== Movement ===&lt;br /&gt;
&lt;br /&gt;
The system doesn't provide an explicit hook for a user-defined movement pattern.&lt;br /&gt;
&lt;br /&gt;
However, it does support walking once through a set of waypoints.&lt;br /&gt;
&lt;br /&gt;
We can implement any custom movement pattern as several sets of waypoints (each with its own prefix).&lt;br /&gt;
&lt;br /&gt;
For example, if we want to walk from A to B, then C or D and E depending on some condition, we might define the sets as ap1 (A, B), ap2 (C) and ap3 (D, E).&lt;br /&gt;
&lt;br /&gt;
We tell Ambient AI to walk waypoints prefixed ap1. On completion, we tell it to walk ap2 or ap3, depending on the condition.&lt;br /&gt;
&lt;br /&gt;
Intercepting the Ambient AI is tricky. By default, EVENT_TYPE_COMMAND_COMPLETE is handled directly by the rules_core script, which kicks off the next Ambient AI action before we can stop it. Presumably, this is for performance reasons.&lt;br /&gt;
&lt;br /&gt;
Set the AI_CUSTOM_AI_ACTIVE variable on the creature template to 1 (i.e. TRUE) to generate a new event (EVENT_TYPE_CUSTOM_COMMAND_COMPLETE) which can be handled in the creature script.   &lt;br /&gt;
&lt;br /&gt;
Using AMBIENT_MOVE_ONCE, when the final waypoint is reached, Ambient AI will reset the move pattern to AMBIENT_MOVE_NONE before this new event fires.&lt;br /&gt;
&lt;br /&gt;
We can then trigger the next set of waypoints by including a snippet like this in our creature script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
        case EVENT_TYPE_CUSTOM_COMMAND_COMPLETE:&lt;br /&gt;
        {&lt;br /&gt;
         object oCreature = OBJECT_SELF;&lt;br /&gt;
&lt;br /&gt;
         // Do nothing unless we have arrived at our destination &lt;br /&gt;
&lt;br /&gt;
         if (GetLocalInt(oCreature, AMBIENT_MOVE_PATTERN) == AMBIENT_MOVE_NONE)&lt;br /&gt;
            {     &lt;br /&gt;
              int    nLastCommandType = GetEventInteger(ev, 0);&lt;br /&gt;
              int    nCommandStatus   = GetEventInteger(ev, 1);&lt;br /&gt;
              int    nLastSubCommand  = GetEventInteger(ev, 2);&lt;br /&gt;
              object oLastTarget      = OBJECT_INVALID;&lt;br /&gt;
              object oBlockingObject  = GetEventObject(ev, 2);  &lt;br /&gt;
&lt;br /&gt;
              // Check which path just finished&lt;br /&gt;
&lt;br /&gt;
              if (GetLocalString(oCreature, AMBIENT_MOVE_PREFIX) != &amp;quot;ap1_&amp;lt;tag&amp;gt;&amp;quot;) break;&lt;br /&gt;
&lt;br /&gt;
              // Stop Ambient AI for good order&lt;br /&gt;
&lt;br /&gt;
              Ambient_Stop(oCreature);&lt;br /&gt;
&lt;br /&gt;
              // Fix bug in Ambient_Start&lt;br /&gt;
&lt;br /&gt;
              SetLocalInt(oCreature, AMBIENT_MOVE_COUNT, AMBIENT_MOVE_COUNT_INVALID); &lt;br /&gt;
              SetLocalInt(oCreature, AMBIENT_MOVE_STATE,  AMBIENT_MOVE_NEXT);   &lt;br /&gt;
&lt;br /&gt;
              // Restart on new path           &lt;br /&gt;
&lt;br /&gt;
              Ambient_Start(oCreature, AMBIENT_SYSTEM_ENABLED, AMBIENT_MOVE_ONCE, &amp;quot;ap2_&amp;lt;tag&amp;gt;&amp;quot;);                &lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
          bEventHandled = TRUE;&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Note that when using any movement pattern other than AMBIENT_MOVE_ONCE, Ambient AI will issue the next movement command before EVENT_TYPE_CUSTOM_COMMAND_COMPLETE fires.        &lt;br /&gt;
&lt;br /&gt;
== Bugs ==&lt;br /&gt;
&lt;br /&gt;
Changing the movement path for a creature is [[Bug:_Ambient_movement_erratic_when_a_new_path_is_specified | bugged]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Ambient behavior]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_Light_Map_glitches&amp;diff=16138</id>
		<title>Bug: Light Map glitches</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_Light_Map_glitches&amp;diff=16138"/>
				<updated>2011-05-18T09:51:38Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Workarounds */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Version found:''' 1.0.982.19 &amp;lt;!-- put the version number of your toolset here --&amp;gt;&lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- Describe the bug here including as many details as possible. What situations trigger it and what effects it causes are the most important. --&amp;gt;&lt;br /&gt;
After light maps have been rendered, they may contain obvious glitches (e.g. dark triangles, shadows from models that have been deleted, severe brightness / darkness issues etc).&lt;br /&gt;
&lt;br /&gt;
This may be related in part to the hard-coding of &amp;quot;single player&amp;quot; in part of the resource processing pipeline, which has already been identified as a bug affecting water planes.&lt;br /&gt;
&lt;br /&gt;
However, that's probably not the whole story, because deleting the old erf file can improve the results, too (and makes the rendering process much faster).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are numerous bugs and glitches with the currently available eclipseray 1.2 as you can read at the appropriate threads. e.g.:&lt;br /&gt;
&lt;br /&gt;
== Bugs ==&lt;br /&gt;
* black spots randomly placed at the lightmaps around tesselation borders&lt;br /&gt;
* shiny blue shade at certain models&lt;br /&gt;
* bugged and therefore corrupted lightmap of a chunk if more than one static/animated light lits it&lt;br /&gt;
* wrong calculated intensity value of baked lights&lt;br /&gt;
* alpha maps are not rendered correctly -&amp;gt; spider webs drop a shadow but they should not do so&lt;br /&gt;
* light probes are not rendered correctly -&amp;gt; they all show the same mirrored texture&lt;br /&gt;
&lt;br /&gt;
There is '''no workaround''' for any of the glitches! The dark triangles are directly connected with tesselation borders. If you tesselate your mesh the triangles will wander around the new border where the high resolution grid hits the low resolution grid.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&amp;lt;!-- if you know of any ways to work around the bug describe them here. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most lighting bugs seem to go away if you &lt;br /&gt;
&lt;br /&gt;
* Delete any erf files for the level (you may need to close the toolset first)&lt;br /&gt;
* Delete Windows temporary files&lt;br /&gt;
* In (Documents)\Bioware\Dragon Age\Toolset, delete all files from subfolders LvlWorkspace, ProbeLightMaps and resourcepostintermediateWin32&lt;br /&gt;
* Switch to the Single Player campaign in the toolset (File &amp;gt; Manage Modules)&lt;br /&gt;
* Open your level and do all the rendering and posting in Single Player&lt;br /&gt;
* Delete the old level folder from AddIns &amp;gt; [module] &amp;gt; core &amp;gt; override &amp;gt; toolsetexport&lt;br /&gt;
* Move the folder you just made in packages &amp;gt; core &amp;gt; override &amp;gt; toolsetexport to that Addins location&lt;br /&gt;
* Reopen your module (File &amp;gt; Manage Modules)&lt;br /&gt;
&lt;br /&gt;
If you get a &amp;quot;failed to load&amp;quot; error in Single Player, your level may contain an unnecessary custom object, such as a test creature. &lt;br /&gt;
&lt;br /&gt;
Routine file deletion (mentioned above) can be done at a stroke using free configurable tools such as [http://www.piriform.com/ccleaner  CCleaner].&lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;br /&gt;
[[Category:Level layout bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_EVENT_TYPE_CUSTOM_COMMAND_COMPLETE_not_being_handled&amp;diff=16137</id>
		<title>Bug: EVENT TYPE CUSTOM COMMAND COMPLETE not being handled</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_EVENT_TYPE_CUSTOM_COMMAND_COMPLETE_not_being_handled&amp;diff=16137"/>
				<updated>2011-05-18T09:35:51Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Version found:''' v1.0.1008.0&lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&lt;br /&gt;
== Comment ==&lt;br /&gt;
&lt;br /&gt;
This may be a spurious bug report.&lt;br /&gt;
&lt;br /&gt;
If the AI_CUSTOM_AI_ACTIVE variable on the creature template is set (to 1), EVENT_TYPE_CUSTOM_COMMAND_COMPLETE is sent to the creature script.&lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_Builder_to_Builder_Create_includes_core_resources_by_default&amp;diff=16136</id>
		<title>Bug: Builder to Builder Create includes core resources by default</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_Builder_to_Builder_Create_includes_core_resources_by_default&amp;diff=16136"/>
				<updated>2011-05-18T09:30:27Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: Created page with '*'''Toolset verion:''' 1.0.1008.0 *'''Game version:''' 1.04  *'''Status:''' Open  == Description == &amp;lt;!-- Describe the bug here including as many details as possible. What situati...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Toolset verion:''' 1.0.1008.0&lt;br /&gt;
*'''Game version:''' 1.04 &lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- Describe the bug here including as many details as possible. What situations trigger it and what effects it causes are the most important. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Builder to Builder Create includes dependent core resources by default.&lt;br /&gt;
&lt;br /&gt;
This is a major inconvenience when taking daily backups of a large module.&lt;br /&gt;
&lt;br /&gt;
It makes the extract much bigger and slower than it needs to be.&lt;br /&gt;
&lt;br /&gt;
It also makes the load process more confusing.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&amp;lt;!-- if you know of any ways to work around the bug describe them here. --&amp;gt;&lt;br /&gt;
Unselect all.&lt;br /&gt;
&lt;br /&gt;
Sort to module order.&lt;br /&gt;
&lt;br /&gt;
Page down from the top to the end of the module. &lt;br /&gt;
&lt;br /&gt;
Select all resources for the module.&lt;br /&gt;
&lt;br /&gt;
Remember how many pages you have to scroll down, to speed things up next time.&lt;br /&gt;
&lt;br /&gt;
== Comment ==&lt;br /&gt;
&lt;br /&gt;
An earlier comment in the wiki suggested that dependent core resources should be included to prevent integrity issues on Load.&lt;br /&gt;
&lt;br /&gt;
In practice, there is almost never a problem, because everyone has the same core resources. If there is, Load just doesn't load the resources in question, which is easily fixed. So, in the light of experience, this is considered to be a bug.&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_Water_plane_missing_in-game&amp;diff=16135</id>
		<title>Bug: Water plane missing in-game</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_Water_plane_missing_in-game&amp;diff=16135"/>
				<updated>2011-05-18T09:18:33Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Workarounds */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Version found:''' 1.0.982.19 &amp;lt;!-- put the version number of your toolset here --&amp;gt;&lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
{{EV|203997|[[User:Allan Smith|Allan Smith]]}}&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- Describe the bug here including as many details as possible. What situations trigger it and what effects it causes are the most important. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you create a level with a water plane in it the water is appearing properly in the toolset but is non-existent in the game. This problem has been identified. It is not lightmapper related; it turns out that &amp;quot;single player&amp;quot; is hard-coded into a part of the resource processing pipeline.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&amp;lt;!-- if you know of any ways to work around the bug describe them here. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A proper fix may take some time, but there's a fairly simple workaround for it.&lt;br /&gt;
&lt;br /&gt;
To post a level layout with water, first ensure that you've switched to the single player module via [[manage modules]], and then once you've posted it you'll need to manually copy the resulting files from the single player [[override directory]] into your addin's override directory.&lt;br /&gt;
&lt;br /&gt;
N.B. This bug is one of several path-related errors in level processing. For example, light mapping is also bugged. So, it's advisable to do all level work in the Single Player module, as described above.&lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;br /&gt;
[[Category:Level layout bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_Ambient_movement_erratic_when_a_new_path_is_specified&amp;diff=16134</id>
		<title>Bug: Ambient movement erratic when a new path is specified</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_Ambient_movement_erratic_when_a_new_path_is_specified&amp;diff=16134"/>
				<updated>2011-05-18T09:13:43Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Toolset verion:''' 1.0.1008.0&lt;br /&gt;
*'''Game version:''' 1.04 &lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- Describe the bug here including as many details as possible. What situations trigger it and what effects it causes are the most important. --&amp;gt;&lt;br /&gt;
The Ambient_Start function allows the waypoint path AMBIENT_MOVE_PREFIX to be specified.&lt;br /&gt;
&lt;br /&gt;
However, if it is used to specify a new path for a creature, the new waypoints may be visited in the wrong order.&lt;br /&gt;
&lt;br /&gt;
Specifically, if the creature last moved to old path waypoint N, it will visit new path waypoint N (if it exists) before new path waypoint 1.&lt;br /&gt;
&lt;br /&gt;
This has been verified in AMBIENT_MOVE_ONCE mode, but probably affects most movement patterns.&lt;br /&gt;
&lt;br /&gt;
Ambient_StartTeam() and Ambient_StartTag() depend on Ambient_Start, so they have the same bug.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&amp;lt;!-- if you know of any ways to work around the bug describe them here. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the following initialistions before calling Ambient_Start:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
SetLocalInt(oCreature, AMBIENT_MOVE_COUNT, AMBIENT_MOVE_COUNT_INVALID); &lt;br /&gt;
SetLocalInt(oCreature, AMBIENT_MOVE_STATE,  AMBIENT_MOVE_NEXT);              &lt;br /&gt;
Ambient_Start(oCreature, ... &lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where oCreature is the creature object in question.&lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16133</id>
		<title>Ambient behaviour</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16133"/>
				<updated>2011-05-18T09:08:29Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{infobox creature}}&lt;br /&gt;
&lt;br /&gt;
Ambient behaviour begins when the player moves within 50m of a creature and ceases when the player remains more than 50m away for at least 40s. Ambient behaviour alternates between a movement phase and an animation phase, simulating a bubble of activity around the player. In a movement phase, the creature (optionally) moves to a new destination (typically a [[waypoint]] but it could be any object) and turns to face the same direction as the destination object. In an animation phase, the creature (optionally) performs one or more animations either in sequence or at random. Exact behaviour is controlled by local variables set on either the creature instance or template (see table below). All other local variables with the prefix AMBIENT_* are used internally by the ambient behaviour system (see script [[sys_ambient_h]].nss) and should not be manually modified. Never directly modify AMBIENT_* local variables at run time using [[SetLocalInt]] - always use the functions [[Ambient_Start]], [[Ambient_Stop]], [[Ambient_OverrideBehaviour]], and [[Ambient_RestoreBehaviour]] instead. Ambient behaviour is persisted when a game is saved and automatically resumes when a game is loaded. &lt;br /&gt;
&lt;br /&gt;
== Local Variables (var_creature) ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_SYSTEM_STATE| int| 0| Bitmask controlling ambient system operation. (ergo, values below are in hexadecimal).&lt;br /&gt;
* 0x01 (AMBIENT_SYSTEM_ENABLED): Ambient behaviour enabled. For non-looping animations this is the only bit that need be set.&lt;br /&gt;
* 0x02 (AMBIENT_SYSTEM_SPAWNSTART: Begin ambient behaviour immediately after spawning. Generally, only infinitely looping animations require this.&lt;br /&gt;
* 0x04 (AMBIENT_SYSTEM_NOPLAYNEXT): Sets '''bPlayNext''' parameter to [[CommandPlayAnimation]] to false. Only infinitely looping animations require this.&lt;br /&gt;
* 0x08 (AMBIENT_SYSTEM_NOBLEND): Sets '''bBlendIn''' parameter to [[CommandPlayAnimation]] to false. Set this to force a creature to resume an infinitely looping animation after a conversation.&lt;br /&gt;
* 0x10 (AMBIENT_SYSTEM_ALWAYSON): Ambient behaviour never stops, regardless of distance to player. This should rarely, if ever, be used but at least the functionality exists if needed.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PATTERN| int | 0 | Dictates how the creature moves. Add 100 to the values below make creature run instead of walk. Add 10-90 for a random mix of running and walking (a higher value means more running).&lt;br /&gt;
*  0 (AMBIENT_MOVE_NONE): No ambient movement &lt;br /&gt;
*  1 (AMBIENT_MOVE_PATROL): Patrol waypoints (1, 2, 3, 2, 1, ...) &lt;br /&gt;
*  2 (AMBIENT_MOVE_LOOP): Loop through waypoints (1, 2, 3, 1, 2, 3, ...) &lt;br /&gt;
*  3 (AMBIENT_MOVE_WARP): Jump creature from the last waypoint to the first (1, 2, 3, jump to 1, 2, 3, ...) &lt;br /&gt;
*  4 (AMBIENT_MOVE_RANDOM): Move to a random waypoint other than the one the creature is currently at &lt;br /&gt;
*  5 (AMBIENT_MOVE_WANDER): Move to random location within 10m of home location &lt;br /&gt;
*  6 (AMBIENT_MOVE_WANDER_FAR): Move to random location within 30m of home location &lt;br /&gt;
*  7 (AMBIENT_MOVE_PATH_PATROL): Patrol all waypoints using [[CommandMoveToMultiLocations]] (1,2,3,2,1,...) &lt;br /&gt;
*  8 (AMBIENT_MOVE_PATH_LOOP): Loop through all waypoints using [[CommandMoveToMultiLocations]] (1,2,3. 1,2,3)&lt;br /&gt;
*  9 (AMBIENT_MOVE_ONCE): Walk through the waypoint set once (1-2-3)}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PREFIX| string | ap_&amp;lt;tag&amp;gt;| The prefix is used to determine the waypoints the creature can travel to. Note that ''&amp;lt;tag&amp;gt;'' is a placeholder filled in at run-time with the tag of the creature. Hence, for example, if AMBIENT_MOVE_PREFIX is ''ap_&amp;lt;tag&amp;gt;'' and the creature's tag is ''cr_dog'' then the system will look for waypoints with tags ''ap_cr_dog_01'', ''ap_cr_dog_02'', ''etc''. If no waypoint is found with the ''_01'' extension, the system will search instead for all waypoints with tags matching the AMBIENT_MOVE_PREFIX value exactly (i.e. ''ap_cr_dog''). This is useful in cases where you just want to add N waypoints all with the same tag.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_PATTERN| int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
*  0: No ambient animation pattern (ergo, no ambient animations).}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ| float | -1.0  | Animation frequency. The part left of the decimal specifies the minimum and the part right of the decimal specifies the maximum number of random animations to play during an animation phase. So, for example, a value of 1.3 will play between 1 and 3 random animations from the animation pattern listed in ambient_ai.xls. A value of -1.0 plays all animations in the animation pattern in the order they are listed in ambient_ai.xls. Animation pattens that are highlighted in green on the worksheeet should always be played in order (i.e. AMBIENT_ANIM_FREQ is -1.0).}}&lt;br /&gt;
{{Variable table row| AMBIENT_COMMAND | int | 0 |If non-zero, this value forces the creature to perform a specific command (instead of moving and animating).&lt;br /&gt;
*  0: Use standard ambient ambient behaviour system to perform movement and animations. &lt;br /&gt;
*  1: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 1-5 seconds between attack commands. &lt;br /&gt;
*  2: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 0-0.5 seconds between attack commands.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_PATTERN if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_FREQ_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_FREQ if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_STATE | int |0| Internal use by ambient behaviour system. Tracks number of animations left to play.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_COUNT | int |-1| Internal use by ambient behaviour system. Tracks total number of destination points for a creature.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_STATE | int |0| Internal use by ambient behaviour system. Tracks the last waypoint creature moved to and direction of travel.}}&lt;br /&gt;
{{Variable table row|AMBIENT_TICK_COUNT | int |0| Used internally, do not modify}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_OVERRIDE_COUNT|int|0|}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
== ambient_ai.xls ==&lt;br /&gt;
The actions used in an animation phase are listed in the ambient_anim_patterns worksheet of [[ambient_ai.xls]]. Each row defines an animation pattern, consisting of up to thirteen actions. Each action is composed of an animation (left of the decimal) and the number of loops it is played (right of decimal). For example, 619.02 will play a sleeping loop animation twice and 619.99 will play an infinitely looping sleeping animation. Non-looping animations require no loop-count (i.e. decimal) component. The list of all available animations is located in [[ANIM_base.xls]]. &lt;br /&gt;
&lt;br /&gt;
== sys_ambient_h ==&lt;br /&gt;
&lt;br /&gt;
The script [[sys_ambient_h]] contains the implementation of the ambient behaviour system. The AMBIENT_* local variables should never be directly modified at run-time. Instead, use the following functions to customize a creature's ambient behaviour through script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;	&lt;br /&gt;
// Normally this function is called automatically to begin or resume  ambient behaviour when a &lt;br /&gt;
// creature perceives the player. However, it can be called explicitly to force a creature to begin &lt;br /&gt;
// performing ambient behaviour or, if nAmbientEnable is 1, to enable ambient behaviour on a creature. &lt;br /&gt;
void Ambient_Start(object oCreature = OBJECT_SELF, int nAmbientEnable = 0, int nMovePattern = 0, string sMovePrefix = &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// Normally this function is called automatically to pause ambient behaviour after the party has &lt;br /&gt;
// been out of the creature's sight for a while. However, this function can be used to force a &lt;br /&gt;
// creature to temporarily cease ambient behaviour. Note that the creature will automatically  &lt;br /&gt;
// resume ambient behaviour when it perceives the player again. &lt;br /&gt;
void Ambient_Pause(object oCreature = OBJECT_SELF, int bCheckVisibility = TRUE);&lt;br /&gt;
&lt;br /&gt;
// Turns off ambient behaviour on a creature. The creature will resume ambient behaviour only &lt;br /&gt;
// after Ambient_Start() is called.&lt;br /&gt;
void Ambient_Stop(object oCreature = OBJECT_SELF);&lt;br /&gt;
&lt;br /&gt;
// Overrides the ambient animation pattern and animation frequency defined by the creature's template. &lt;br /&gt;
void Ambient_OverrideBehaviour(object oCreature, int nAnimPattern, float fAnimFreq);&lt;br /&gt;
&lt;br /&gt;
// Restores a creature's ambient animation behaviour to that defined in the creature's template.&lt;br /&gt;
void Ambient_RestoreBehaviour(object oCreature);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overriding Ambient Behaviour ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE | int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
* 0: no animations.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ_OVERRIDE | float | -1.0 | Animation frequency. The portion left of decimal specifies the minimum and the portion right of the decimal specifies the maximum number of animations to play during an animation phase. A value of -1.0 plays all animations in the animation pattern in the order listed in [[ambient_ai.xls]].}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_OVERRIDE_COUNT | int | | Used internally, do not modify}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
== Customising Ambient Behaviour ==&lt;br /&gt;
&lt;br /&gt;
=== Animations ===&lt;br /&gt;
&lt;br /&gt;
New ambient_anim_patterns can be added as an M2DA.&lt;br /&gt;
&lt;br /&gt;
Provisionally, it seems that some animations are cutscene-only. They don't work when scripted. This requires further investigation and documentation.&lt;br /&gt;
&lt;br /&gt;
=== Movement ===&lt;br /&gt;
&lt;br /&gt;
The system doesn't provide an explicit hook for a user-defined movement pattern.&lt;br /&gt;
&lt;br /&gt;
However, it does support walking once through a set of waypoints.&lt;br /&gt;
&lt;br /&gt;
We can implement any custom movement pattern as several sets of waypoints (each with its own prefix).&lt;br /&gt;
&lt;br /&gt;
For example, if we want to walk from A to B, then C or D and E depending on some condition, we might define the sets as ap1 (A, B), ap2 (C) and ap3 (D, E).&lt;br /&gt;
&lt;br /&gt;
We tell Ambient AI to walk waypoints prefixed ap1. On completion, we tell it to walk ap2 or ap3, depending on the condition.&lt;br /&gt;
&lt;br /&gt;
Intercepting the Ambient AI is tricky. By default, EVENT_TYPE_COMMAND_COMPLETE is handled directly by the rules_core script, which kicks off the next Ambient AI action before we can stop it. Presumably, this is for performance reasons.&lt;br /&gt;
&lt;br /&gt;
Set the AI_CUSTOM_AI_ACTIVE variable on the creature template to 1 (i.e. TRUE) to generate a new event (EVENT_TYPE_CUSTOM_COMMAND_COMPLETE) which can be handled in the creature script.   &lt;br /&gt;
&lt;br /&gt;
Using AMBIENT_MOVE_ONCE, when the final waypoint is reached, Ambient AI will reset the move pattern to AMBIENT_MOVE_NONE before this new event fires.&lt;br /&gt;
&lt;br /&gt;
We can then trigger the next set of waypoints by including a snippet like this in our creature script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
        case EVENT_TYPE_CUSTOM_COMMAND_COMPLETE:&lt;br /&gt;
        {&lt;br /&gt;
         object oCreature = OBJECT_SELF;&lt;br /&gt;
&lt;br /&gt;
         // Do nothing unless we have arrived at our destination &lt;br /&gt;
&lt;br /&gt;
         if (GetLocalInt(oCreature, AMBIENT_MOVE_PATTERN) == AMBIENT_MOVE_NONE)&lt;br /&gt;
            {     &lt;br /&gt;
              int    nLastCommandType = GetEventInteger(ev, 0);&lt;br /&gt;
              int    nCommandStatus   = GetEventInteger(ev, 1);&lt;br /&gt;
              int    nLastSubCommand  = GetEventInteger(ev, 2);&lt;br /&gt;
              object oLastTarget      = OBJECT_INVALID;&lt;br /&gt;
              object oBlockingObject  = GetEventObject(ev, 2);  &lt;br /&gt;
&lt;br /&gt;
              // Check which path just finished&lt;br /&gt;
&lt;br /&gt;
              if (GetLocalString(oCreature, AMBIENT_MOVE_PREFIX) != &amp;quot;ap1_&amp;lt;tag&amp;gt;&amp;quot;) break;&lt;br /&gt;
&lt;br /&gt;
              // Stop Ambient AI for good order&lt;br /&gt;
&lt;br /&gt;
              Ambient_Stop(oCreature);&lt;br /&gt;
&lt;br /&gt;
              // Fix bug in Ambient_Start&lt;br /&gt;
&lt;br /&gt;
              SetLocalInt(oCreature, AMBIENT_MOVE_COUNT, AMBIENT_MOVE_COUNT_INVALID); &lt;br /&gt;
              SetLocalInt(oCreature, AMBIENT_MOVE_STATE,  AMBIENT_MOVE_NEXT);   &lt;br /&gt;
&lt;br /&gt;
              // Restart on new path           &lt;br /&gt;
&lt;br /&gt;
              Ambient_Start(oCreature, AMBIENT_SYSTEM_ENABLED, AMBIENT_MOVE_ONCE, &amp;quot;ap2_&amp;lt;tag&amp;gt;&amp;quot;);                &lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
          bEventHandled = TRUE;&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Note that when using any movement pattern other than AMBIENT_MOVE_ONCE, Ambient AI will issue the next movement command before EVENT_TYPE_CUSTOM_COMMAND_COMPLETE fires.        &lt;br /&gt;
&lt;br /&gt;
== Bugs ==&lt;br /&gt;
&lt;br /&gt;
Changing the movement path for a creature is [[Bug:_Ambient_movement_erratic_when_a_new_path_is_specified | bugged]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Ambient behavior]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_Ambient_movement_erratic_when_a_new_path_is_specified&amp;diff=16132</id>
		<title>Bug: Ambient movement erratic when a new path is specified</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_Ambient_movement_erratic_when_a_new_path_is_specified&amp;diff=16132"/>
				<updated>2011-05-18T07:24:32Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: Created page with '*'''Toolset verion:''' 1.0.1008.0 *'''Game version:''' 1.04  *'''Status:''' Open  == Description == &amp;lt;!-- Describe the bug here including as many details as possible. What situati...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Toolset verion:''' 1.0.1008.0&lt;br /&gt;
*'''Game version:''' 1.04 &lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- Describe the bug here including as many details as possible. What situations trigger it and what effects it causes are the most important. --&amp;gt;&lt;br /&gt;
The Ambient_Start function allows the waypoint path AMBIENT_MOVE_PREFIX to be specified.&lt;br /&gt;
&lt;br /&gt;
However, if it is used to specify a new path for a creature, the new waypoints may be visited in the wrong order.&lt;br /&gt;
&lt;br /&gt;
Specifically, if the creature last moved to old path waypoint N, it will visit new path waypoint N before new path waypoint 1.&lt;br /&gt;
&lt;br /&gt;
This has been verified in AMBIENT_MOVE_ONCE mode, but probably affects most movement patterns.&lt;br /&gt;
&lt;br /&gt;
Ambient_StartTeam() and Ambient_StartTag() depend on Ambient_Start, so they have the same bug.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&amp;lt;!-- if you know of any ways to work around the bug describe them here. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the following initialistions before calling Ambient_Start:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
SetLocalInt(oCreature, AMBIENT_MOVE_COUNT, AMBIENT_MOVE_COUNT_INVALID); &lt;br /&gt;
SetLocalInt(oCreature, AMBIENT_MOVE_STATE,  AMBIENT_MOVE_NEXT);              &lt;br /&gt;
Ambient_Start(oCreature, ... &lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where oCreature is the creature object in question.&lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16129</id>
		<title>Ambient behaviour</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Ambient_behaviour&amp;diff=16129"/>
				<updated>2011-05-16T10:25:21Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Local Variables (var_creature) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{infobox creature}}&lt;br /&gt;
&lt;br /&gt;
Ambient behaviour begins when the player moves within 50m of a creature and ceases when the player remains more than 50m away for at least 40s. Ambient behaviour alternates between a movement phase and an animation phase, simulating a bubble of activity around the player. In a movement phase, the creature (optionally) moves to a new destination (typically a [[waypoint]] but it could be any object) and turns to face the same direction as the destination object. In an animation phase, the creature (optionally) performs one or more animations either in sequence or at random. Exact behaviour is controlled by local variables set on either the creature instance or template (see table below). All other local variables with the prefix AMBIENT_* are used internally by the ambient behaviour system (see script [[sys_ambient_h]].nss) and should not be manually modified. Never directly modify AMBIENT_* local variables at run time using [[SetLocalInt]] - always use the functions [[Ambient_Start]], [[Ambient_Stop]], [[Ambient_OverrideBehaviour]], and [[Ambient_RestoreBehaviour]] instead. Ambient behaviour is persisted when a game is saved and automatically resumes when a game is loaded. &lt;br /&gt;
&lt;br /&gt;
== Local Variables (var_creature) ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_SYSTEM_STATE| int| 0| Bitmask controlling ambient system operation. (ergo, values below are in hexadecimal).&lt;br /&gt;
* 0x01 (AMBIENT_SYSTEM_ENABLED): Ambient behaviour enabled. For non-looping animations this is the only bit that need be set.&lt;br /&gt;
* 0x02 (AMBIENT_SYSTEM_SPAWNSTART: Begin ambient behaviour immediately after spawning. Generally, only infinitely looping animations require this.&lt;br /&gt;
* 0x04 (AMBIENT_SYSTEM_NOPLAYNEXT): Sets '''bPlayNext''' parameter to [[CommandPlayAnimation]] to false. Only infinitely looping animations require this.&lt;br /&gt;
* 0x08 (AMBIENT_SYSTEM_NOBLEND): Sets '''bBlendIn''' parameter to [[CommandPlayAnimation]] to false. Set this to force a creature to resume an infinitely looping animation after a conversation.&lt;br /&gt;
* 0x10 (AMBIENT_SYSTEM_ALWAYSON): Ambient behaviour never stops, regardless of distance to player. This should rarely, if ever, be used but at least the functionality exists if needed.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PATTERN| int | 0 | Dictates how the creature moves. Add 100 to the values below make creature run instead of walk. Add 10-90 for a random mix of running and walking (a higher value means more running).&lt;br /&gt;
*  0 (AMBIENT_MOVE_NONE): No ambient movement &lt;br /&gt;
*  1 (AMBIENT_MOVE_PATROL): Patrol waypoints (1, 2, 3, 2, 1, ...) &lt;br /&gt;
*  2 (AMBIENT_MOVE_LOOP): Loop through waypoints (1, 2, 3, 1, 2, 3, ...) &lt;br /&gt;
*  3 (AMBIENT_MOVE_WARP): Jump creature from the last waypoint to the first (1, 2, 3, jump to 1, 2, 3, ...) &lt;br /&gt;
*  4 (AMBIENT_MOVE_RANDOM): Move to a random waypoint other than the one the creature is currently at &lt;br /&gt;
*  5 (AMBIENT_MOVE_WANDER): Move to random location within 10m of home location &lt;br /&gt;
*  6 (AMBIENT_MOVE_WANDER_FAR): Move to random location within 30m of home location &lt;br /&gt;
*  7 (AMBIENT_MOVE_PATH_PATROL): Patrol all waypoints using [[CommandMoveToMultiLocations]] (1,2,3,2,1,...) &lt;br /&gt;
*  8 (AMBIENT_MOVE_PATH_LOOP): Loop through all waypoints using [[CommandMoveToMultiLocations]] (1,2,3. 1,2,3)&lt;br /&gt;
*  9 (AMBIENT_MOVE_ONCE): Walk through the waypoint set once (1-2-3)}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_PREFIX| string | ap_&amp;lt;tag&amp;gt;| The prefix is used to determine the waypoints the creature can travel to. Note that ''&amp;lt;tag&amp;gt;'' is a placeholder filled in at run-time with the tag of the creature. Hence, for example, if AMBIENT_MOVE_PREFIX is ''ap_&amp;lt;tag&amp;gt;'' and the creature's tag is ''cr_dog'' then the system will look for waypoints with tags ''ap_cr_dog_01'', ''ap_cr_dog_02'', ''etc''. If no waypoint is found with the ''_01'' extension, the system will search instead for all waypoints with tags matching the AMBIENT_MOVE_PREFIX value exactly (i.e. ''ap_cr_dog''). This is useful in cases where you just want to add N waypoints all with the same tag.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_PATTERN| int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
*  0: No ambient animation pattern (ergo, no ambient animations).}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ| float | -1.0  | Animation frequency. The part left of the decimal specifies the minimum and the part right of the decimal specifies the maximum number of random animations to play during an animation phase. So, for example, a value of 1.3 will play between 1 and 3 random animations from the animation pattern listed in ambient_ai.xls. A value of -1.0 plays all animations in the animation pattern in the order they are listed in ambient_ai.xls. Animation pattens that are highlighted in green on the worksheeet should always be played in order (i.e. AMBIENT_ANIM_FREQ is -1.0).}}&lt;br /&gt;
{{Variable table row| AMBIENT_COMMAND | int | 0 |If non-zero, this value forces the creature to perform a specific command (instead of moving and animating).&lt;br /&gt;
*  0: Use standard ambient ambient behaviour system to perform movement and animations. &lt;br /&gt;
*  1: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 1-5 seconds between attack commands. &lt;br /&gt;
*  2: Forces creature to attack the nearest object with tag ''&amp;lt;tag&amp;gt;_target''. There's an interval of 0-0.5 seconds between attack commands.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_PATTERN if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_FREQ_OVERRIDE| int| 0| Overrides AMBIENT_ANIM_FREQ if non-zero.}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_STATE | int |0| Internal use by ambient behaviour system. Tracks number of animations left to play.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_COUNT | int |-1| Internal use by ambient behaviour system. Tracks total number of destination points for a creature.}}&lt;br /&gt;
{{Variable table row|AMBIENT_MOVE_STATE | int |0| Internal use by ambient behaviour system. Tracks the last waypoint creature moved to and direction of travel.}}&lt;br /&gt;
{{Variable table row|AMBIENT_TICK_COUNT | int |0| Used internally, do not modify}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_OVERRIDE_COUNT|int|0|}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
== ambient_ai.xls ==&lt;br /&gt;
The actions used in an animation phase are listed in the ambient_anim_patterns worksheet of [[ambient_ai.xls]]. Each row defines an animation pattern, consisting of up to thirteen actions. Each action is composed of an animation (left of the decimal) and the number of loops it is played (right of decimal). For example, 619.02 will play a sleeping loop animation twice and 619.99 will play an infinitely looping sleeping animation. Non-looping animations require no loop-count (i.e. decimal) component. The list of all available animations is located in [[ANIM_base.xls]]. &lt;br /&gt;
&lt;br /&gt;
== sys_ambient_h ==&lt;br /&gt;
&lt;br /&gt;
The script [[sys_ambient_h]] contains the implementation of the ambient behaviour system. The AMBIENT_* local variables should never be directly modified at run-time. Instead, use the following functions to customize a creature's ambient behaviour through script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;	&lt;br /&gt;
// Normally this function is called automatically to begin or resume  ambient behaviour when a &lt;br /&gt;
// creature perceives the player. However, it can be called explicitly to force a creature to begin &lt;br /&gt;
// performing ambient behaviour or, if nAmbientEnable is 1, to enable ambient behaviour on a creature. &lt;br /&gt;
void Ambient_Start(object oCreature = OBJECT_SELF, int nAmbientEnable = 0, int nMovePattern = 0, string sMovePrefix = &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// Normally this function is called automatically to pause ambient behaviour after the party has &lt;br /&gt;
// been out of the creature's sight for a while. However, this function can be used to force a &lt;br /&gt;
// creature to temporarily cease ambient behaviour. Note that the creature will automatically  &lt;br /&gt;
// resume ambient behaviour when it perceives the player again. &lt;br /&gt;
void Ambient_Pause(object oCreature = OBJECT_SELF, int bCheckVisibility = TRUE);&lt;br /&gt;
&lt;br /&gt;
// Turns off ambient behaviour on a creature. The creature will resume ambient behaviour only &lt;br /&gt;
// after Ambient_Start() is called.&lt;br /&gt;
void Ambient_Stop(object oCreature = OBJECT_SELF);&lt;br /&gt;
&lt;br /&gt;
// Overrides the ambient animation pattern and animation frequency defined by the creature's template. &lt;br /&gt;
void Ambient_OverrideBehaviour(object oCreature, int nAnimPattern, float fAnimFreq);&lt;br /&gt;
&lt;br /&gt;
// Restores a creature's ambient animation behaviour to that defined in the creature's template.&lt;br /&gt;
void Ambient_RestoreBehaviour(object oCreature);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overriding Ambient Behaviour ==&lt;br /&gt;
&lt;br /&gt;
{{Variable table start}}&lt;br /&gt;
{{Variable table row|AMBIENT_ANIM_PATTERN_OVERRIDE | int | 0 | Index into [[ambient_ai.xls]]. Specifies the list of possible actions the creature can/will perform during an animation phase.&lt;br /&gt;
* 0: no animations.}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_FREQ_OVERRIDE | float | -1.0 | Animation frequency. The portion left of decimal specifies the minimum and the portion right of the decimal specifies the maximum number of animations to play during an animation phase. A value of -1.0 plays all animations in the animation pattern in the order listed in [[ambient_ai.xls]].}}&lt;br /&gt;
{{Variable table row| AMBIENT_ANIM_OVERRIDE_COUNT | int | | Used internally, do not modify}}&lt;br /&gt;
{{Variable table end}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Ambient behavior]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Backgrounds_tutorial&amp;diff=16128</id>
		<title>Backgrounds tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Backgrounds_tutorial&amp;diff=16128"/>
				<updated>2011-05-15T09:05:01Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Creating the background strings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This tutorial shows you how to modify the character backgrounds that can be selected during character generation. This is likely only of use if you are creating your own module or campaign as there would be no point to changing the background in the single player campaign unless you were also going to make extensive additions to support the new backgrounds  (e.g a completely new origin story). So the example we will use for this tutorial is a new stand alone module in which we completely replace the existing backgrounds. Changing backgrounds is especially useful if your module is set in a different lore to the main Dragon Age game or if you simply want to reduce the scope of the number of different backgrounds.&lt;br /&gt;
&lt;br /&gt;
We will also demonstrate some important principals that can be followed when modifying other core rules such as available races or classes. Most importantly we will add the new backgrounds in a way that doesn’t require any editing of core resources. By leaving the core resources alone we make our changes compatible with future patches which might otherwise overwrite our work. Furthermore keeping the core resources in tact allows us to make different modifications to different modules within the same toolset.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the reader should have some experience with scripting or coding in order to carry out the operations involved. The more you are relying on just copy pasting these instructions the more likely you are to make mistakes that you won’t know how to fix.&lt;br /&gt;
&lt;br /&gt;
== The backgrounds demo module ==&lt;br /&gt;
Any basic module will do for the purposes of this tutorial. If you want to create a test module for this tutorial then just create a simple module with a single area and a starting location. Make sure that the only thing selected in the module’s hierarchy is ''Core game resources''. This will ensure that the module is a stand alone module rather than an add-in to the single player campaign or some other module. For the purposes of this tutorial we will assume the module is called ''Backgrounds demo'' and I will prefix my resources with ''bdm_'' to be sure that they are distinct from any that are already in existence.&lt;br /&gt;
&lt;br /&gt;
We are going to completely replace the existing backgrounds with 3 new ones of our own. You can use new backgrounds in your module however you see fit. You could create entire origin stories for each one like in the single player campaign (possibly a major undertaking depending on length) or you can just use them to influence dialogue and plot options in the main part of your game.&lt;br /&gt;
&lt;br /&gt;
For our demo we are creating a  module in which the player starts off in a small human village (we will not be creating the details of this module so this is just for the purpose of an example). There is a wizard in this village who plays a pivotal role in the story. We allow the player to start as the wizard’s apprentice (if they are a mage) or as his servant (if they are human or elven and not a mage) or as a wandering traveller who has come to visit the wizard (if they are not human and not a mage). So the three backgrounds will be:&lt;br /&gt;
&lt;br /&gt;
* Servant&lt;br /&gt;
* Apprentice&lt;br /&gt;
* Traveller&lt;br /&gt;
&lt;br /&gt;
== Creating the background strings ==&lt;br /&gt;
Before we start modifying the 2DA files we are going to create some strings. Open the string editor in the toolset and create the following strings in your ‘Backgrounds demo’ talk table:&lt;br /&gt;
&lt;br /&gt;
[[Image:Back_tut_talk_table.png]]&lt;br /&gt;
&lt;br /&gt;
Your string IDs might be different to these so be sure to reference the right string ID in the instructions that follow. Simply replace these string Ids with your own.&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT!''' ''There is currently a bug in the game that causes it to crash if a background description ID has a value greater than 109 912 680. There is a [http://social.bioware.com/project/4695/ community fix] for this. Alternatively, you can go into your module’s properties and change the start ID for strings to be less than the critical value. After that the string editor will generate IDs in a range that won’t crash. Reset the start ID to its original value after you create the background descriptions (that way you have less to alter once Bioware fix this, and less risk of incompatibility with other mods).''&lt;br /&gt;
&lt;br /&gt;
You may have noticed that we have given two different names and descriptions for the traveller background depending on the PC’s race. We will say more about that in the following section.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|String editor}}&lt;br /&gt;
&lt;br /&gt;
== Modifying the 2DAs ==&lt;br /&gt;
The next thing we need to do is to modify the worksheets in backgrounds.xls. Be sure to make a copy of the spreadsheet first so that you leave the original intact. See LINK for general information about editing 2DA files. The first worksheet is called ‘backgrounds’; modify it to look like the following:&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_backgrounds.png]]&lt;br /&gt;
&lt;br /&gt;
Note that since 2DAs combine together to form M2DAs, and we don’t want the existing backgrounds in our game, we have overwritten the last two slots as unused1 and unused2,  even though we won’t be using them. The name and desc  string refs on this tab will be overwritten by the race specific ones on the names tab so we can leave those blank (AFAIK these string refs are not used providing the ones on the names tab are provided - also the tooltip string ref seems not to be used anywhere – if you prefer you can set these to something just to be safe).&lt;br /&gt;
&lt;br /&gt;
The three race columns determine which backgrounds can be selected by which race and the 3 class columns determine which background can be selected by which class. So, as you can see from the picture our Servant background is accessible to elf or human warriors and rogues, the Apprentice background can be selected by elf or human mages and the Traveller background by elf or dwarf warriors and rogues.&lt;br /&gt;
&lt;br /&gt;
The last three tabs indicate a starting ability for each background by race. Note that by default these columns are not hooked up into the character generation script (instead they are hard coded in the script) and are not used, but we will correct that later on when we do the scripting. You have to be careful here because the columns relate to the race IDs, so 1=dwarf, 2=elf and 3=human, which is in a different order to the other race columns in this table. The number in the column is an ability ID as given in ABI_base.xls. For this demo we have just given the same skill for each race for a given background. Servants get combat tactics, Apprentices get persuade and Travellers get survival.&lt;br /&gt;
&lt;br /&gt;
The next tab table to modify is background_names.&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_bg_names.png]]&lt;br /&gt;
&lt;br /&gt;
Make sure that the IDs here match the IDs in your string table. Note that for Apprentices and Servants we use the same strings regardless of race, but for the Traveller background we use different strings. This is to illustrate how you can divide a single background up into multiple names and descriptions. Internally they are both stored as the same background ID but during character generation a different name, description and icon can be shown to the player. In the single player game this was done with the Noble background by splitting it into human and dwarf Noble variations.&lt;br /&gt;
&lt;br /&gt;
NOTE – you must be careful when splitting a single background into different parts for each race. You must make both the names and descriptions different! If you don’t make the descriptions different then the engine will not recognise them as different even if they have different names.&lt;br /&gt;
&lt;br /&gt;
Now modify the background_desc table as follows&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_bg_desc.png]]&lt;br /&gt;
&lt;br /&gt;
Again note the distinct descriptions for the Traveller background.&lt;br /&gt;
&lt;br /&gt;
Now for the background_icons table. For this demo we will just use some of the existing icons but you may want to create your own icons to add here.&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_bg_icons.png]]&lt;br /&gt;
&lt;br /&gt;
The background_defaults table must have an entry for each race, background and class combination that is allowed. The ID column must be calculated as follows:&lt;br /&gt;
&lt;br /&gt;
(1000 * raceID)  + (100 * classID) + backgroundID&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tute_bg_defaults.png]]&lt;br /&gt;
&lt;br /&gt;
The label column should give a description of the row (AFAIK this is not used anywhere).&lt;br /&gt;
For this simple demo we will have each background combination spawn in the same place (the module default start location) but if you wanted different origins to spawn in different places then you can use the next two columns to specify this (AFAIK you have to write your own scripts to accomplish this though).&lt;br /&gt;
&lt;br /&gt;
In the template column you can put the name of a creature resource that you want to use as a template for this race/background/class combination. In the picture you can see that we have just used some default templates that shipped with the toolset but you can easily create your own. Note that only the inventory is copied across to the PC so if you want to create your own templates you do not need to alter anything on the creature except for their inventory.&lt;br /&gt;
&lt;br /&gt;
The name columns take string Ids. If you want to add your own names then you’ll have to create new strings in the string editor.&lt;br /&gt;
&lt;br /&gt;
Finally we have the ability column. As with the skill columns in the backgrounds table these IDs correspond to entries in the ABI_base.xls file. It should be noted that race, class and background are all possible sources of starting abilities so before you decide what to put in this column you should familiarise yourself with what skills are already being added in different parts of character generation in order to ensure that you don’t duplicate an ability somewhere.&lt;br /&gt;
&lt;br /&gt;
The final table is the chargen_preload table. The two columns here should exactly match the entries from the ID and Template columns of the previous table.&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_chargen_preload.png]]&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|2DA|2DA#Excel file formatting|Background.xls}}&lt;br /&gt;
&lt;br /&gt;
== Compiling and fixing the GDAs ==&lt;br /&gt;
Now compile backgrounds.xls and place the resulting GDAs into your ''AddIns\module_name\module\override'' directory.&lt;br /&gt;
Never place anything in your ''AddIns\module_name\core\override'' directory or it will affect other modules than the one you are editing.&lt;br /&gt;
&lt;br /&gt;
There used to be a [[Bug: ExcelProcessor doesn't handle row IDs above 8.3 million correctly|bug]] that prevented large string IDs from compiling correctly. This is now fixed. For the record, the old workaround was to edit the GDA files in the toolset to correct the string IDs manually, but you should now see that the string IDs are correct.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Compiling 2DAs|GDA}}&lt;br /&gt;
&lt;br /&gt;
== Creating the backgrounds plot ==&lt;br /&gt;
The background plot is used for keeping track of a PC’s background and can be used to affect conversation options.&lt;br /&gt;
 &lt;br /&gt;
The single player game uses a plot called gen00pt_backgrounds to keep track of the PC background. You can find it in the ''\_Global\Generic'' folder of the plots tab if you want to take a look. We will create a similar plot for our custom backgrounds. Create a new plot and call it ''bdm_000pt_backgrounds'' (My naming convention is to use 000 to indicate a resource that isn’t tied to any particular area – feel free to use your own convention but remember to update any references later in the tutorial). Add main plot flags as indicated in the picture below:&lt;br /&gt;
&lt;br /&gt;
[[Image:Back_tut_bg_plot.png]]&lt;br /&gt;
&lt;br /&gt;
You could also add some defined flags if you wanted. Defined flags can be used to return some combination of the main flags such as TRAVELLER or add some extra condition like FEMALE_APPRENTICE or ELVEN_APPRENTICE. Defined flags are beyond the scope of this tutorial however.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Designer Resources|Plot}}&lt;br /&gt;
&lt;br /&gt;
== Creating the scripts ==&lt;br /&gt;
We are not going to edit any of the original core game scripts, we will only be adding new scripts of our own. As we discuss how to do this you should examine the core scripts that are referred to, but under no circumstances should you make any changes to those files. By leaving the core scripts as they are we make our modification more compatible with any future patches that may be released. If you modified the core scripts and then a patch was released that overwrote those scripts you would lose your changes. Also keeping your modification contained within your own module allows you to make different modifications to different modules within the one toolset.&lt;br /&gt;
&lt;br /&gt;
Lets start off with a script to handle the character generation events that are normally handled by the module_core script. Create a new script called ''bdm_module_core''. It is up to you what directory structure to use for your scripts but it can be a good idea to keep all your scripts in a directory with your module name to make them distinct from the core scripts. Then if you are emulating the functionality of  a particular core script you can mirror the original directory structure underneath your main module folder. So in this case the module_core script is contained in the ''\_Core Scripts'' folder so we will put our bdm_module_core in ''\Backgrounds demo\_Core Scripts'' (the underscore ensures the core directories come first – looks like Bioware accidentally created one without it! I’m pretty sure Core and _Core are meant to be the same directory). Organising things this way will really help with keeping track of your scripts.&lt;br /&gt;
&lt;br /&gt;
The ''bdm_module_core'' script should contain the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;global_objects_h&amp;quot;&lt;br /&gt;
void main(){&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEvent = GetEventType(ev); //extract event type from current event&lt;br /&gt;
    int nEventHandled = FALSE; //keep track of whether the event has been handled&lt;br /&gt;
    switch(nEvent){&lt;br /&gt;
        case EVENT_TYPE_MODULE_START:{&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Initiate character generation.&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            PreloadCharGen(); //preloads resources for character generation&lt;br /&gt;
            StartCharGen(GetHero(),0,TRUE); //initiates character generation&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        default:&lt;br /&gt;
        {&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Handle character generation events sent by the engine.&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            if ((nEvent &amp;gt;= EVENT_TYPE_CHARGEN_START &amp;amp;&amp;amp; nEvent &amp;lt;= EVENT_TYPE_CHARGEN_END) &lt;br /&gt;
                || nEvent == EVENT_TYPE_PLAYERLEVELUP )&lt;br /&gt;
            {&lt;br /&gt;
                HandleEvent(ev, R&amp;quot;bdm_sys_chargen.ncs&amp;quot;);&lt;br /&gt;
                nEventHandled = TRUE;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    if (!nEventHandled) { //If this event wasn't handled by this script, let the core script try&lt;br /&gt;
        HandleEvent(ev, RESOURCE_SCRIPT_MODULE_CORE);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now go to ''file &amp;gt; manage modules'' and open the properties for your module and set the script property to point at this script.&lt;br /&gt;
&lt;br /&gt;
Our new script handles some of the events that are usually handled by the module_core script. Once it has handled the event it chooses whether or not to pass the event on to module_core. The first event that we handle is EVENT_TYPE_MODULE_START, which is where we initiate character generation. In this case we pass the event on to the core script to handle after we have done what we need to.&lt;br /&gt;
&lt;br /&gt;
NOTE : you may find that you don't need to change any other scripts. It's not clear what the scripts in the rest of this section are trying to do - see discussion.&lt;br /&gt;
&lt;br /&gt;
The second thing we handle is actually a group of events. If you look in the module_core script you will see that right down the bottom in the default event handler is some code that looks just like the code we have added in our default event, with a couple of little differences. Instead of passing the character generation events to the sys_chargen.ncs script we are going to pass it to our own script called ''bdm_sys_chargen.ncs'' which we will write shortly. If we catch one of those character generation events then we want to handle it ourselves and prevent the core script from handling it so we set nEventHandled = TRUE. Note that any other event that is caught by the default handler but isn’t a character generation event is going to go straight on through to the core script.&lt;br /&gt;
&lt;br /&gt;
Before we create the ''bdm_sys_chargen'' script we are going to need some new constants defined. Create a new script called ''bdm_2da_constants_h'' and put it in folder ''\Backgrounds demo\_Core Includes''. Now add the following to this script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// -----------------------------------------------------------------------------&lt;br /&gt;
// Backgrounds - rules/backgrounds.xls&lt;br /&gt;
// -----------------------------------------------------------------------------&lt;br /&gt;
const int BACKGROUND_SERVANT = 1;&lt;br /&gt;
const int BACKGROUND_APPRENTICE = 2;&lt;br /&gt;
const int BACKGROUND_TRAVELLER = 3;&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These constants provide a way for us to refer to the background IDs that we defined in the 2DA files without having to remember the numbers. Constants like this also make your code more readable.  If you need to add more new items to 2DAs when you are modding something else you can also add constants for them here. From now on we will be using these background constants instead of the original single player background constants that you can find in the ''2da_constants_h'' script. That means we’d better find all the places where those constants are used and update them with our own scripts.&lt;br /&gt;
&lt;br /&gt;
Create another new script and call it ''bdm_sys_chargen'' and put it in a folder called ''\Backgrounds demo\_Systems''. Put the following code in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;bdm_sys_chargen_h&amp;quot;&lt;br /&gt;
#include &amp;quot;log_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
const int CHARGEN_QUICKSTART_QUICK = 0;&lt;br /&gt;
const int CHARGEN_QUICKSTART_NORMAL = 1;&lt;br /&gt;
const int CHARGEN_QUICKSTART_ADVANCED = 2;&lt;br /&gt;
&lt;br /&gt;
void _RunChargen(int nRace, int nClass, object oChar, int nBackground)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    Chargen_InitializeCharacter(oChar);&lt;br /&gt;
    Chargen_SelectGender(oChar,GENDER_MALE);&lt;br /&gt;
    Chargen_SelectRace(oChar,nRace);&lt;br /&gt;
    Chargen_SelectCoreClass(oChar,nClass);&lt;br /&gt;
    Chargen_SelectBackground(oChar, nBackground,FALSE);&lt;br /&gt;
&lt;br /&gt;
    int nEquipIdx = Chargen_GetEquipIndex(nRace, nClass, nBackground);&lt;br /&gt;
    Chargen_InitInventory(oChar,0,nEquipIdx);&lt;br /&gt;
    Chargen_SpendAttributePoints(oChar,PROPERTY_ATTRIBUTE_STRENGTH, 3,FALSE);&lt;br /&gt;
    Chargen_SpendAttributePoints(oChar,PROPERTY_ATTRIBUTE_DEXTERITY, 2,FALSE);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    event   ev              =   GetCurrentEvent();&lt;br /&gt;
    int     nEventType      =   GetEventType(ev);&lt;br /&gt;
    object  oChar           =   GetEventObject(ev,0);&lt;br /&gt;
&lt;br /&gt;
    int nMode;&lt;br /&gt;
    int nInt0 = GetEventInteger(ev,0);&lt;br /&gt;
    int nInt1 = GetEventInteger(ev,1);&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    // Debug Data.&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    Log_Trace(LOG_CHANNEL_EVENTS_CHARGEN,&amp;quot;bdm_sys_chargen&amp;quot;,&amp;quot;Chargen Event:&amp;quot; + Log_GetEventNameById (nEventType) &lt;br /&gt;
               + &amp;quot; &amp;quot; + ToString(nInt0) + &amp;quot;,&amp;quot; + ToString(nInt1), oChar);&lt;br /&gt;
&lt;br /&gt;
    int nEventHandled = FALSE;&lt;br /&gt;
&lt;br /&gt;
    switch (nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        // ----------------------------------------------------------------------&lt;br /&gt;
        // This fires when the player selects the icon corresponding to any of&lt;br /&gt;
        // the available backgrounds&lt;br /&gt;
        //&lt;br /&gt;
        // nInt0 - Constant BACKGROUND_* integer&lt;br /&gt;
        // ----------------------------------------------------------------------&lt;br /&gt;
        case EVENT_TYPE_CHARGEN_SELECT_BACKGROUND: {&lt;br /&gt;
            int nBackground = nInt0;&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Set the background on the player and reinitialize plot flags&lt;br /&gt;
            // for the background&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            Chargen_InitializeCharacter(oChar,TRUE);&lt;br /&gt;
            Chargen_SelectGender(oChar,GetCreatureGender(oChar));&lt;br /&gt;
            Chargen_SelectRace(oChar,GetCreatureRacialType(oChar));&lt;br /&gt;
            Chargen_SelectCoreClass(oChar,GetCreatureCoreClass(oChar));&lt;br /&gt;
&lt;br /&gt;
            bdm_Chargen_SelectBackground(oChar, nBackground, FALSE);&lt;br /&gt;
            bdm_Chargen_SetupPlotFlags(oChar);&lt;br /&gt;
&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Generate the index into the equipment template 2da and&lt;br /&gt;
            // then load the starting equipment based on the data returned.&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            int nClass = GetCreatureCoreClass(oChar);&lt;br /&gt;
            int nRace = GetCreatureRacialType(oChar);&lt;br /&gt;
            int nEquipIdx = Chargen_GetEquipIndex(nRace, nClass, nBackground);&lt;br /&gt;
           Chargen_InitInventory(oChar,0,nEquipIdx);&lt;br /&gt;
            nEventHandled = TRUE;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        case EVENT_TYPE_CHARGEN_END: {&lt;br /&gt;
            nMode = nInt0;&lt;br /&gt;
            int nQuickStart = nInt1;&lt;br /&gt;
            // 0 - quickstart&lt;br /&gt;
            // 1 - normal    \&lt;br /&gt;
            // 2 - advanced  / treat as the same&lt;br /&gt;
            Log_Trace(LOG_CHANNEL_CHARACTER,&amp;quot;bdm_sys_chargen&amp;quot;,&amp;quot;MODE: &amp;quot; + IntToString(nMode) &lt;br /&gt;
                       + &amp;quot;, Quick Start: &amp;quot; + IntToString(nQuickStart));&lt;br /&gt;
            if (nMode == CHARGEN_MODE_CREATE &amp;amp;&amp;amp; nQuickStart == CHARGEN_QUICKSTART_QUICK){&lt;br /&gt;
                Log_Trace(LOG_CHANNEL_CHARACTER,&amp;quot;bdm_sys_chargen&amp;quot;,&amp;quot;Setting default values for player character&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    int nRandClass = abs((GetLowResTimer()%3)+1);&lt;br /&gt;
&lt;br /&gt;
                    if(nRandClass == CLASS_ROGUE || nRandClass == CLASS_WARRIOR)&lt;br /&gt;
                    {&lt;br /&gt;
                        _RunChargen(RACE_HUMAN, nRandClass, oChar, BACKGROUND_SERVANT );&lt;br /&gt;
&lt;br /&gt;
                        WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT, TRUE);&lt;br /&gt;
                    }&lt;br /&gt;
                    else // mage&lt;br /&gt;
                    {&lt;br /&gt;
                        _RunChargen(RACE_HUMAN, nRandClass, oChar, BACKGROUND_APPRENTICE );&lt;br /&gt;
                        WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE, TRUE);&lt;br /&gt;
                    }&lt;br /&gt;
                    Chargen_SetNumTactics(oChar);&lt;br /&gt;
                    SetCanLevelUp(oChar,Chargen_HasPointsToSpend(oChar));&lt;br /&gt;
                    SendEventModuleChargenDone(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
                    nEventHandled = TRUE;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
    }    //end switch&lt;br /&gt;
&lt;br /&gt;
    if (!nEventHandled){&lt;br /&gt;
        HandleEvent(ev, R&amp;quot;sys_chargen.ncs&amp;quot;);&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;
There are two events in the original sys_chargen script that we need to replace because they deal with backgrounds. The first of these is EVENT_TYPE_CHARGEN_SELECT_BACKGROUND and the other is EVENT_TYPE_CHARGEN_END. For the second event we only need to change the case where the character is being created in quickstart mode, so we just handle that section of the code. The objective here is to change only as much as we need to and then pass any remaining events through to the original sys_chargen script. Take some time to compare the new script with Bioware’s ''sys_chargen'' script .&lt;br /&gt;
&lt;br /&gt;
You will notice that we include a script called ''bdm_sys_chargen_h'' and that we use some functions with a ''bdm_'' prefix. Those functions are contained in that include file which we’ll write now. Essentially these are modifications of a couple of functions from the ''sys_chargen_h'' include file. Create a new script and call it ''bdm_sys_chargen_h''. Put it in folder ''\Backgrounds demo\_Systems\Includes'' and add the following code:&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;bdm_2da_constants_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_bdm_000pt_backgrounds&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void bdm_Chargen_SelectBackground(object oChar, int nBackground, int bUnApply = FALSE)&lt;br /&gt;
{&lt;br /&gt;
     Log_Chargen(&amp;quot;bdm_Chargen_SelectBackground&amp;quot;,&amp;quot;-- &amp;quot; + (bUnApply?&amp;quot;Un&amp;quot;:&amp;quot;&amp;quot;) +&amp;quot;Selecting BG: &amp;quot; + ToString(nBackground),oChar);&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    // 1. Set the background variable&lt;br /&gt;
    //          - Create creature property (or check what we used so far&lt;br /&gt;
    //          - We don't set backgrounds on non player generated chars.&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    if (bUnApply)&lt;br /&gt;
    {&lt;br /&gt;
        SetCreatureProperty(oChar, PROPERTY_SIMPLE_BACKGROUND, 0.0, PROPERTY_VALUE_BASE);&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
       SetCreatureProperty(oChar, PROPERTY_SIMPLE_BACKGROUND, IntToFloat(nBackground), PROPERTY_VALUE_BASE);&lt;br /&gt;
    }&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    // 2. Give one skill&lt;br /&gt;
    //    - retrieve the skill that is granted by the background from backgrounds.xls&lt;br /&gt;
    //    - give it to the player.&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    int nAbility = ChargenGetBackgroundSkill(GetCreatureRacialType(oChar), nBackground);&lt;br /&gt;
    if (nAbility)&lt;br /&gt;
    {&lt;br /&gt;
        _AddAbility (oChar, nAbility, bUnApply);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bdm_Chargen_SetupPlotFlags(object oChar)&lt;br /&gt;
{&lt;br /&gt;
    int nRace       =  GetCreatureRacialType(oChar);&lt;br /&gt;
    int nBackground = GetPlayerBackground(oChar);&lt;br /&gt;
&lt;br /&gt;
    Log_Trace(LOG_CHANNEL_CHARACTER,&amp;quot;bdm_sys_chargen_h&amp;quot;,&amp;quot;Setting plot flags, race: &amp;quot; &lt;br /&gt;
               + IntToString(nRace) + &amp;quot;, background: &amp;quot; + IntToString(nBackground));&lt;br /&gt;
&lt;br /&gt;
    // First, init all flags (debug setup)&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT,FALSE);&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE,FALSE);&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_DWARF_TRAVELLER,FALSE);&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_ELF_TRAVELLER,FALSE);&lt;br /&gt;
&lt;br /&gt;
    switch (nBackground)&lt;br /&gt;
    {&lt;br /&gt;
        case BACKGROUND_SERVANT:&lt;br /&gt;
        {&lt;br /&gt;
            WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT,TRUE); break;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        case BACKGROUND_APPRENTICE:&lt;br /&gt;
        {&lt;br /&gt;
            WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE,TRUE); break;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        case BACKGROUND_TRAVELLER:&lt;br /&gt;
        {&lt;br /&gt;
            switch(nRace)&lt;br /&gt;
            {&lt;br /&gt;
                case RACE_DWARF: WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_DWARF_TRAVELLER,TRUE); break;&lt;br /&gt;
                case RACE_ELF: WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_ELF_TRAVELLER,TRUE); break;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lets examine these two functions. First you should compare them to their original versions. For ''bdm_Chargen_SelectBackground()'' we have actually made a more generic version of the function that should work with any backgrounds. We have removed the hard coded values for the background abilities and now use the function ChargenGetBackgroundSkill() which actually gets the background skill from the backgrounds 2DA file that we edited earlier (recall the last three columns that give a skill depending on background and race). If you need fancier logic than just reading the values form the GDA (e.g. like Bioware’s logic for the Noble background) then you can always go back to hard coding them the way Bioware did.&lt;br /&gt;
&lt;br /&gt;
The second function is ''bdm_Chargen_SetupPlotFlags()'' which does just what it says. Remember the plot we created earlier? Here we set the appropriate flag based on race and background.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Script}}&lt;br /&gt;
&lt;br /&gt;
== Testing that everything works ==&lt;br /&gt;
Now compile your scripts and export your module. Also, make sure that you export your talk table.&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT!''' ''Always make sure you empty your \Dragon Age\packages\core\override folder after doing an export. Due to a bug in the current toolset your single player game will become damaged if you don’t do this before playing.''&lt;br /&gt;
&lt;br /&gt;
You should now be able to run your game and see the backgrounds you created appear in character generation. If you want to test that the background plots have been set correctly, add an NPC to the start area and create a conversation for them in which each line is switched according to a background plot flag. You can also check that the character is receiving the abilities that we set in the 2DAs.&lt;br /&gt;
&lt;br /&gt;
'''NOTE''' ''There seems to be no way to change the popup message that comes up at the beginning of character generation. Altering the Pre-chargen string ID in the loadhints GDA does not seem to do anything.''&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Exporting a module}}&lt;br /&gt;
&lt;br /&gt;
== Optional extras ==&lt;br /&gt;
There are a couple of other Bioware scripts that reference the background constants. They are not essential to modify because they are not used anywhere by default. The genev_tutorial script uses a background check but unless you plan on firing the tutorial from your module then you won’t have need of it. Also there is at least one debug script that makes use of the original single player backgrounds (to grant a background plot flag to the PC) so if you want similar debug functionality you may have to roll your own function.&lt;br /&gt;
&lt;br /&gt;
== Race &amp;amp; Gender descriptions ==&lt;br /&gt;
If your module is not set in Ferelden, you may wish to change the descriptions of the Race and Gender buttons that appear during Character Creation.&lt;br /&gt;
&lt;br /&gt;
The Race descriptions are in the Description column of the RACE_base 2DA, so you can replace them with new strings. As before, until the bug is fixed, use a string id in the 100000000 range. &lt;br /&gt;
&lt;br /&gt;
Unfortunately, the gender description is hard-coded in the game as string id 377283. Fortunately, you can make a  [[String_editor#Editing_a_string_with_a_specific_id | local version]] of this string, which only applies to your campaign. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you an advanced user who is familar with the [[UI_Tutorial_%28draft%29 | UI Tutorial]], it's set in the GUI's Localization.as file as LOC_GENDER_DESCRIPTION = 377283, which is then used in the RaceGenderScene.as file. after editing the Localization.as file, you compile it and inject it into the appropriate .gfx'es.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
In this tutorial we have demonstrated a way to modify the backgrounds used in the game without altering any of the core scripts. It is expected that a similar approach could be taken to modding other aspects of the game such as adding classes or races. In these cases the scripts that were created in this tutorial could be extended to handle other parts of the character generation process such as class and race selection.&lt;br /&gt;
&lt;br /&gt;
[[Category:Character generation]]&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=SetMaxHealth&amp;diff=16118</id>
		<title>SetMaxHealth</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=SetMaxHealth&amp;diff=16118"/>
				<updated>2011-05-11T07:24:16Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{dafunction&lt;br /&gt;
|name=SetMaxHealth&lt;br /&gt;
|brief=Set object's maximum health&lt;br /&gt;
|param1type=object&lt;br /&gt;
|param1name=oObject&lt;br /&gt;
|param1desc=the object that we are modifying&lt;br /&gt;
|param2type=int&lt;br /&gt;
|param2name=nHealth&lt;br /&gt;
|param2desc=the new maximum health value for the object&lt;br /&gt;
|returntype=void&lt;br /&gt;
|returndesc=&lt;br /&gt;
|sourcefile=script.ldf&lt;br /&gt;
|sourcemodule=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- This section contains the full description from the functions comments. Do not change unless you are confident these are incomplete or incorrect. --&amp;gt;&lt;br /&gt;
Set object's maximum health.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
This function doesn't seem to work for creatures.&lt;br /&gt;
&lt;br /&gt;
It appears that Chargen_ModifyCreaturePropertyBase with PROPERTY_DEPLETABLE_HEALTH will increase or decrease maximum health by the specified amount. This workaround has not yet been tested exhaustively, but it is based on the Bioware code in sys_autoscale_h.&lt;br /&gt;
&amp;lt;!-- == Examples == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains examples transcluded from the snippet library. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- == See also == --&amp;gt;&lt;br /&gt;
&amp;lt;!-- This section contains links to articles, functions or constant groups. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Stats functions]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Cutscene_tutorial&amp;diff=16089</id>
		<title>Cutscene tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Cutscene_tutorial&amp;diff=16089"/>
				<updated>2011-04-20T16:44:46Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Adding dialogue */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox cutscenes}}&lt;br /&gt;
&lt;br /&gt;
[[Cutscene]]s can be stand-alone cinematic sequences that are triggered by scripts in the course of the game, or they can be inserted into [[conversation]]s in place of the simplified cinematics that conversations can automatically generate.&lt;br /&gt;
&lt;br /&gt;
Our example situation in this tutorial will serve as the beginning of a conversation between the player and two NPCs. The player has just arrived at the campsite where these two NPCs are staying. He walks up to the fire. One of the NPCs is happy to see the player and greets him, but the other is distrustful. The two share a brief exchange to establish this before the interactive part of the conversation begins.&lt;br /&gt;
&lt;br /&gt;
== Creating a new cutscene ==&lt;br /&gt;
&lt;br /&gt;
To create a brand new blank cutscene resource, create a new resource in the usual way:&lt;br /&gt;
&lt;br /&gt;
[[Image:New resource.png]]&lt;br /&gt;
&lt;br /&gt;
The result is opened in the cutscene editor.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene new.png|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
There are two basic sections to the cutscene editor; the viewports (top) and the timeline (bottom).&lt;br /&gt;
&lt;br /&gt;
=== Viewports ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Viewports can be attached to various cameras to preview what they can see&lt;br /&gt;
* Add a &amp;quot;Safe Frame&amp;quot; to camera viewports to ensure the correct aspect ratio&lt;br /&gt;
* Set a viewport to &amp;quot;User&amp;quot; to see where cameras are positioned from another perspective. This can be done by selecting &amp;quot;Detach From Camera&amp;quot; in the viewport's right-click menu in the title bar&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The camera viewports in the cutscene editor work similarly to the viewports in the stage editor. You can set the number and layout of viewports under the &amp;quot;View&amp;quot; menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial viewport layout.png]]&lt;br /&gt;
&lt;br /&gt;
And for each individual viewport you can select which camera it's showing and set other display options by right-clicking on the title bar of the viewport:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial viewport properties.png]]&lt;br /&gt;
&lt;br /&gt;
When you set a viewport to show the view through one of the cutscene's cameras, it's a good idea to turn on that viewport's &amp;quot;Safe Frame&amp;quot; option as well. This will put a border on the viewport showing what will be visible when the cutscene plays.&lt;br /&gt;
&lt;br /&gt;
Note that when you play the cutscene in the cutscene editor, only the currently selected viewport (the one with the blue title bar) will show the cutscene &amp;quot;live&amp;quot; - the others won't update the view displayed in them until they're selected. To preview the cutscene as the player would see it, then, you should set one of the viewports to &amp;quot;Active Camera&amp;quot; and ensure that this viewport is selected when you play the cutscene in the editor. If the &amp;quot;Active Camera&amp;quot; viewport turns gray, try setting the cutscene property &amp;quot;Enable Level Effects&amp;quot; to false.&lt;br /&gt;
&lt;br /&gt;
=== Timeline ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* There is always exactly one MASTER object in a cutscene.&lt;br /&gt;
* Each active object is listed on the timeline, with multiple &amp;quot;tracks&amp;quot; for each.&lt;br /&gt;
* All objects have position tracks (divided into X, Y and Z tracks). Some objects have additional built-in tracks.&lt;br /&gt;
* Other actions and effects can be added to generic tracks. Objects can have as many generic tracks as you want.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Below the viewport is the timeline. Along the top of the timeline is a time scale; it can be set either to show frames (at 30 frames per second) or milliseconds by changing the &amp;quot;Time Scale&amp;quot; property if the cutscene in the object inspector.  A marker indicates what point in the timeline the viewports are currently showing.&lt;br /&gt;
&lt;br /&gt;
Below are a set of rows containing the various actors, cameras, and other objects active in the cutscene. This is where most of the editing is going to take place. Each object will have a number of &amp;quot;tracks&amp;quot;, which will contain commands that are sent to the actors at particular times in the course of the cutscene.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial timeline.png]]&lt;br /&gt;
&lt;br /&gt;
The first object in the track list is the &amp;quot;MASTER&amp;quot; object. This is a special object that every cutscene has exactly one of. The MASTER object is the cutscene equivalent to the root node of a conversation tree, a repository for global settings and effects. For example the MASTER object contains the track that determines which camera is active at any given time. The MASTER object cannot be deleted. By default, a MASTER object appears in the cutscene editor as a small greenish sphere; you can change the MASTER object's appearance in the cutscene option settings.&lt;br /&gt;
&lt;br /&gt;
A new cutscene also has a camera, called Camera 1. This camera can be deleted or renamed if you like; we can add new cameras as needed later on.&lt;br /&gt;
&lt;br /&gt;
Every object has &amp;quot;Position&amp;quot; and &amp;quot;Orientation&amp;quot; tracks that control their locations in space. Cameras also have a FOV (field of view) track.&lt;br /&gt;
&lt;br /&gt;
Objects can have other &amp;quot;generic&amp;quot; tracks added by the editor as needed. These generic tracks contain all the other commands and directions we can give.&lt;br /&gt;
&lt;br /&gt;
== The setting of the cutscene ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* The MASTER object should be moved somewhere near the center of your cutscene.&lt;br /&gt;
* You can optionally set a stage for your cutscene, enabling stage-related actions for objects.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Establishing the setting of a cutscene is done in the object inspector in the group of properties labeled &amp;quot;Setting&amp;quot;. The most important of these is the &amp;quot;Area&amp;quot; property, which allows you to set the cutscene in an existing [[area]]. We already have a suitable area that was created in an earlier tutorial; the area &amp;quot;great_outdoors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
By default the MASTER object and Camera 1 will be located at the coordinates 0,0,0 in the area. You'll want to move the camera to the appropriate location within the area using standard [[3D control]]s for movement and view management. The MASTER object is invisible when the cutscene is played in-game so it usually doesn't matter where you put it. However, there are some settings that depend on the MASTER object's location - for example, you can set level-of-detail for models so that the model's LOD varies depending on how close it is to the MASTER object - so it's probably a good idea to put MASTER somewhere near the middle of where you'll be having the cutscene's action take place.&lt;br /&gt;
&lt;br /&gt;
You can also set a stage for the cutscene. This is optional, but setting a stage enables &amp;quot;Jump to Stage Place&amp;quot; and &amp;quot;Jump to Stage Camera&amp;quot; actions that could help make setting the cutscene up easier if you already have a good stage defined in the area.&lt;br /&gt;
&lt;br /&gt;
=== Adding objects and creatures ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Objects already present in the area the cutscene is set in are inactive by default. You need to activate them to control them.&lt;br /&gt;
* Other objects can be added from the resource palette as normal.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
All of the objects that are normally present in the area (such as creatures and placeables) will be visible in the cutscene editor, but they'll all initially be marked as &amp;quot;inactive&amp;quot;. This means that, although they'll be visible in the cutscene when it plays, they won't be controllable; they'll just do whatever ambient activities they would be doing normally. In the case of our campsite area there are two creatures that were placed here in the area editor; the happy camper, named camp_happy, and the angry camper, named camp_angry. We need to seize control of them to make them active participants in the cutscene's activities. To make them active, right-click on them and select &amp;quot;activate objects&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene activate object.png]]&lt;br /&gt;
&lt;br /&gt;
The object will then become an active object in the cutscene, getting its own entry in the timeline that will allow you to control its actions.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene object activated.png]]&lt;br /&gt;
&lt;br /&gt;
We'll activate both of these campers since they'll both be taking part in the cutscene's dialogue.&lt;br /&gt;
&lt;br /&gt;
You can also add objects that aren't normally a part of the area. Simply open the object palette, select the creature or placeable you wish to use in the cutscene, and then click in the viewport to add the object to that location. It will automatically be made active and get an entry in the timeline. The player won't see these objects during regular play, since they're not a part of the area - they're only in the cutscene.&lt;br /&gt;
&lt;br /&gt;
If you want to make an area object disappear during the cutscene you'll need to activate it (allowing you to control it) and then add a track with an action that makes it invisible in the first frame. It will go back to normal again when the cutscene ends and the game resumes, cutscenes are run entirely separate from the main action of the game and have no direct effects on it.&lt;br /&gt;
&lt;br /&gt;
=== Adding the player ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Use the &amp;quot;Mapping Tag&amp;quot; property on an actor to make the game replace it with another object (such as PLAYER) at run-time.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Normally we don't have to worry about placing the player in an area since the player controls his own movements and actions. But when we're doing a cutscene we can control the player just like any other actor, so we'll need a way to insert the player as an active object. Furthermore, since we'll have no idea what the player is going to look like at any given moment, we'll need to have a way to insert the player as he appears in the game when the cutscene begins.&lt;br /&gt;
&lt;br /&gt;
This is done by inserting a &amp;quot;dummy&amp;quot; virtual actor and then setting the actor's &amp;quot;Mapping Tag&amp;quot; property to the special &amp;quot;PLAYER&amp;quot; tag. &lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene dummy player.png|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
It doesn't matter what the dummy actor looks like now, it will be replaced with the player's character later on, so we'll just use a default male human model to make it both simple and obvious.&lt;br /&gt;
&lt;br /&gt;
There are ways to tweak the way the cutscene plays based on other characteristics of the player, for example by modifying the position of the camera to account for the player's height or by adding additional dummies to represent followers. We won't go into these more advanced topics in this tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Adding cameras ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Remember to enable Safe Frame when attaching a viewport to a camera.&lt;br /&gt;
* Use an &amp;quot;Active Camera&amp;quot; viewport to preview the cutscene.&lt;br /&gt;
* Use a &amp;quot;User&amp;quot; viewport to see camera positions from the outside. This can be done by selecting &amp;quot;Detach From Camera&amp;quot; in the viewport's right-click menu in the title bar.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
We could film a cutscene entirely from one camera if we liked, either as a single static shot or by moving the camera around to new positions as needed. It's easier and more convenient in most cases just to add several different cameras, however, and use the &amp;quot;Active Camera&amp;quot; track on the MASTER object to switch between them.&lt;br /&gt;
&lt;br /&gt;
For our cutscene we're going to want three different cameras; one camera that's a wide shot showing the player arriving at the campfire, one camera focused on the angry camper, and one focused on the happy camper. We could add more than just these three to make the scene even more dynamic but for simplicity we'll stick to just those for now. We can add more later.&lt;br /&gt;
&lt;br /&gt;
Cameras are added by right-clicking in the viewport and selecting &amp;quot;Insert &amp;amp;rarr; Camera&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene insert camera.png]]&lt;br /&gt;
&lt;br /&gt;
You can then position them using standard [[3D control]]s. To make it easier to get the camera set up with the correct view, a good technique is to set one of the viewports to display the camera's feed; you can then reorient and reposition the camera using that viewport's camera controls while getting immediate feedback as to what the camera will see in its new state.&lt;br /&gt;
&lt;br /&gt;
We're also going to rename the three cameras at this point with names intended to remind us of what their purposes are. We'll name them &amp;quot;Arrival Camera&amp;quot;, &amp;quot;Happy Camera&amp;quot;, and &amp;quot;Angry Camera&amp;quot;. We'll want &amp;quot;Arrival Camera&amp;quot; to be active initially, so we may as well use the original camera for this role; it's already set active by default. We'll see how to switch which camera is active later in this tutorial.&lt;br /&gt;
&lt;br /&gt;
We now have all the basic props we need to get the cutscene going.&lt;br /&gt;
&lt;br /&gt;
== Adding an animation to an actor ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Set the &amp;quot;Pose&amp;quot; property for actors to make them breathe and fidget naturally when not doing other animations.&lt;br /&gt;
* Other animations are set by adding &amp;quot;Play Animation&amp;quot; actions to a generic track.&lt;br /&gt;
* Animation filenames are often arcane and hard to find.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you play the cutscene now the first thing you'll probably notice is that the actors are all standing perfectly motionless. Normally someone who's standing still isn't really standing ''perfectly'' still; they breathe, they shift their weight from foot to foot, and so forth. Since almost every actor we use is going to need to do this we don't want to have to spend a lot of effort setting it up, and fortunately we don't have to. Every actor has a &amp;quot;Pose&amp;quot; property in the object inspector. Simply set this pose to &amp;quot;Standing Neutral&amp;quot; and the actors will display this default subtle movement whenever no other animations are being explicitly imposed on them.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene set pose.png]]&lt;br /&gt;
&lt;br /&gt;
Our next task is somewhat less trivial; we want to show the player walking up to the fire. We're going to have to add a walking animation to the player's actor that runs for a short period of time and then stops.&lt;br /&gt;
&lt;br /&gt;
To do this we'll need to add a new track to the actor's timeline. Right-click on the actor's entry in the timeline and select &amp;quot;Add Track&amp;quot; from the resulting menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene add track.png]]&lt;br /&gt;
&lt;br /&gt;
The new track will be named &amp;quot;New Track&amp;quot; by default and will start out empty. Actors in cutscenes will sometimes have dozens of tracks directing their actions so we'll want to rename the track to something a little more informative. In this case we'll name it &amp;quot;Walk to fire&amp;quot;. To have it actually cause the player's actor to walk to the fire we'll need to add a &amp;quot;[[Play animation]]&amp;quot; action to it. Right-click on the track and select &amp;quot;Add Action&amp;quot; to get the menu to select this.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene add action.png]]&lt;br /&gt;
&lt;br /&gt;
The action will be added starting at the point you're currently viewing in the timeline, so you may wish to move the timeline's time slider back to the beginning before adding this animation. You can reposition an action along the timeline simply by dragging it with the mouse.&lt;br /&gt;
&lt;br /&gt;
Initially the action has no animation associated with it. To set the animation, select the action in the timeline and then in the Object Inspector go to the &amp;quot;Animation&amp;quot; property and click on the ellipsis ([[Image:ellipsis.png]]) button.&lt;br /&gt;
&lt;br /&gt;
Unfortunately this is where things turn a bit arcane since the names of the various animation files are often very unclear and not all will appear in the default list. You may need to resort to trial and error to find one you like, but there are many hundreds of animations available in the game's resources so this could take some time. See [[animation list]] and [http://social.bioware.com/project/30/#files Beerfish Excel Utilities] for a list of many of them.&lt;br /&gt;
&lt;br /&gt;
Note that only a single animation can play at any time on a given track. However, it is possible to have multiple animations for a character, each of which must be on a different track. This is essential in order to be able to blend animations together as detailed in [[Play_animation#Blending_Animations]]. Animation blending is necessary in order to have your characters transition seamlessly from one animation to another, which is essential to making character movement look natural.&lt;br /&gt;
&lt;br /&gt;
In this case the animation we want, &amp;quot;mh.dg_f_5p&amp;quot; (&amp;quot;male human dialog forward five paces&amp;quot;), doesn't appear in the default list of animations available in the animation picker. You'll need to click the ellipsis button next to the &amp;quot;Custom Animation&amp;quot; field and find it in the complete list of all animation resources.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene finding an animation.png]]&lt;br /&gt;
&lt;br /&gt;
If you try playing the cutscene now you'll see that the player's actor will spend a little over five seconds walking and then come to a natural stop - about as long as we needed. But the actor will be animated in place, his legs taking steps but not actually moving him anywhere. This is where position keys and GAD comes in.&lt;br /&gt;
&lt;br /&gt;
== Moving an actor ==&lt;br /&gt;
&lt;br /&gt;
=== Position and orientation keys ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Objects be moved over time by setting &amp;quot;key frames&amp;quot; on their position and orientation tracks.&lt;br /&gt;
* Intermediate frames are interpolated between key frames.&lt;br /&gt;
* You can set the curve type between key frames with the &amp;quot;transition out&amp;quot; property for each key.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Every object in a cutscene has a pre-defined &amp;quot;Position&amp;quot; track with three sub-tracks for its X, Y and Z coordinates. Most objects also have a pre-defined &amp;quot;Orientation&amp;quot; track with three subtracks for roll, pitch, and yaw. These tracks can be used to cause an object to move around within the area over the course of the cutscene.&lt;br /&gt;
&lt;br /&gt;
Movement is handled by setting the position and orientation of objects at specific points in time, called key frames, and then interpolating intermediate positions and orientations. To set a key frame, right-click on the actor's entry in the timeline and select &amp;quot;key position&amp;quot;. This will set a key for the current position and orientation at the current time in the timeline. You can set position and orientation keys separately if you like. Since this operation is so common there's a very convenient shortcut for it; &amp;quot;k&amp;quot; inserts a key for the currently selected object's position and orientation, &amp;quot;p&amp;quot; inserts a key for its position, and &amp;quot;o&amp;quot; inserts a key for its orientation. Alternately, select the object and click the key command in the toolbar: [[Image:IconKey.png]]&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene key selection.png]]&lt;br /&gt;
&lt;br /&gt;
For our purposes right now all we'll need to do is set a key frame at the beginning of the timeline. Move the pointer to the beginning, select the player actor, and set a key. Small boxes will appear on the position and orientation tracks to mark the key frame.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene key marker.png]]&lt;br /&gt;
&lt;br /&gt;
These markers essentially mean &amp;quot;at this particular point in time, dummy_player will be in this particular place and facing in this particular direction.&amp;quot; &lt;br /&gt;
&lt;br /&gt;
To get an actor to move over time you could set two key frames - one at the beginning of the movement, with the actor in his starting position, and one at the end of the movement, with the actor at his end position. You can set how the cutscene engine interpolates between the two positions by setting the &amp;quot;Transition Out&amp;quot; property of the starting keyframe to either Bezier (a smooth curve), Linear (a straight line), or Step (a sudden jump from the starting position to the end position). See the [[curve editor]] page for more detail.&lt;br /&gt;
&lt;br /&gt;
We're not going to actually do this in this case, however; we'll try it at a later point in this tutorial to move a camera around. For this particular actor it would be difficult to manually match the actor's walking action with his motion over the ground. If the animation and the movement don't match the actor's feet will &amp;quot;skate&amp;quot; unrealistically along the surface.&lt;br /&gt;
&lt;br /&gt;
There's an easier way to match an animation such as this one with movement through the scene; a mechanism called GAD.&lt;br /&gt;
&lt;br /&gt;
=== Using GAD ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* GAD is a mechanism by which an animation applies a built-in displacement to the object it's animating.&lt;br /&gt;
* You need to set at least one key frame for an object to use GAD, even if you don't otherwise use key frames to move it.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
GAD is a displacement that is automatically added to the actor's current position as the animation plays. Each animation has its own GAD information built into it, custom-designed to make the actor move in a manner appropriate to its actions. If we enable it the actor will be moved forward as the animation plays.&lt;br /&gt;
&lt;br /&gt;
Not all animations have GAD associated with them. For example, having an actor wave his hand wouldn't displace him, so there would be no GAD associated with that animation. We only need to worry about GAD in cases like this one where the animation should accompany movement.&lt;br /&gt;
&lt;br /&gt;
To enable GAD select the animation action and set &amp;quot;Play Gad&amp;quot; to true in the object inspector. If no key frames have been defined for the actor the cutscene editor will pop up a warning at this point suggesting that we add position and orientation keys before we add GAD:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene gad warning.png]]&lt;br /&gt;
&lt;br /&gt;
It's important to set at least one set of keys for an object using GAD. The animation's GAD may seem to work correctly without it at first, but unexpected and unpredictable errors could occur later that will send the actor careening off into the distance.&lt;br /&gt;
&lt;br /&gt;
Once we've set a key frame and have set the action's &amp;quot;Play Gad&amp;quot; option to true you'll see that the actor now moves forward as he walks. This is good, but since we started him off in the position he's meant to end in it results in the actor walking straight through the campfire. You'll need to move the actor back so that he starts farther away from the fire.&lt;br /&gt;
&lt;br /&gt;
Note that if you've already set a keyframe as described in the previous section you'll need to re-set it for the actor's new location (or alternately set the &amp;quot;update keys&amp;quot; mode with the [[Image:IconUpdateKeys.png]] tool), otherwise the moment the animation starts the actor will instantly jump back to the place he was where you set the keyframe. Once you set a keyframe for an actor, moving the actor around in the cutscene editor doesn't really change its position unless you re-set the keyframe to the new position. Keyframes and the curves interpolating between them always take precedence. &lt;br /&gt;
^&lt;br /&gt;
|&lt;br /&gt;
(ED: This need extreme explanation by someone that knows how to do this properly because this paragraph is obtuse!!)&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* An animation's &amp;quot;Extend Gad Beyond Action&amp;quot; property makes Gad's displacement persist after the animation ends.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The other GAD properties are set to the most appropriate defaults automatically when you select an animation but one particular property bears mention here in case you run into trouble with it later on; the &amp;quot;Extend Gad Beyond Action&amp;quot; property. In the case of this walking animation it defaults to true. That means that once the animation ends, the displacement that the actor has undergone as a result of it will remain in effect - he will stay in the final position he walked to. If this were set to false, once the animation ended all of the displacement the actor had gained as a result would be undone and he'd instantly jump back to where he started walking from again. If at some point in the future you find your actors doing this, this property is the first place to look for the answer.&lt;br /&gt;
&lt;br /&gt;
There's one final detail we'll tweak here. The walking animation begins with the player starting from a standstill, which is not the impression we want to convey; the player has supposedly been walking for some time before the camera started rolling. We could set the animation to begin playing partway through by changing the animation action's &amp;quot;Start Offset&amp;quot; property, but since this is happening at the beginning of the cutscene's timeline an easier approach is to simply select the animation action and drag it so that it begins a half second before the cutscene does. The cutscene will only begin displaying at the 0 mark and anything that falls before this point in time will never be shown so the initial half second of the actor's walk animation will go unseen.&lt;br /&gt;
&lt;br /&gt;
== Moving a camera ==&lt;br /&gt;
&lt;br /&gt;
The scene now has some of the dynamic action we wanted, showing the player walking up to the campfire and stopping at its edge. But it's still a rather dull introduction and we can do better. Instead of a static camera shot we can set the camera so that it pans across the scene to follow the player's arrival.&lt;br /&gt;
&lt;br /&gt;
Select the Arrival Camera and open up its track list. It has Position and Orientation tracks just like the other actors, and can have keyframes set just the same. With the time marker set to 0, move the Arrival Camera so that its view shows how you want the shot framed at the beginning of the cutscene. In our example we're going to set it so that it shows the player in the center of the frame. With the camera still selected, press &amp;quot;k&amp;quot; to set a key frame for the camera.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera start position.png]]&lt;br /&gt;
&lt;br /&gt;
(You may notice that the Field of View (FOV) track also gets a key marker. We won't be changing the camera's FOV so you can ignore that.)&lt;br /&gt;
&lt;br /&gt;
Next move the timeline scrubber to the end of the walking animation at the 5 second mark. The player's actor will now be at the final position where he'll be standing for the conversation. Change the camera's orientation, panning to the right so that all of the actors can be seen in its field of view. In our case the camera's too close to encompass everyone so we'll also move its position to allow it to see them all.&lt;br /&gt;
&lt;br /&gt;
Once you have the shot lined up correctly, press &amp;quot;k&amp;quot; to set a second keyframe.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera end position.png]]&lt;br /&gt;
&lt;br /&gt;
You may notice that the User viewports now show a red line tracing out the selected object's trajectory through space (if not, you may need to click the &amp;quot;show trajectories&amp;quot; [[Image:IconShowTrajectory.png]] button in the toolbar). As the first five seconds of the cutscene plays, the Arrival Camera should slide smoothly along the red line and rotate smoothly on its axes to transition from the first keyframe to the second keyframe (If it suddenly jumps from one position to the other instead you may need to click the &amp;quot;default curve mode&amp;quot; tool [[Image:IconDefaultCurveMode.png]] and try setting the keys again, or change the &amp;quot;transition out&amp;quot; property of the keyframe to Bezier).&lt;br /&gt;
&lt;br /&gt;
You can fine-tune the trajectory of the camera by adding additional keyframes between the starting and ending ones. In our case we see that when the time marker is set to the middle of the camera's movement the player slips slightly out of frame.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera middle position unadjusted.png]]&lt;br /&gt;
&lt;br /&gt;
We can fix this by changing the camera's position and orientation as needed, and then adding a new keyframe with &amp;quot;k&amp;quot;. In this case we'll pull the camera back slightly so that its motion through space becomes a curve instead of a straight line.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera middle position adjusted.png]]&lt;br /&gt;
&lt;br /&gt;
We now have a nice, dynamic establishing shot. The scene begins with the player alone and in the center of the camera's shot, and as he walks toward the fire the camera moves and pans around him to show him arriving in the presence of our two campers.&lt;br /&gt;
&lt;br /&gt;
== Switching cameras ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* A track on the MASTER object defines which camera is currently &amp;quot;active.&amp;quot;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Once the player arrives he is going to be greeted by the camper who is happy to see him. To give a clear shot of who's doing the talking, we'll want to switch the active camera from Arrival Camera to Happy Camera.&lt;br /&gt;
&lt;br /&gt;
The track where the active camera gets changed is attached to the MASTER object. Move the timeline's time indicator to the point in time where you wish to switch active cameras, in this case 5.5 seconds (giving the scene a half-second view of the player after he's come to a halt). Right-click on the Active Camera track and select Add Action. The only option available for this track is the &amp;quot;Switch Camera&amp;quot; action so go ahead and add one. In the new Switch Camera action's properties set it to switch the active camera to Happy Camera.&lt;br /&gt;
&lt;br /&gt;
Now when the cutscene is played we'll get an establishing shot showing the player walking up to the fire and then switch to a closeup of the happy camper so that he can deliver his greeting.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene switch active camera.png]]&lt;br /&gt;
&lt;br /&gt;
== Adding dialogue ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Lines of dialog can be inserted from an existing [[conversation]] resource. For convenience, create a new conversation to hold the dialog for a cutscene.&lt;br /&gt;
* Caption text, voice over, and facial performance are all included with each line.&lt;br /&gt;
* If you edit the conversation later, the changes will be reflected in the cutscene. Remember to generate new VO and FaceFX in the conversation editor.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are three major components to dialog in Dragon Age; the text of the line being spoken (which is displayed as a caption at the top of the screen), the voice-over for the line being spoken, and the facial performance that makes the virtual actor lip-synch and display appropriate emotions.&lt;br /&gt;
&lt;br /&gt;
There's already a tool in the toolset that is designed for handling all of these things; the conversation editor. Actors in a cutscene can be given &amp;quot;Speak Line&amp;quot; actions that cause them to deliver lines from an existing dialog, with all three components added together into the actor's performance automatically.&lt;br /&gt;
&lt;br /&gt;
Here we are going to add dialogue to a cutscene (though sometimes it is better to take a [[Conversation#Conversation-centred_approach | conversation-centred approach]]).&lt;br /&gt;
&lt;br /&gt;
To create the dialog for this cutscene we'll now create a new conversation resource. This conversation is not going to be used in the game directly so we'll be able to ignore many of the more advanced features and settings covered in the conversation tutorial; its only purpose is to serve as a repository of dialog lines for use in this cutscene.&lt;br /&gt;
&lt;br /&gt;
The following screenshot shows our intended conversation. The only things that we need to define for it is the text of the dialog and optionally the emotion settings for RoboBrad to use when generating facial performance. As with our previous conversation we'll generate synthesized placeholder voice-over and generate FaceFX based on that; when we record real voice over later on we can simply update this conversation with it and the cutscene's performance will change to match.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene conversation.png]]&lt;br /&gt;
&lt;br /&gt;
To help keep track of which lines are spoken by which actors you could also optionally set the speaker tag on each line to identify who's doing the talking. This particular conversation has only two speakers so we won't bother with that. The cutscene engine won't need speaker tags, we'll be explicitly telling it who is saying each line. You'll only need to set those things if you wish to preview the conversation before using its lines in the cutscene.&lt;br /&gt;
&lt;br /&gt;
Once you've created your dialogue go back to the cutscene editor and add a new track to the camp_happy actor. Rename it to something informative, such as &amp;quot;Dialogue&amp;quot;. Move the timeline marker to the spot where you want the actor to start speaking and add a new &amp;quot;Speak Line&amp;quot; action.&lt;br /&gt;
&lt;br /&gt;
In the Speak Line action's properties, set the &amp;quot;Source Conversation&amp;quot; property to the conversation resource we just created. Then, select the specific line you want the actor to speak in the &amp;quot;Source Line&amp;quot; property (it will have a drop-down menu with all of the lines from the source conversation in it).&lt;br /&gt;
&lt;br /&gt;
That's all you need to do to get the actors to talk. You may wish to add one other detail at this point; head tracking. This is the action that causes actors to turn their heads toward a specific target, usually the person they're talking to or who is talking to them. It's added as its own action, so create another track and add a headtracking action to it with the player as the target. In this case we want the happy camper to turn his head toward the player right before he starts speaking.&lt;br /&gt;
&lt;br /&gt;
== Adding other details ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Headtracking actions make actors look at other objects in the cutscene.&lt;br /&gt;
* You can have more than one action on a track provided they don't overlap.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
We've now gone through all the basics, so we'll just finish fleshing out the conversation with a few other details that are done the same way as the examples above.&lt;br /&gt;
&lt;br /&gt;
To add a little more animation to the scene, we add another track for camp_happy with an animation action (mh.dg_hnd_salute_01, a salute) to play during his spoken line. This animation is simpler to deal with than the walking animation because it doesn't displace the actor; there's no need to define position keys or worry about enabling GAD.&lt;br /&gt;
&lt;br /&gt;
We'll set camp_angry's headlook so that she turns toward camp_happy while he's speaking; when we subsequently switch cameras to show her line of dialog she'll already be looking in his direction.&lt;br /&gt;
&lt;br /&gt;
For camp_happy's next line, however, we'll make the headtracking change visible during his shot so the player will see how his attention has switched to camp_angry. Note that we can reuse the existing &amp;quot;Dialogue&amp;quot; and &amp;quot;Headtracking&amp;quot; tracks for this actor; we don't need to create a new track for every single action that an actor performs. So long as the durations of the actions on a track don't overlap they can coexist peacefully.&lt;br /&gt;
&lt;br /&gt;
Finally, after camp_angry's last line we'll set her headtracking to look back toward the player. He's going to get the next word in when we integrate this cutscene into a conversation so this is a good way to indicate that the conversation's focus has gone to the player now.&lt;br /&gt;
&lt;br /&gt;
Once we've finished crafting the cutscene we now know how long its duration needs to be. You can now go to the conversation's properties in the Object Inspector and set the cutscene's duration to the desired length.&lt;br /&gt;
&lt;br /&gt;
The finished timeline of our cutscene:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene finished timeline.png]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
[[Category:Cutscenes]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Cutscene Tips and Tricks ===&lt;br /&gt;
&lt;br /&gt;
Here are a few tips and tricks that might save the cutscene creator some time and perhaps hair pulling.&lt;br /&gt;
&lt;br /&gt;
- Head tracking is often used to look at another actor or a visible item in the cutscene. However you can further manipulate the head of the actor by having the actor look at invisible objects. You can have the actor look from one invisible object to another or move the invisible object around in the cutscene to get the actor to look at things independent of visible actors or items.&lt;br /&gt;
&lt;br /&gt;
- You may find it useful to give meaningful names to your cameras if you are using more than one or two. (You might name a camera after the actor or placeable that it follows or name one camera ‘close-up’ and another ‘wide-angle’ for example.)&lt;br /&gt;
&lt;br /&gt;
- If you are panning a camera around a room following a series of actors or placeables and you find that the camera suddenly decides to rotate in the other direction you can force it to stay moving in the direction you desire by adding or subtracting 360 degrees from the position/orientation you are using to move the camera.&lt;br /&gt;
&lt;br /&gt;
- Feel free to experiment with animations. Try using animations that are not normally meant for your actor type, you might find some interesting or bizarre movements for your actor.&lt;br /&gt;
&lt;br /&gt;
- You can put multiple actions along one track as long as they do not overlap rather than using many different tracks.&lt;br /&gt;
&lt;br /&gt;
- Pay attention to what your key frames ‘transition out’ are set to when moving your cameras. Step will jump the camera from position to position while Bezier and Linear will move the camera in a smoother motion. If you are not getting the desired effect when moving cameras check what your key frames ‘transition out’ are set to.&lt;br /&gt;
&lt;br /&gt;
- If you have a longer more detailed cutscene you can keep the number of cameras you use to a reasonable number by just moving one (or more) around while another camera is the ‘active’ camera.&lt;br /&gt;
&lt;br /&gt;
- For testing purposes change the length of the cutscene in the cutscenes properties to a smaller value and enlarge that number as you add on to the cutscene. In this way you won’t need to wait for a long period of time for the cutscene to end.&lt;br /&gt;
&lt;br /&gt;
- After placing an animation on a track you can speed up the animation by left clicking on the small circular arrows on one end and dragging it shorter or make the animation play slower by dragging the animation longer on the track.&lt;br /&gt;
&lt;br /&gt;
- You can make the content of your scene seem to change by placing invisible objects in the cutsence, using an fx to obscure the view and making the object visible while the fx is playing. (For example you might have some invisible rock debris. Use a cave in fx with clouds of dust to obscure the screen. While the fx is playing make the debris visible. When the fx is finished your debris will be in place.)&lt;br /&gt;
&lt;br /&gt;
- If you find that your actor is walking across surfaces (such as water for instance) when they should be following the ground you can set ‘items follow surface’ in the area that your cutscene is based on. The actor should then walk on the ground and thus wade into the water. Conversely if you want a character or placeable to not follow the surface of the ground (for instance if you want a placeable or actor to be near or on the surface of water) move the actor or placeable higher by adjusting the Z axis of the boat or actor. (An example of using a placeable partly submerged in water might be something like a boat.)&lt;br /&gt;
&lt;br /&gt;
- In a cutscene you can only activate things that are unique. As in if you plopped down three identical chests in an area, when trying to activate them all in a cutscene it will not allow this and gives you a warning message. In the example above you would have to make three different chests (though they could look the same) to be able to activate them all in the cutscene.&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Cutscene_tutorial&amp;diff=16088</id>
		<title>Cutscene tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Cutscene_tutorial&amp;diff=16088"/>
				<updated>2011-04-20T16:43:45Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Adding dialogue */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox cutscenes}}&lt;br /&gt;
&lt;br /&gt;
[[Cutscene]]s can be stand-alone cinematic sequences that are triggered by scripts in the course of the game, or they can be inserted into [[conversation]]s in place of the simplified cinematics that conversations can automatically generate.&lt;br /&gt;
&lt;br /&gt;
Our example situation in this tutorial will serve as the beginning of a conversation between the player and two NPCs. The player has just arrived at the campsite where these two NPCs are staying. He walks up to the fire. One of the NPCs is happy to see the player and greets him, but the other is distrustful. The two share a brief exchange to establish this before the interactive part of the conversation begins.&lt;br /&gt;
&lt;br /&gt;
== Creating a new cutscene ==&lt;br /&gt;
&lt;br /&gt;
To create a brand new blank cutscene resource, create a new resource in the usual way:&lt;br /&gt;
&lt;br /&gt;
[[Image:New resource.png]]&lt;br /&gt;
&lt;br /&gt;
The result is opened in the cutscene editor.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene new.png|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
There are two basic sections to the cutscene editor; the viewports (top) and the timeline (bottom).&lt;br /&gt;
&lt;br /&gt;
=== Viewports ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Viewports can be attached to various cameras to preview what they can see&lt;br /&gt;
* Add a &amp;quot;Safe Frame&amp;quot; to camera viewports to ensure the correct aspect ratio&lt;br /&gt;
* Set a viewport to &amp;quot;User&amp;quot; to see where cameras are positioned from another perspective. This can be done by selecting &amp;quot;Detach From Camera&amp;quot; in the viewport's right-click menu in the title bar&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The camera viewports in the cutscene editor work similarly to the viewports in the stage editor. You can set the number and layout of viewports under the &amp;quot;View&amp;quot; menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial viewport layout.png]]&lt;br /&gt;
&lt;br /&gt;
And for each individual viewport you can select which camera it's showing and set other display options by right-clicking on the title bar of the viewport:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial viewport properties.png]]&lt;br /&gt;
&lt;br /&gt;
When you set a viewport to show the view through one of the cutscene's cameras, it's a good idea to turn on that viewport's &amp;quot;Safe Frame&amp;quot; option as well. This will put a border on the viewport showing what will be visible when the cutscene plays.&lt;br /&gt;
&lt;br /&gt;
Note that when you play the cutscene in the cutscene editor, only the currently selected viewport (the one with the blue title bar) will show the cutscene &amp;quot;live&amp;quot; - the others won't update the view displayed in them until they're selected. To preview the cutscene as the player would see it, then, you should set one of the viewports to &amp;quot;Active Camera&amp;quot; and ensure that this viewport is selected when you play the cutscene in the editor. If the &amp;quot;Active Camera&amp;quot; viewport turns gray, try setting the cutscene property &amp;quot;Enable Level Effects&amp;quot; to false.&lt;br /&gt;
&lt;br /&gt;
=== Timeline ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* There is always exactly one MASTER object in a cutscene.&lt;br /&gt;
* Each active object is listed on the timeline, with multiple &amp;quot;tracks&amp;quot; for each.&lt;br /&gt;
* All objects have position tracks (divided into X, Y and Z tracks). Some objects have additional built-in tracks.&lt;br /&gt;
* Other actions and effects can be added to generic tracks. Objects can have as many generic tracks as you want.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Below the viewport is the timeline. Along the top of the timeline is a time scale; it can be set either to show frames (at 30 frames per second) or milliseconds by changing the &amp;quot;Time Scale&amp;quot; property if the cutscene in the object inspector.  A marker indicates what point in the timeline the viewports are currently showing.&lt;br /&gt;
&lt;br /&gt;
Below are a set of rows containing the various actors, cameras, and other objects active in the cutscene. This is where most of the editing is going to take place. Each object will have a number of &amp;quot;tracks&amp;quot;, which will contain commands that are sent to the actors at particular times in the course of the cutscene.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial timeline.png]]&lt;br /&gt;
&lt;br /&gt;
The first object in the track list is the &amp;quot;MASTER&amp;quot; object. This is a special object that every cutscene has exactly one of. The MASTER object is the cutscene equivalent to the root node of a conversation tree, a repository for global settings and effects. For example the MASTER object contains the track that determines which camera is active at any given time. The MASTER object cannot be deleted. By default, a MASTER object appears in the cutscene editor as a small greenish sphere; you can change the MASTER object's appearance in the cutscene option settings.&lt;br /&gt;
&lt;br /&gt;
A new cutscene also has a camera, called Camera 1. This camera can be deleted or renamed if you like; we can add new cameras as needed later on.&lt;br /&gt;
&lt;br /&gt;
Every object has &amp;quot;Position&amp;quot; and &amp;quot;Orientation&amp;quot; tracks that control their locations in space. Cameras also have a FOV (field of view) track.&lt;br /&gt;
&lt;br /&gt;
Objects can have other &amp;quot;generic&amp;quot; tracks added by the editor as needed. These generic tracks contain all the other commands and directions we can give.&lt;br /&gt;
&lt;br /&gt;
== The setting of the cutscene ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* The MASTER object should be moved somewhere near the center of your cutscene.&lt;br /&gt;
* You can optionally set a stage for your cutscene, enabling stage-related actions for objects.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Establishing the setting of a cutscene is done in the object inspector in the group of properties labeled &amp;quot;Setting&amp;quot;. The most important of these is the &amp;quot;Area&amp;quot; property, which allows you to set the cutscene in an existing [[area]]. We already have a suitable area that was created in an earlier tutorial; the area &amp;quot;great_outdoors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
By default the MASTER object and Camera 1 will be located at the coordinates 0,0,0 in the area. You'll want to move the camera to the appropriate location within the area using standard [[3D control]]s for movement and view management. The MASTER object is invisible when the cutscene is played in-game so it usually doesn't matter where you put it. However, there are some settings that depend on the MASTER object's location - for example, you can set level-of-detail for models so that the model's LOD varies depending on how close it is to the MASTER object - so it's probably a good idea to put MASTER somewhere near the middle of where you'll be having the cutscene's action take place.&lt;br /&gt;
&lt;br /&gt;
You can also set a stage for the cutscene. This is optional, but setting a stage enables &amp;quot;Jump to Stage Place&amp;quot; and &amp;quot;Jump to Stage Camera&amp;quot; actions that could help make setting the cutscene up easier if you already have a good stage defined in the area.&lt;br /&gt;
&lt;br /&gt;
=== Adding objects and creatures ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Objects already present in the area the cutscene is set in are inactive by default. You need to activate them to control them.&lt;br /&gt;
* Other objects can be added from the resource palette as normal.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
All of the objects that are normally present in the area (such as creatures and placeables) will be visible in the cutscene editor, but they'll all initially be marked as &amp;quot;inactive&amp;quot;. This means that, although they'll be visible in the cutscene when it plays, they won't be controllable; they'll just do whatever ambient activities they would be doing normally. In the case of our campsite area there are two creatures that were placed here in the area editor; the happy camper, named camp_happy, and the angry camper, named camp_angry. We need to seize control of them to make them active participants in the cutscene's activities. To make them active, right-click on them and select &amp;quot;activate objects&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene activate object.png]]&lt;br /&gt;
&lt;br /&gt;
The object will then become an active object in the cutscene, getting its own entry in the timeline that will allow you to control its actions.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene object activated.png]]&lt;br /&gt;
&lt;br /&gt;
We'll activate both of these campers since they'll both be taking part in the cutscene's dialogue.&lt;br /&gt;
&lt;br /&gt;
You can also add objects that aren't normally a part of the area. Simply open the object palette, select the creature or placeable you wish to use in the cutscene, and then click in the viewport to add the object to that location. It will automatically be made active and get an entry in the timeline. The player won't see these objects during regular play, since they're not a part of the area - they're only in the cutscene.&lt;br /&gt;
&lt;br /&gt;
If you want to make an area object disappear during the cutscene you'll need to activate it (allowing you to control it) and then add a track with an action that makes it invisible in the first frame. It will go back to normal again when the cutscene ends and the game resumes, cutscenes are run entirely separate from the main action of the game and have no direct effects on it.&lt;br /&gt;
&lt;br /&gt;
=== Adding the player ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Use the &amp;quot;Mapping Tag&amp;quot; property on an actor to make the game replace it with another object (such as PLAYER) at run-time.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Normally we don't have to worry about placing the player in an area since the player controls his own movements and actions. But when we're doing a cutscene we can control the player just like any other actor, so we'll need a way to insert the player as an active object. Furthermore, since we'll have no idea what the player is going to look like at any given moment, we'll need to have a way to insert the player as he appears in the game when the cutscene begins.&lt;br /&gt;
&lt;br /&gt;
This is done by inserting a &amp;quot;dummy&amp;quot; virtual actor and then setting the actor's &amp;quot;Mapping Tag&amp;quot; property to the special &amp;quot;PLAYER&amp;quot; tag. &lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene dummy player.png|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
It doesn't matter what the dummy actor looks like now, it will be replaced with the player's character later on, so we'll just use a default male human model to make it both simple and obvious.&lt;br /&gt;
&lt;br /&gt;
There are ways to tweak the way the cutscene plays based on other characteristics of the player, for example by modifying the position of the camera to account for the player's height or by adding additional dummies to represent followers. We won't go into these more advanced topics in this tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Adding cameras ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Remember to enable Safe Frame when attaching a viewport to a camera.&lt;br /&gt;
* Use an &amp;quot;Active Camera&amp;quot; viewport to preview the cutscene.&lt;br /&gt;
* Use a &amp;quot;User&amp;quot; viewport to see camera positions from the outside. This can be done by selecting &amp;quot;Detach From Camera&amp;quot; in the viewport's right-click menu in the title bar.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
We could film a cutscene entirely from one camera if we liked, either as a single static shot or by moving the camera around to new positions as needed. It's easier and more convenient in most cases just to add several different cameras, however, and use the &amp;quot;Active Camera&amp;quot; track on the MASTER object to switch between them.&lt;br /&gt;
&lt;br /&gt;
For our cutscene we're going to want three different cameras; one camera that's a wide shot showing the player arriving at the campfire, one camera focused on the angry camper, and one focused on the happy camper. We could add more than just these three to make the scene even more dynamic but for simplicity we'll stick to just those for now. We can add more later.&lt;br /&gt;
&lt;br /&gt;
Cameras are added by right-clicking in the viewport and selecting &amp;quot;Insert &amp;amp;rarr; Camera&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene insert camera.png]]&lt;br /&gt;
&lt;br /&gt;
You can then position them using standard [[3D control]]s. To make it easier to get the camera set up with the correct view, a good technique is to set one of the viewports to display the camera's feed; you can then reorient and reposition the camera using that viewport's camera controls while getting immediate feedback as to what the camera will see in its new state.&lt;br /&gt;
&lt;br /&gt;
We're also going to rename the three cameras at this point with names intended to remind us of what their purposes are. We'll name them &amp;quot;Arrival Camera&amp;quot;, &amp;quot;Happy Camera&amp;quot;, and &amp;quot;Angry Camera&amp;quot;. We'll want &amp;quot;Arrival Camera&amp;quot; to be active initially, so we may as well use the original camera for this role; it's already set active by default. We'll see how to switch which camera is active later in this tutorial.&lt;br /&gt;
&lt;br /&gt;
We now have all the basic props we need to get the cutscene going.&lt;br /&gt;
&lt;br /&gt;
== Adding an animation to an actor ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Set the &amp;quot;Pose&amp;quot; property for actors to make them breathe and fidget naturally when not doing other animations.&lt;br /&gt;
* Other animations are set by adding &amp;quot;Play Animation&amp;quot; actions to a generic track.&lt;br /&gt;
* Animation filenames are often arcane and hard to find.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you play the cutscene now the first thing you'll probably notice is that the actors are all standing perfectly motionless. Normally someone who's standing still isn't really standing ''perfectly'' still; they breathe, they shift their weight from foot to foot, and so forth. Since almost every actor we use is going to need to do this we don't want to have to spend a lot of effort setting it up, and fortunately we don't have to. Every actor has a &amp;quot;Pose&amp;quot; property in the object inspector. Simply set this pose to &amp;quot;Standing Neutral&amp;quot; and the actors will display this default subtle movement whenever no other animations are being explicitly imposed on them.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene set pose.png]]&lt;br /&gt;
&lt;br /&gt;
Our next task is somewhat less trivial; we want to show the player walking up to the fire. We're going to have to add a walking animation to the player's actor that runs for a short period of time and then stops.&lt;br /&gt;
&lt;br /&gt;
To do this we'll need to add a new track to the actor's timeline. Right-click on the actor's entry in the timeline and select &amp;quot;Add Track&amp;quot; from the resulting menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene add track.png]]&lt;br /&gt;
&lt;br /&gt;
The new track will be named &amp;quot;New Track&amp;quot; by default and will start out empty. Actors in cutscenes will sometimes have dozens of tracks directing their actions so we'll want to rename the track to something a little more informative. In this case we'll name it &amp;quot;Walk to fire&amp;quot;. To have it actually cause the player's actor to walk to the fire we'll need to add a &amp;quot;[[Play animation]]&amp;quot; action to it. Right-click on the track and select &amp;quot;Add Action&amp;quot; to get the menu to select this.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene add action.png]]&lt;br /&gt;
&lt;br /&gt;
The action will be added starting at the point you're currently viewing in the timeline, so you may wish to move the timeline's time slider back to the beginning before adding this animation. You can reposition an action along the timeline simply by dragging it with the mouse.&lt;br /&gt;
&lt;br /&gt;
Initially the action has no animation associated with it. To set the animation, select the action in the timeline and then in the Object Inspector go to the &amp;quot;Animation&amp;quot; property and click on the ellipsis ([[Image:ellipsis.png]]) button.&lt;br /&gt;
&lt;br /&gt;
Unfortunately this is where things turn a bit arcane since the names of the various animation files are often very unclear and not all will appear in the default list. You may need to resort to trial and error to find one you like, but there are many hundreds of animations available in the game's resources so this could take some time. See [[animation list]] and [http://social.bioware.com/project/30/#files Beerfish Excel Utilities] for a list of many of them.&lt;br /&gt;
&lt;br /&gt;
Note that only a single animation can play at any time on a given track. However, it is possible to have multiple animations for a character, each of which must be on a different track. This is essential in order to be able to blend animations together as detailed in [[Play_animation#Blending_Animations]]. Animation blending is necessary in order to have your characters transition seamlessly from one animation to another, which is essential to making character movement look natural.&lt;br /&gt;
&lt;br /&gt;
In this case the animation we want, &amp;quot;mh.dg_f_5p&amp;quot; (&amp;quot;male human dialog forward five paces&amp;quot;), doesn't appear in the default list of animations available in the animation picker. You'll need to click the ellipsis button next to the &amp;quot;Custom Animation&amp;quot; field and find it in the complete list of all animation resources.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene finding an animation.png]]&lt;br /&gt;
&lt;br /&gt;
If you try playing the cutscene now you'll see that the player's actor will spend a little over five seconds walking and then come to a natural stop - about as long as we needed. But the actor will be animated in place, his legs taking steps but not actually moving him anywhere. This is where position keys and GAD comes in.&lt;br /&gt;
&lt;br /&gt;
== Moving an actor ==&lt;br /&gt;
&lt;br /&gt;
=== Position and orientation keys ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Objects be moved over time by setting &amp;quot;key frames&amp;quot; on their position and orientation tracks.&lt;br /&gt;
* Intermediate frames are interpolated between key frames.&lt;br /&gt;
* You can set the curve type between key frames with the &amp;quot;transition out&amp;quot; property for each key.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Every object in a cutscene has a pre-defined &amp;quot;Position&amp;quot; track with three sub-tracks for its X, Y and Z coordinates. Most objects also have a pre-defined &amp;quot;Orientation&amp;quot; track with three subtracks for roll, pitch, and yaw. These tracks can be used to cause an object to move around within the area over the course of the cutscene.&lt;br /&gt;
&lt;br /&gt;
Movement is handled by setting the position and orientation of objects at specific points in time, called key frames, and then interpolating intermediate positions and orientations. To set a key frame, right-click on the actor's entry in the timeline and select &amp;quot;key position&amp;quot;. This will set a key for the current position and orientation at the current time in the timeline. You can set position and orientation keys separately if you like. Since this operation is so common there's a very convenient shortcut for it; &amp;quot;k&amp;quot; inserts a key for the currently selected object's position and orientation, &amp;quot;p&amp;quot; inserts a key for its position, and &amp;quot;o&amp;quot; inserts a key for its orientation. Alternately, select the object and click the key command in the toolbar: [[Image:IconKey.png]]&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene key selection.png]]&lt;br /&gt;
&lt;br /&gt;
For our purposes right now all we'll need to do is set a key frame at the beginning of the timeline. Move the pointer to the beginning, select the player actor, and set a key. Small boxes will appear on the position and orientation tracks to mark the key frame.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene key marker.png]]&lt;br /&gt;
&lt;br /&gt;
These markers essentially mean &amp;quot;at this particular point in time, dummy_player will be in this particular place and facing in this particular direction.&amp;quot; &lt;br /&gt;
&lt;br /&gt;
To get an actor to move over time you could set two key frames - one at the beginning of the movement, with the actor in his starting position, and one at the end of the movement, with the actor at his end position. You can set how the cutscene engine interpolates between the two positions by setting the &amp;quot;Transition Out&amp;quot; property of the starting keyframe to either Bezier (a smooth curve), Linear (a straight line), or Step (a sudden jump from the starting position to the end position). See the [[curve editor]] page for more detail.&lt;br /&gt;
&lt;br /&gt;
We're not going to actually do this in this case, however; we'll try it at a later point in this tutorial to move a camera around. For this particular actor it would be difficult to manually match the actor's walking action with his motion over the ground. If the animation and the movement don't match the actor's feet will &amp;quot;skate&amp;quot; unrealistically along the surface.&lt;br /&gt;
&lt;br /&gt;
There's an easier way to match an animation such as this one with movement through the scene; a mechanism called GAD.&lt;br /&gt;
&lt;br /&gt;
=== Using GAD ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* GAD is a mechanism by which an animation applies a built-in displacement to the object it's animating.&lt;br /&gt;
* You need to set at least one key frame for an object to use GAD, even if you don't otherwise use key frames to move it.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
GAD is a displacement that is automatically added to the actor's current position as the animation plays. Each animation has its own GAD information built into it, custom-designed to make the actor move in a manner appropriate to its actions. If we enable it the actor will be moved forward as the animation plays.&lt;br /&gt;
&lt;br /&gt;
Not all animations have GAD associated with them. For example, having an actor wave his hand wouldn't displace him, so there would be no GAD associated with that animation. We only need to worry about GAD in cases like this one where the animation should accompany movement.&lt;br /&gt;
&lt;br /&gt;
To enable GAD select the animation action and set &amp;quot;Play Gad&amp;quot; to true in the object inspector. If no key frames have been defined for the actor the cutscene editor will pop up a warning at this point suggesting that we add position and orientation keys before we add GAD:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene gad warning.png]]&lt;br /&gt;
&lt;br /&gt;
It's important to set at least one set of keys for an object using GAD. The animation's GAD may seem to work correctly without it at first, but unexpected and unpredictable errors could occur later that will send the actor careening off into the distance.&lt;br /&gt;
&lt;br /&gt;
Once we've set a key frame and have set the action's &amp;quot;Play Gad&amp;quot; option to true you'll see that the actor now moves forward as he walks. This is good, but since we started him off in the position he's meant to end in it results in the actor walking straight through the campfire. You'll need to move the actor back so that he starts farther away from the fire.&lt;br /&gt;
&lt;br /&gt;
Note that if you've already set a keyframe as described in the previous section you'll need to re-set it for the actor's new location (or alternately set the &amp;quot;update keys&amp;quot; mode with the [[Image:IconUpdateKeys.png]] tool), otherwise the moment the animation starts the actor will instantly jump back to the place he was where you set the keyframe. Once you set a keyframe for an actor, moving the actor around in the cutscene editor doesn't really change its position unless you re-set the keyframe to the new position. Keyframes and the curves interpolating between them always take precedence. &lt;br /&gt;
^&lt;br /&gt;
|&lt;br /&gt;
(ED: This need extreme explanation by someone that knows how to do this properly because this paragraph is obtuse!!)&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* An animation's &amp;quot;Extend Gad Beyond Action&amp;quot; property makes Gad's displacement persist after the animation ends.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The other GAD properties are set to the most appropriate defaults automatically when you select an animation but one particular property bears mention here in case you run into trouble with it later on; the &amp;quot;Extend Gad Beyond Action&amp;quot; property. In the case of this walking animation it defaults to true. That means that once the animation ends, the displacement that the actor has undergone as a result of it will remain in effect - he will stay in the final position he walked to. If this were set to false, once the animation ended all of the displacement the actor had gained as a result would be undone and he'd instantly jump back to where he started walking from again. If at some point in the future you find your actors doing this, this property is the first place to look for the answer.&lt;br /&gt;
&lt;br /&gt;
There's one final detail we'll tweak here. The walking animation begins with the player starting from a standstill, which is not the impression we want to convey; the player has supposedly been walking for some time before the camera started rolling. We could set the animation to begin playing partway through by changing the animation action's &amp;quot;Start Offset&amp;quot; property, but since this is happening at the beginning of the cutscene's timeline an easier approach is to simply select the animation action and drag it so that it begins a half second before the cutscene does. The cutscene will only begin displaying at the 0 mark and anything that falls before this point in time will never be shown so the initial half second of the actor's walk animation will go unseen.&lt;br /&gt;
&lt;br /&gt;
== Moving a camera ==&lt;br /&gt;
&lt;br /&gt;
The scene now has some of the dynamic action we wanted, showing the player walking up to the campfire and stopping at its edge. But it's still a rather dull introduction and we can do better. Instead of a static camera shot we can set the camera so that it pans across the scene to follow the player's arrival.&lt;br /&gt;
&lt;br /&gt;
Select the Arrival Camera and open up its track list. It has Position and Orientation tracks just like the other actors, and can have keyframes set just the same. With the time marker set to 0, move the Arrival Camera so that its view shows how you want the shot framed at the beginning of the cutscene. In our example we're going to set it so that it shows the player in the center of the frame. With the camera still selected, press &amp;quot;k&amp;quot; to set a key frame for the camera.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera start position.png]]&lt;br /&gt;
&lt;br /&gt;
(You may notice that the Field of View (FOV) track also gets a key marker. We won't be changing the camera's FOV so you can ignore that.)&lt;br /&gt;
&lt;br /&gt;
Next move the timeline scrubber to the end of the walking animation at the 5 second mark. The player's actor will now be at the final position where he'll be standing for the conversation. Change the camera's orientation, panning to the right so that all of the actors can be seen in its field of view. In our case the camera's too close to encompass everyone so we'll also move its position to allow it to see them all.&lt;br /&gt;
&lt;br /&gt;
Once you have the shot lined up correctly, press &amp;quot;k&amp;quot; to set a second keyframe.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera end position.png]]&lt;br /&gt;
&lt;br /&gt;
You may notice that the User viewports now show a red line tracing out the selected object's trajectory through space (if not, you may need to click the &amp;quot;show trajectories&amp;quot; [[Image:IconShowTrajectory.png]] button in the toolbar). As the first five seconds of the cutscene plays, the Arrival Camera should slide smoothly along the red line and rotate smoothly on its axes to transition from the first keyframe to the second keyframe (If it suddenly jumps from one position to the other instead you may need to click the &amp;quot;default curve mode&amp;quot; tool [[Image:IconDefaultCurveMode.png]] and try setting the keys again, or change the &amp;quot;transition out&amp;quot; property of the keyframe to Bezier).&lt;br /&gt;
&lt;br /&gt;
You can fine-tune the trajectory of the camera by adding additional keyframes between the starting and ending ones. In our case we see that when the time marker is set to the middle of the camera's movement the player slips slightly out of frame.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera middle position unadjusted.png]]&lt;br /&gt;
&lt;br /&gt;
We can fix this by changing the camera's position and orientation as needed, and then adding a new keyframe with &amp;quot;k&amp;quot;. In this case we'll pull the camera back slightly so that its motion through space becomes a curve instead of a straight line.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera middle position adjusted.png]]&lt;br /&gt;
&lt;br /&gt;
We now have a nice, dynamic establishing shot. The scene begins with the player alone and in the center of the camera's shot, and as he walks toward the fire the camera moves and pans around him to show him arriving in the presence of our two campers.&lt;br /&gt;
&lt;br /&gt;
== Switching cameras ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* A track on the MASTER object defines which camera is currently &amp;quot;active.&amp;quot;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Once the player arrives he is going to be greeted by the camper who is happy to see him. To give a clear shot of who's doing the talking, we'll want to switch the active camera from Arrival Camera to Happy Camera.&lt;br /&gt;
&lt;br /&gt;
The track where the active camera gets changed is attached to the MASTER object. Move the timeline's time indicator to the point in time where you wish to switch active cameras, in this case 5.5 seconds (giving the scene a half-second view of the player after he's come to a halt). Right-click on the Active Camera track and select Add Action. The only option available for this track is the &amp;quot;Switch Camera&amp;quot; action so go ahead and add one. In the new Switch Camera action's properties set it to switch the active camera to Happy Camera.&lt;br /&gt;
&lt;br /&gt;
Now when the cutscene is played we'll get an establishing shot showing the player walking up to the fire and then switch to a closeup of the happy camper so that he can deliver his greeting.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene switch active camera.png]]&lt;br /&gt;
&lt;br /&gt;
== Adding dialogue ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Lines of dialog can be inserted from an existing [[conversation]] resource. For convenience, create a new conversation to hold the dialog for a cutscene.&lt;br /&gt;
* Caption text, voice over, and facial performance are all included with each line.&lt;br /&gt;
* If you edit the conversation later, the changes will be reflected in the cutscene. Remember to generate new VO and FaceFX in the conversation editor.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are three major components to dialog in Dragon Age; the text of the line being spoken (which is displayed as a caption at the top of the screen), the voice-over for the line being spoken, and the facial performance that makes the virtual actor lip-synch and display appropriate emotions.&lt;br /&gt;
&lt;br /&gt;
There's already a tool in the toolset that is designed for handling all of these things; the conversation editor. Actors in a cutscene can be given &amp;quot;Speak Line&amp;quot; actions that cause them to deliver lines from an existing dialog, with all three components added together into the actor's performance automatically.&lt;br /&gt;
&lt;br /&gt;
Here we are going to add dialogue to a cutscene (though sometimes it is better to take a [[http://social.bioware.com/wiki/datoolset/index.php/Conversation#Conversation-centred_approach conversation-centred approach]]).&lt;br /&gt;
&lt;br /&gt;
To create the dialog for this cutscene we'll now create a new conversation resource. This conversation is not going to be used in the game directly so we'll be able to ignore many of the more advanced features and settings covered in the conversation tutorial; its only purpose is to serve as a repository of dialog lines for use in this cutscene.&lt;br /&gt;
&lt;br /&gt;
The following screenshot shows our intended conversation. The only things that we need to define for it is the text of the dialog and optionally the emotion settings for RoboBrad to use when generating facial performance. As with our previous conversation we'll generate synthesized placeholder voice-over and generate FaceFX based on that; when we record real voice over later on we can simply update this conversation with it and the cutscene's performance will change to match.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene conversation.png]]&lt;br /&gt;
&lt;br /&gt;
To help keep track of which lines are spoken by which actors you could also optionally set the speaker tag on each line to identify who's doing the talking. This particular conversation has only two speakers so we won't bother with that. The cutscene engine won't need speaker tags, we'll be explicitly telling it who is saying each line. You'll only need to set those things if you wish to preview the conversation before using its lines in the cutscene.&lt;br /&gt;
&lt;br /&gt;
Once you've created your dialogue go back to the cutscene editor and add a new track to the camp_happy actor. Rename it to something informative, such as &amp;quot;Dialogue&amp;quot;. Move the timeline marker to the spot where you want the actor to start speaking and add a new &amp;quot;Speak Line&amp;quot; action.&lt;br /&gt;
&lt;br /&gt;
In the Speak Line action's properties, set the &amp;quot;Source Conversation&amp;quot; property to the conversation resource we just created. Then, select the specific line you want the actor to speak in the &amp;quot;Source Line&amp;quot; property (it will have a drop-down menu with all of the lines from the source conversation in it).&lt;br /&gt;
&lt;br /&gt;
That's all you need to do to get the actors to talk. You may wish to add one other detail at this point; head tracking. This is the action that causes actors to turn their heads toward a specific target, usually the person they're talking to or who is talking to them. It's added as its own action, so create another track and add a headtracking action to it with the player as the target. In this case we want the happy camper to turn his head toward the player right before he starts speaking.&lt;br /&gt;
&lt;br /&gt;
== Adding other details ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Headtracking actions make actors look at other objects in the cutscene.&lt;br /&gt;
* You can have more than one action on a track provided they don't overlap.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
We've now gone through all the basics, so we'll just finish fleshing out the conversation with a few other details that are done the same way as the examples above.&lt;br /&gt;
&lt;br /&gt;
To add a little more animation to the scene, we add another track for camp_happy with an animation action (mh.dg_hnd_salute_01, a salute) to play during his spoken line. This animation is simpler to deal with than the walking animation because it doesn't displace the actor; there's no need to define position keys or worry about enabling GAD.&lt;br /&gt;
&lt;br /&gt;
We'll set camp_angry's headlook so that she turns toward camp_happy while he's speaking; when we subsequently switch cameras to show her line of dialog she'll already be looking in his direction.&lt;br /&gt;
&lt;br /&gt;
For camp_happy's next line, however, we'll make the headtracking change visible during his shot so the player will see how his attention has switched to camp_angry. Note that we can reuse the existing &amp;quot;Dialogue&amp;quot; and &amp;quot;Headtracking&amp;quot; tracks for this actor; we don't need to create a new track for every single action that an actor performs. So long as the durations of the actions on a track don't overlap they can coexist peacefully.&lt;br /&gt;
&lt;br /&gt;
Finally, after camp_angry's last line we'll set her headtracking to look back toward the player. He's going to get the next word in when we integrate this cutscene into a conversation so this is a good way to indicate that the conversation's focus has gone to the player now.&lt;br /&gt;
&lt;br /&gt;
Once we've finished crafting the cutscene we now know how long its duration needs to be. You can now go to the conversation's properties in the Object Inspector and set the cutscene's duration to the desired length.&lt;br /&gt;
&lt;br /&gt;
The finished timeline of our cutscene:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene finished timeline.png]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
[[Category:Cutscenes]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Cutscene Tips and Tricks ===&lt;br /&gt;
&lt;br /&gt;
Here are a few tips and tricks that might save the cutscene creator some time and perhaps hair pulling.&lt;br /&gt;
&lt;br /&gt;
- Head tracking is often used to look at another actor or a visible item in the cutscene. However you can further manipulate the head of the actor by having the actor look at invisible objects. You can have the actor look from one invisible object to another or move the invisible object around in the cutscene to get the actor to look at things independent of visible actors or items.&lt;br /&gt;
&lt;br /&gt;
- You may find it useful to give meaningful names to your cameras if you are using more than one or two. (You might name a camera after the actor or placeable that it follows or name one camera ‘close-up’ and another ‘wide-angle’ for example.)&lt;br /&gt;
&lt;br /&gt;
- If you are panning a camera around a room following a series of actors or placeables and you find that the camera suddenly decides to rotate in the other direction you can force it to stay moving in the direction you desire by adding or subtracting 360 degrees from the position/orientation you are using to move the camera.&lt;br /&gt;
&lt;br /&gt;
- Feel free to experiment with animations. Try using animations that are not normally meant for your actor type, you might find some interesting or bizarre movements for your actor.&lt;br /&gt;
&lt;br /&gt;
- You can put multiple actions along one track as long as they do not overlap rather than using many different tracks.&lt;br /&gt;
&lt;br /&gt;
- Pay attention to what your key frames ‘transition out’ are set to when moving your cameras. Step will jump the camera from position to position while Bezier and Linear will move the camera in a smoother motion. If you are not getting the desired effect when moving cameras check what your key frames ‘transition out’ are set to.&lt;br /&gt;
&lt;br /&gt;
- If you have a longer more detailed cutscene you can keep the number of cameras you use to a reasonable number by just moving one (or more) around while another camera is the ‘active’ camera.&lt;br /&gt;
&lt;br /&gt;
- For testing purposes change the length of the cutscene in the cutscenes properties to a smaller value and enlarge that number as you add on to the cutscene. In this way you won’t need to wait for a long period of time for the cutscene to end.&lt;br /&gt;
&lt;br /&gt;
- After placing an animation on a track you can speed up the animation by left clicking on the small circular arrows on one end and dragging it shorter or make the animation play slower by dragging the animation longer on the track.&lt;br /&gt;
&lt;br /&gt;
- You can make the content of your scene seem to change by placing invisible objects in the cutsence, using an fx to obscure the view and making the object visible while the fx is playing. (For example you might have some invisible rock debris. Use a cave in fx with clouds of dust to obscure the screen. While the fx is playing make the debris visible. When the fx is finished your debris will be in place.)&lt;br /&gt;
&lt;br /&gt;
- If you find that your actor is walking across surfaces (such as water for instance) when they should be following the ground you can set ‘items follow surface’ in the area that your cutscene is based on. The actor should then walk on the ground and thus wade into the water. Conversely if you want a character or placeable to not follow the surface of the ground (for instance if you want a placeable or actor to be near or on the surface of water) move the actor or placeable higher by adjusting the Z axis of the boat or actor. (An example of using a placeable partly submerged in water might be something like a boat.)&lt;br /&gt;
&lt;br /&gt;
- In a cutscene you can only activate things that are unique. As in if you plopped down three identical chests in an area, when trying to activate them all in a cutscene it will not allow this and gives you a warning message. In the example above you would have to make three different chests (though they could look the same) to be able to activate them all in the cutscene.&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Cutscene_tutorial&amp;diff=16087</id>
		<title>Cutscene tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Cutscene_tutorial&amp;diff=16087"/>
				<updated>2011-04-20T16:43:16Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Adding dialogue */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox cutscenes}}&lt;br /&gt;
&lt;br /&gt;
[[Cutscene]]s can be stand-alone cinematic sequences that are triggered by scripts in the course of the game, or they can be inserted into [[conversation]]s in place of the simplified cinematics that conversations can automatically generate.&lt;br /&gt;
&lt;br /&gt;
Our example situation in this tutorial will serve as the beginning of a conversation between the player and two NPCs. The player has just arrived at the campsite where these two NPCs are staying. He walks up to the fire. One of the NPCs is happy to see the player and greets him, but the other is distrustful. The two share a brief exchange to establish this before the interactive part of the conversation begins.&lt;br /&gt;
&lt;br /&gt;
== Creating a new cutscene ==&lt;br /&gt;
&lt;br /&gt;
To create a brand new blank cutscene resource, create a new resource in the usual way:&lt;br /&gt;
&lt;br /&gt;
[[Image:New resource.png]]&lt;br /&gt;
&lt;br /&gt;
The result is opened in the cutscene editor.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene new.png|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
There are two basic sections to the cutscene editor; the viewports (top) and the timeline (bottom).&lt;br /&gt;
&lt;br /&gt;
=== Viewports ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Viewports can be attached to various cameras to preview what they can see&lt;br /&gt;
* Add a &amp;quot;Safe Frame&amp;quot; to camera viewports to ensure the correct aspect ratio&lt;br /&gt;
* Set a viewport to &amp;quot;User&amp;quot; to see where cameras are positioned from another perspective. This can be done by selecting &amp;quot;Detach From Camera&amp;quot; in the viewport's right-click menu in the title bar&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The camera viewports in the cutscene editor work similarly to the viewports in the stage editor. You can set the number and layout of viewports under the &amp;quot;View&amp;quot; menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial viewport layout.png]]&lt;br /&gt;
&lt;br /&gt;
And for each individual viewport you can select which camera it's showing and set other display options by right-clicking on the title bar of the viewport:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial viewport properties.png]]&lt;br /&gt;
&lt;br /&gt;
When you set a viewport to show the view through one of the cutscene's cameras, it's a good idea to turn on that viewport's &amp;quot;Safe Frame&amp;quot; option as well. This will put a border on the viewport showing what will be visible when the cutscene plays.&lt;br /&gt;
&lt;br /&gt;
Note that when you play the cutscene in the cutscene editor, only the currently selected viewport (the one with the blue title bar) will show the cutscene &amp;quot;live&amp;quot; - the others won't update the view displayed in them until they're selected. To preview the cutscene as the player would see it, then, you should set one of the viewports to &amp;quot;Active Camera&amp;quot; and ensure that this viewport is selected when you play the cutscene in the editor. If the &amp;quot;Active Camera&amp;quot; viewport turns gray, try setting the cutscene property &amp;quot;Enable Level Effects&amp;quot; to false.&lt;br /&gt;
&lt;br /&gt;
=== Timeline ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* There is always exactly one MASTER object in a cutscene.&lt;br /&gt;
* Each active object is listed on the timeline, with multiple &amp;quot;tracks&amp;quot; for each.&lt;br /&gt;
* All objects have position tracks (divided into X, Y and Z tracks). Some objects have additional built-in tracks.&lt;br /&gt;
* Other actions and effects can be added to generic tracks. Objects can have as many generic tracks as you want.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Below the viewport is the timeline. Along the top of the timeline is a time scale; it can be set either to show frames (at 30 frames per second) or milliseconds by changing the &amp;quot;Time Scale&amp;quot; property if the cutscene in the object inspector.  A marker indicates what point in the timeline the viewports are currently showing.&lt;br /&gt;
&lt;br /&gt;
Below are a set of rows containing the various actors, cameras, and other objects active in the cutscene. This is where most of the editing is going to take place. Each object will have a number of &amp;quot;tracks&amp;quot;, which will contain commands that are sent to the actors at particular times in the course of the cutscene.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene tutorial timeline.png]]&lt;br /&gt;
&lt;br /&gt;
The first object in the track list is the &amp;quot;MASTER&amp;quot; object. This is a special object that every cutscene has exactly one of. The MASTER object is the cutscene equivalent to the root node of a conversation tree, a repository for global settings and effects. For example the MASTER object contains the track that determines which camera is active at any given time. The MASTER object cannot be deleted. By default, a MASTER object appears in the cutscene editor as a small greenish sphere; you can change the MASTER object's appearance in the cutscene option settings.&lt;br /&gt;
&lt;br /&gt;
A new cutscene also has a camera, called Camera 1. This camera can be deleted or renamed if you like; we can add new cameras as needed later on.&lt;br /&gt;
&lt;br /&gt;
Every object has &amp;quot;Position&amp;quot; and &amp;quot;Orientation&amp;quot; tracks that control their locations in space. Cameras also have a FOV (field of view) track.&lt;br /&gt;
&lt;br /&gt;
Objects can have other &amp;quot;generic&amp;quot; tracks added by the editor as needed. These generic tracks contain all the other commands and directions we can give.&lt;br /&gt;
&lt;br /&gt;
== The setting of the cutscene ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* The MASTER object should be moved somewhere near the center of your cutscene.&lt;br /&gt;
* You can optionally set a stage for your cutscene, enabling stage-related actions for objects.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Establishing the setting of a cutscene is done in the object inspector in the group of properties labeled &amp;quot;Setting&amp;quot;. The most important of these is the &amp;quot;Area&amp;quot; property, which allows you to set the cutscene in an existing [[area]]. We already have a suitable area that was created in an earlier tutorial; the area &amp;quot;great_outdoors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
By default the MASTER object and Camera 1 will be located at the coordinates 0,0,0 in the area. You'll want to move the camera to the appropriate location within the area using standard [[3D control]]s for movement and view management. The MASTER object is invisible when the cutscene is played in-game so it usually doesn't matter where you put it. However, there are some settings that depend on the MASTER object's location - for example, you can set level-of-detail for models so that the model's LOD varies depending on how close it is to the MASTER object - so it's probably a good idea to put MASTER somewhere near the middle of where you'll be having the cutscene's action take place.&lt;br /&gt;
&lt;br /&gt;
You can also set a stage for the cutscene. This is optional, but setting a stage enables &amp;quot;Jump to Stage Place&amp;quot; and &amp;quot;Jump to Stage Camera&amp;quot; actions that could help make setting the cutscene up easier if you already have a good stage defined in the area.&lt;br /&gt;
&lt;br /&gt;
=== Adding objects and creatures ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Objects already present in the area the cutscene is set in are inactive by default. You need to activate them to control them.&lt;br /&gt;
* Other objects can be added from the resource palette as normal.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
All of the objects that are normally present in the area (such as creatures and placeables) will be visible in the cutscene editor, but they'll all initially be marked as &amp;quot;inactive&amp;quot;. This means that, although they'll be visible in the cutscene when it plays, they won't be controllable; they'll just do whatever ambient activities they would be doing normally. In the case of our campsite area there are two creatures that were placed here in the area editor; the happy camper, named camp_happy, and the angry camper, named camp_angry. We need to seize control of them to make them active participants in the cutscene's activities. To make them active, right-click on them and select &amp;quot;activate objects&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene activate object.png]]&lt;br /&gt;
&lt;br /&gt;
The object will then become an active object in the cutscene, getting its own entry in the timeline that will allow you to control its actions.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene object activated.png]]&lt;br /&gt;
&lt;br /&gt;
We'll activate both of these campers since they'll both be taking part in the cutscene's dialogue.&lt;br /&gt;
&lt;br /&gt;
You can also add objects that aren't normally a part of the area. Simply open the object palette, select the creature or placeable you wish to use in the cutscene, and then click in the viewport to add the object to that location. It will automatically be made active and get an entry in the timeline. The player won't see these objects during regular play, since they're not a part of the area - they're only in the cutscene.&lt;br /&gt;
&lt;br /&gt;
If you want to make an area object disappear during the cutscene you'll need to activate it (allowing you to control it) and then add a track with an action that makes it invisible in the first frame. It will go back to normal again when the cutscene ends and the game resumes, cutscenes are run entirely separate from the main action of the game and have no direct effects on it.&lt;br /&gt;
&lt;br /&gt;
=== Adding the player ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Use the &amp;quot;Mapping Tag&amp;quot; property on an actor to make the game replace it with another object (such as PLAYER) at run-time.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Normally we don't have to worry about placing the player in an area since the player controls his own movements and actions. But when we're doing a cutscene we can control the player just like any other actor, so we'll need a way to insert the player as an active object. Furthermore, since we'll have no idea what the player is going to look like at any given moment, we'll need to have a way to insert the player as he appears in the game when the cutscene begins.&lt;br /&gt;
&lt;br /&gt;
This is done by inserting a &amp;quot;dummy&amp;quot; virtual actor and then setting the actor's &amp;quot;Mapping Tag&amp;quot; property to the special &amp;quot;PLAYER&amp;quot; tag. &lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene dummy player.png|thumb|center|600px]]&lt;br /&gt;
&lt;br /&gt;
It doesn't matter what the dummy actor looks like now, it will be replaced with the player's character later on, so we'll just use a default male human model to make it both simple and obvious.&lt;br /&gt;
&lt;br /&gt;
There are ways to tweak the way the cutscene plays based on other characteristics of the player, for example by modifying the position of the camera to account for the player's height or by adding additional dummies to represent followers. We won't go into these more advanced topics in this tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Adding cameras ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Remember to enable Safe Frame when attaching a viewport to a camera.&lt;br /&gt;
* Use an &amp;quot;Active Camera&amp;quot; viewport to preview the cutscene.&lt;br /&gt;
* Use a &amp;quot;User&amp;quot; viewport to see camera positions from the outside. This can be done by selecting &amp;quot;Detach From Camera&amp;quot; in the viewport's right-click menu in the title bar.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
We could film a cutscene entirely from one camera if we liked, either as a single static shot or by moving the camera around to new positions as needed. It's easier and more convenient in most cases just to add several different cameras, however, and use the &amp;quot;Active Camera&amp;quot; track on the MASTER object to switch between them.&lt;br /&gt;
&lt;br /&gt;
For our cutscene we're going to want three different cameras; one camera that's a wide shot showing the player arriving at the campfire, one camera focused on the angry camper, and one focused on the happy camper. We could add more than just these three to make the scene even more dynamic but for simplicity we'll stick to just those for now. We can add more later.&lt;br /&gt;
&lt;br /&gt;
Cameras are added by right-clicking in the viewport and selecting &amp;quot;Insert &amp;amp;rarr; Camera&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene insert camera.png]]&lt;br /&gt;
&lt;br /&gt;
You can then position them using standard [[3D control]]s. To make it easier to get the camera set up with the correct view, a good technique is to set one of the viewports to display the camera's feed; you can then reorient and reposition the camera using that viewport's camera controls while getting immediate feedback as to what the camera will see in its new state.&lt;br /&gt;
&lt;br /&gt;
We're also going to rename the three cameras at this point with names intended to remind us of what their purposes are. We'll name them &amp;quot;Arrival Camera&amp;quot;, &amp;quot;Happy Camera&amp;quot;, and &amp;quot;Angry Camera&amp;quot;. We'll want &amp;quot;Arrival Camera&amp;quot; to be active initially, so we may as well use the original camera for this role; it's already set active by default. We'll see how to switch which camera is active later in this tutorial.&lt;br /&gt;
&lt;br /&gt;
We now have all the basic props we need to get the cutscene going.&lt;br /&gt;
&lt;br /&gt;
== Adding an animation to an actor ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Set the &amp;quot;Pose&amp;quot; property for actors to make them breathe and fidget naturally when not doing other animations.&lt;br /&gt;
* Other animations are set by adding &amp;quot;Play Animation&amp;quot; actions to a generic track.&lt;br /&gt;
* Animation filenames are often arcane and hard to find.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
If you play the cutscene now the first thing you'll probably notice is that the actors are all standing perfectly motionless. Normally someone who's standing still isn't really standing ''perfectly'' still; they breathe, they shift their weight from foot to foot, and so forth. Since almost every actor we use is going to need to do this we don't want to have to spend a lot of effort setting it up, and fortunately we don't have to. Every actor has a &amp;quot;Pose&amp;quot; property in the object inspector. Simply set this pose to &amp;quot;Standing Neutral&amp;quot; and the actors will display this default subtle movement whenever no other animations are being explicitly imposed on them.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene set pose.png]]&lt;br /&gt;
&lt;br /&gt;
Our next task is somewhat less trivial; we want to show the player walking up to the fire. We're going to have to add a walking animation to the player's actor that runs for a short period of time and then stops.&lt;br /&gt;
&lt;br /&gt;
To do this we'll need to add a new track to the actor's timeline. Right-click on the actor's entry in the timeline and select &amp;quot;Add Track&amp;quot; from the resulting menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene add track.png]]&lt;br /&gt;
&lt;br /&gt;
The new track will be named &amp;quot;New Track&amp;quot; by default and will start out empty. Actors in cutscenes will sometimes have dozens of tracks directing their actions so we'll want to rename the track to something a little more informative. In this case we'll name it &amp;quot;Walk to fire&amp;quot;. To have it actually cause the player's actor to walk to the fire we'll need to add a &amp;quot;[[Play animation]]&amp;quot; action to it. Right-click on the track and select &amp;quot;Add Action&amp;quot; to get the menu to select this.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene add action.png]]&lt;br /&gt;
&lt;br /&gt;
The action will be added starting at the point you're currently viewing in the timeline, so you may wish to move the timeline's time slider back to the beginning before adding this animation. You can reposition an action along the timeline simply by dragging it with the mouse.&lt;br /&gt;
&lt;br /&gt;
Initially the action has no animation associated with it. To set the animation, select the action in the timeline and then in the Object Inspector go to the &amp;quot;Animation&amp;quot; property and click on the ellipsis ([[Image:ellipsis.png]]) button.&lt;br /&gt;
&lt;br /&gt;
Unfortunately this is where things turn a bit arcane since the names of the various animation files are often very unclear and not all will appear in the default list. You may need to resort to trial and error to find one you like, but there are many hundreds of animations available in the game's resources so this could take some time. See [[animation list]] and [http://social.bioware.com/project/30/#files Beerfish Excel Utilities] for a list of many of them.&lt;br /&gt;
&lt;br /&gt;
Note that only a single animation can play at any time on a given track. However, it is possible to have multiple animations for a character, each of which must be on a different track. This is essential in order to be able to blend animations together as detailed in [[Play_animation#Blending_Animations]]. Animation blending is necessary in order to have your characters transition seamlessly from one animation to another, which is essential to making character movement look natural.&lt;br /&gt;
&lt;br /&gt;
In this case the animation we want, &amp;quot;mh.dg_f_5p&amp;quot; (&amp;quot;male human dialog forward five paces&amp;quot;), doesn't appear in the default list of animations available in the animation picker. You'll need to click the ellipsis button next to the &amp;quot;Custom Animation&amp;quot; field and find it in the complete list of all animation resources.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene finding an animation.png]]&lt;br /&gt;
&lt;br /&gt;
If you try playing the cutscene now you'll see that the player's actor will spend a little over five seconds walking and then come to a natural stop - about as long as we needed. But the actor will be animated in place, his legs taking steps but not actually moving him anywhere. This is where position keys and GAD comes in.&lt;br /&gt;
&lt;br /&gt;
== Moving an actor ==&lt;br /&gt;
&lt;br /&gt;
=== Position and orientation keys ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Objects be moved over time by setting &amp;quot;key frames&amp;quot; on their position and orientation tracks.&lt;br /&gt;
* Intermediate frames are interpolated between key frames.&lt;br /&gt;
* You can set the curve type between key frames with the &amp;quot;transition out&amp;quot; property for each key.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Every object in a cutscene has a pre-defined &amp;quot;Position&amp;quot; track with three sub-tracks for its X, Y and Z coordinates. Most objects also have a pre-defined &amp;quot;Orientation&amp;quot; track with three subtracks for roll, pitch, and yaw. These tracks can be used to cause an object to move around within the area over the course of the cutscene.&lt;br /&gt;
&lt;br /&gt;
Movement is handled by setting the position and orientation of objects at specific points in time, called key frames, and then interpolating intermediate positions and orientations. To set a key frame, right-click on the actor's entry in the timeline and select &amp;quot;key position&amp;quot;. This will set a key for the current position and orientation at the current time in the timeline. You can set position and orientation keys separately if you like. Since this operation is so common there's a very convenient shortcut for it; &amp;quot;k&amp;quot; inserts a key for the currently selected object's position and orientation, &amp;quot;p&amp;quot; inserts a key for its position, and &amp;quot;o&amp;quot; inserts a key for its orientation. Alternately, select the object and click the key command in the toolbar: [[Image:IconKey.png]]&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene key selection.png]]&lt;br /&gt;
&lt;br /&gt;
For our purposes right now all we'll need to do is set a key frame at the beginning of the timeline. Move the pointer to the beginning, select the player actor, and set a key. Small boxes will appear on the position and orientation tracks to mark the key frame.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene key marker.png]]&lt;br /&gt;
&lt;br /&gt;
These markers essentially mean &amp;quot;at this particular point in time, dummy_player will be in this particular place and facing in this particular direction.&amp;quot; &lt;br /&gt;
&lt;br /&gt;
To get an actor to move over time you could set two key frames - one at the beginning of the movement, with the actor in his starting position, and one at the end of the movement, with the actor at his end position. You can set how the cutscene engine interpolates between the two positions by setting the &amp;quot;Transition Out&amp;quot; property of the starting keyframe to either Bezier (a smooth curve), Linear (a straight line), or Step (a sudden jump from the starting position to the end position). See the [[curve editor]] page for more detail.&lt;br /&gt;
&lt;br /&gt;
We're not going to actually do this in this case, however; we'll try it at a later point in this tutorial to move a camera around. For this particular actor it would be difficult to manually match the actor's walking action with his motion over the ground. If the animation and the movement don't match the actor's feet will &amp;quot;skate&amp;quot; unrealistically along the surface.&lt;br /&gt;
&lt;br /&gt;
There's an easier way to match an animation such as this one with movement through the scene; a mechanism called GAD.&lt;br /&gt;
&lt;br /&gt;
=== Using GAD ===&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* GAD is a mechanism by which an animation applies a built-in displacement to the object it's animating.&lt;br /&gt;
* You need to set at least one key frame for an object to use GAD, even if you don't otherwise use key frames to move it.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
GAD is a displacement that is automatically added to the actor's current position as the animation plays. Each animation has its own GAD information built into it, custom-designed to make the actor move in a manner appropriate to its actions. If we enable it the actor will be moved forward as the animation plays.&lt;br /&gt;
&lt;br /&gt;
Not all animations have GAD associated with them. For example, having an actor wave his hand wouldn't displace him, so there would be no GAD associated with that animation. We only need to worry about GAD in cases like this one where the animation should accompany movement.&lt;br /&gt;
&lt;br /&gt;
To enable GAD select the animation action and set &amp;quot;Play Gad&amp;quot; to true in the object inspector. If no key frames have been defined for the actor the cutscene editor will pop up a warning at this point suggesting that we add position and orientation keys before we add GAD:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene gad warning.png]]&lt;br /&gt;
&lt;br /&gt;
It's important to set at least one set of keys for an object using GAD. The animation's GAD may seem to work correctly without it at first, but unexpected and unpredictable errors could occur later that will send the actor careening off into the distance.&lt;br /&gt;
&lt;br /&gt;
Once we've set a key frame and have set the action's &amp;quot;Play Gad&amp;quot; option to true you'll see that the actor now moves forward as he walks. This is good, but since we started him off in the position he's meant to end in it results in the actor walking straight through the campfire. You'll need to move the actor back so that he starts farther away from the fire.&lt;br /&gt;
&lt;br /&gt;
Note that if you've already set a keyframe as described in the previous section you'll need to re-set it for the actor's new location (or alternately set the &amp;quot;update keys&amp;quot; mode with the [[Image:IconUpdateKeys.png]] tool), otherwise the moment the animation starts the actor will instantly jump back to the place he was where you set the keyframe. Once you set a keyframe for an actor, moving the actor around in the cutscene editor doesn't really change its position unless you re-set the keyframe to the new position. Keyframes and the curves interpolating between them always take precedence. &lt;br /&gt;
^&lt;br /&gt;
|&lt;br /&gt;
(ED: This need extreme explanation by someone that knows how to do this properly because this paragraph is obtuse!!)&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* An animation's &amp;quot;Extend Gad Beyond Action&amp;quot; property makes Gad's displacement persist after the animation ends.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The other GAD properties are set to the most appropriate defaults automatically when you select an animation but one particular property bears mention here in case you run into trouble with it later on; the &amp;quot;Extend Gad Beyond Action&amp;quot; property. In the case of this walking animation it defaults to true. That means that once the animation ends, the displacement that the actor has undergone as a result of it will remain in effect - he will stay in the final position he walked to. If this were set to false, once the animation ended all of the displacement the actor had gained as a result would be undone and he'd instantly jump back to where he started walking from again. If at some point in the future you find your actors doing this, this property is the first place to look for the answer.&lt;br /&gt;
&lt;br /&gt;
There's one final detail we'll tweak here. The walking animation begins with the player starting from a standstill, which is not the impression we want to convey; the player has supposedly been walking for some time before the camera started rolling. We could set the animation to begin playing partway through by changing the animation action's &amp;quot;Start Offset&amp;quot; property, but since this is happening at the beginning of the cutscene's timeline an easier approach is to simply select the animation action and drag it so that it begins a half second before the cutscene does. The cutscene will only begin displaying at the 0 mark and anything that falls before this point in time will never be shown so the initial half second of the actor's walk animation will go unseen.&lt;br /&gt;
&lt;br /&gt;
== Moving a camera ==&lt;br /&gt;
&lt;br /&gt;
The scene now has some of the dynamic action we wanted, showing the player walking up to the campfire and stopping at its edge. But it's still a rather dull introduction and we can do better. Instead of a static camera shot we can set the camera so that it pans across the scene to follow the player's arrival.&lt;br /&gt;
&lt;br /&gt;
Select the Arrival Camera and open up its track list. It has Position and Orientation tracks just like the other actors, and can have keyframes set just the same. With the time marker set to 0, move the Arrival Camera so that its view shows how you want the shot framed at the beginning of the cutscene. In our example we're going to set it so that it shows the player in the center of the frame. With the camera still selected, press &amp;quot;k&amp;quot; to set a key frame for the camera.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera start position.png]]&lt;br /&gt;
&lt;br /&gt;
(You may notice that the Field of View (FOV) track also gets a key marker. We won't be changing the camera's FOV so you can ignore that.)&lt;br /&gt;
&lt;br /&gt;
Next move the timeline scrubber to the end of the walking animation at the 5 second mark. The player's actor will now be at the final position where he'll be standing for the conversation. Change the camera's orientation, panning to the right so that all of the actors can be seen in its field of view. In our case the camera's too close to encompass everyone so we'll also move its position to allow it to see them all.&lt;br /&gt;
&lt;br /&gt;
Once you have the shot lined up correctly, press &amp;quot;k&amp;quot; to set a second keyframe.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera end position.png]]&lt;br /&gt;
&lt;br /&gt;
You may notice that the User viewports now show a red line tracing out the selected object's trajectory through space (if not, you may need to click the &amp;quot;show trajectories&amp;quot; [[Image:IconShowTrajectory.png]] button in the toolbar). As the first five seconds of the cutscene plays, the Arrival Camera should slide smoothly along the red line and rotate smoothly on its axes to transition from the first keyframe to the second keyframe (If it suddenly jumps from one position to the other instead you may need to click the &amp;quot;default curve mode&amp;quot; tool [[Image:IconDefaultCurveMode.png]] and try setting the keys again, or change the &amp;quot;transition out&amp;quot; property of the keyframe to Bezier).&lt;br /&gt;
&lt;br /&gt;
You can fine-tune the trajectory of the camera by adding additional keyframes between the starting and ending ones. In our case we see that when the time marker is set to the middle of the camera's movement the player slips slightly out of frame.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera middle position unadjusted.png]]&lt;br /&gt;
&lt;br /&gt;
We can fix this by changing the camera's position and orientation as needed, and then adding a new keyframe with &amp;quot;k&amp;quot;. In this case we'll pull the camera back slightly so that its motion through space becomes a curve instead of a straight line.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene camera middle position adjusted.png]]&lt;br /&gt;
&lt;br /&gt;
We now have a nice, dynamic establishing shot. The scene begins with the player alone and in the center of the camera's shot, and as he walks toward the fire the camera moves and pans around him to show him arriving in the presence of our two campers.&lt;br /&gt;
&lt;br /&gt;
== Switching cameras ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* A track on the MASTER object defines which camera is currently &amp;quot;active.&amp;quot;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Once the player arrives he is going to be greeted by the camper who is happy to see him. To give a clear shot of who's doing the talking, we'll want to switch the active camera from Arrival Camera to Happy Camera.&lt;br /&gt;
&lt;br /&gt;
The track where the active camera gets changed is attached to the MASTER object. Move the timeline's time indicator to the point in time where you wish to switch active cameras, in this case 5.5 seconds (giving the scene a half-second view of the player after he's come to a halt). Right-click on the Active Camera track and select Add Action. The only option available for this track is the &amp;quot;Switch Camera&amp;quot; action so go ahead and add one. In the new Switch Camera action's properties set it to switch the active camera to Happy Camera.&lt;br /&gt;
&lt;br /&gt;
Now when the cutscene is played we'll get an establishing shot showing the player walking up to the fire and then switch to a closeup of the happy camper so that he can deliver his greeting.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene switch active camera.png]]&lt;br /&gt;
&lt;br /&gt;
== Adding dialogue ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Lines of dialog can be inserted from an existing [[conversation]] resource. For convenience, create a new conversation to hold the dialog for a cutscene.&lt;br /&gt;
* Caption text, voice over, and facial performance are all included with each line.&lt;br /&gt;
* If you edit the conversation later, the changes will be reflected in the cutscene. Remember to generate new VO and FaceFX in the conversation editor.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are three major components to dialog in Dragon Age; the text of the line being spoken (which is displayed as a caption at the top of the screen), the voice-over for the line being spoken, and the facial performance that makes the virtual actor lip-synch and display appropriate emotions.&lt;br /&gt;
&lt;br /&gt;
There's already a tool in the toolset that is designed for handling all of these things; the conversation editor. Actors in a cutscene can be given &amp;quot;Speak Line&amp;quot; actions that cause them to deliver lines from an existing dialog, with all three components added together into the actor's performance automatically.&lt;br /&gt;
&lt;br /&gt;
Here we are going to add dialogue to a cutscene (though sometimes it is better to take a [[http://social.bioware.com/wiki/datoolset/index.php/Conversation#Conversation-centred_approach | conversation-centred approach]]).&lt;br /&gt;
&lt;br /&gt;
To create the dialog for this cutscene we'll now create a new conversation resource. This conversation is not going to be used in the game directly so we'll be able to ignore many of the more advanced features and settings covered in the conversation tutorial; its only purpose is to serve as a repository of dialog lines for use in this cutscene.&lt;br /&gt;
&lt;br /&gt;
The following screenshot shows our intended conversation. The only things that we need to define for it is the text of the dialog and optionally the emotion settings for RoboBrad to use when generating facial performance. As with our previous conversation we'll generate synthesized placeholder voice-over and generate FaceFX based on that; when we record real voice over later on we can simply update this conversation with it and the cutscene's performance will change to match.&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene conversation.png]]&lt;br /&gt;
&lt;br /&gt;
To help keep track of which lines are spoken by which actors you could also optionally set the speaker tag on each line to identify who's doing the talking. This particular conversation has only two speakers so we won't bother with that. The cutscene engine won't need speaker tags, we'll be explicitly telling it who is saying each line. You'll only need to set those things if you wish to preview the conversation before using its lines in the cutscene.&lt;br /&gt;
&lt;br /&gt;
Once you've created your dialogue go back to the cutscene editor and add a new track to the camp_happy actor. Rename it to something informative, such as &amp;quot;Dialogue&amp;quot;. Move the timeline marker to the spot where you want the actor to start speaking and add a new &amp;quot;Speak Line&amp;quot; action.&lt;br /&gt;
&lt;br /&gt;
In the Speak Line action's properties, set the &amp;quot;Source Conversation&amp;quot; property to the conversation resource we just created. Then, select the specific line you want the actor to speak in the &amp;quot;Source Line&amp;quot; property (it will have a drop-down menu with all of the lines from the source conversation in it).&lt;br /&gt;
&lt;br /&gt;
That's all you need to do to get the actors to talk. You may wish to add one other detail at this point; head tracking. This is the action that causes actors to turn their heads toward a specific target, usually the person they're talking to or who is talking to them. It's added as its own action, so create another track and add a headtracking action to it with the player as the target. In this case we want the happy camper to turn his head toward the player right before he starts speaking.&lt;br /&gt;
&lt;br /&gt;
== Adding other details ==&lt;br /&gt;
&lt;br /&gt;
{{sidebox|&lt;br /&gt;
* Headtracking actions make actors look at other objects in the cutscene.&lt;br /&gt;
* You can have more than one action on a track provided they don't overlap.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
We've now gone through all the basics, so we'll just finish fleshing out the conversation with a few other details that are done the same way as the examples above.&lt;br /&gt;
&lt;br /&gt;
To add a little more animation to the scene, we add another track for camp_happy with an animation action (mh.dg_hnd_salute_01, a salute) to play during his spoken line. This animation is simpler to deal with than the walking animation because it doesn't displace the actor; there's no need to define position keys or worry about enabling GAD.&lt;br /&gt;
&lt;br /&gt;
We'll set camp_angry's headlook so that she turns toward camp_happy while he's speaking; when we subsequently switch cameras to show her line of dialog she'll already be looking in his direction.&lt;br /&gt;
&lt;br /&gt;
For camp_happy's next line, however, we'll make the headtracking change visible during his shot so the player will see how his attention has switched to camp_angry. Note that we can reuse the existing &amp;quot;Dialogue&amp;quot; and &amp;quot;Headtracking&amp;quot; tracks for this actor; we don't need to create a new track for every single action that an actor performs. So long as the durations of the actions on a track don't overlap they can coexist peacefully.&lt;br /&gt;
&lt;br /&gt;
Finally, after camp_angry's last line we'll set her headtracking to look back toward the player. He's going to get the next word in when we integrate this cutscene into a conversation so this is a good way to indicate that the conversation's focus has gone to the player now.&lt;br /&gt;
&lt;br /&gt;
Once we've finished crafting the cutscene we now know how long its duration needs to be. You can now go to the conversation's properties in the Object Inspector and set the cutscene's duration to the desired length.&lt;br /&gt;
&lt;br /&gt;
The finished timeline of our cutscene:&lt;br /&gt;
&lt;br /&gt;
[[Image:Cutscene finished timeline.png]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
[[Category:Cutscenes]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Cutscene Tips and Tricks ===&lt;br /&gt;
&lt;br /&gt;
Here are a few tips and tricks that might save the cutscene creator some time and perhaps hair pulling.&lt;br /&gt;
&lt;br /&gt;
- Head tracking is often used to look at another actor or a visible item in the cutscene. However you can further manipulate the head of the actor by having the actor look at invisible objects. You can have the actor look from one invisible object to another or move the invisible object around in the cutscene to get the actor to look at things independent of visible actors or items.&lt;br /&gt;
&lt;br /&gt;
- You may find it useful to give meaningful names to your cameras if you are using more than one or two. (You might name a camera after the actor or placeable that it follows or name one camera ‘close-up’ and another ‘wide-angle’ for example.)&lt;br /&gt;
&lt;br /&gt;
- If you are panning a camera around a room following a series of actors or placeables and you find that the camera suddenly decides to rotate in the other direction you can force it to stay moving in the direction you desire by adding or subtracting 360 degrees from the position/orientation you are using to move the camera.&lt;br /&gt;
&lt;br /&gt;
- Feel free to experiment with animations. Try using animations that are not normally meant for your actor type, you might find some interesting or bizarre movements for your actor.&lt;br /&gt;
&lt;br /&gt;
- You can put multiple actions along one track as long as they do not overlap rather than using many different tracks.&lt;br /&gt;
&lt;br /&gt;
- Pay attention to what your key frames ‘transition out’ are set to when moving your cameras. Step will jump the camera from position to position while Bezier and Linear will move the camera in a smoother motion. If you are not getting the desired effect when moving cameras check what your key frames ‘transition out’ are set to.&lt;br /&gt;
&lt;br /&gt;
- If you have a longer more detailed cutscene you can keep the number of cameras you use to a reasonable number by just moving one (or more) around while another camera is the ‘active’ camera.&lt;br /&gt;
&lt;br /&gt;
- For testing purposes change the length of the cutscene in the cutscenes properties to a smaller value and enlarge that number as you add on to the cutscene. In this way you won’t need to wait for a long period of time for the cutscene to end.&lt;br /&gt;
&lt;br /&gt;
- After placing an animation on a track you can speed up the animation by left clicking on the small circular arrows on one end and dragging it shorter or make the animation play slower by dragging the animation longer on the track.&lt;br /&gt;
&lt;br /&gt;
- You can make the content of your scene seem to change by placing invisible objects in the cutsence, using an fx to obscure the view and making the object visible while the fx is playing. (For example you might have some invisible rock debris. Use a cave in fx with clouds of dust to obscure the screen. While the fx is playing make the debris visible. When the fx is finished your debris will be in place.)&lt;br /&gt;
&lt;br /&gt;
- If you find that your actor is walking across surfaces (such as water for instance) when they should be following the ground you can set ‘items follow surface’ in the area that your cutscene is based on. The actor should then walk on the ground and thus wade into the water. Conversely if you want a character or placeable to not follow the surface of the ground (for instance if you want a placeable or actor to be near or on the surface of water) move the actor or placeable higher by adjusting the Z axis of the boat or actor. (An example of using a placeable partly submerged in water might be something like a boat.)&lt;br /&gt;
&lt;br /&gt;
- In a cutscene you can only activate things that are unique. As in if you plopped down three identical chests in an area, when trying to activate them all in a cutscene it will not allow this and gives you a warning message. In the example above you would have to make three different chests (though they could look the same) to be able to activate them all in the cutscene.&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Conversation&amp;diff=16086</id>
		<title>Conversation</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Conversation&amp;diff=16086"/>
				<updated>2011-04-20T16:26:27Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Cinematics and Animation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;float:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| {{Resource palette}}&lt;br /&gt;
|-&lt;br /&gt;
| {{Infobox conversation}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Conversations contain lines of dialogue, usually focused on one NPC and the player's interaction with him or her. Each line of dialogue can have the following associated with it:&lt;br /&gt;
*The text of the line, which can be displayed in-game&lt;br /&gt;
*The [[Voice-Over]] (for non-player characters)&lt;br /&gt;
*The speaker's facial performance (lip synching and expression)&lt;br /&gt;
*[[Stage]] information for positioning the actors and cameras in an area (optional, some conversations can occur anywhere and use default staging)&lt;br /&gt;
*[[Cutscene]] cinematics that can potentially override any of the above with more detailed and complex events.&lt;br /&gt;
&lt;br /&gt;
A conversation is usually associated with a [[creature]], which is referred to in the conversation with the &amp;quot;OWNER&amp;quot; tag. They can also be associated with placeables, or simply used as a container for lines of dialogue used in a cutscene.&lt;br /&gt;
&lt;br /&gt;
The main body of the display for this type of object is one or more tree-shaped structures containing all of the lines or actions that can be reached in the course of following this conversation. For example:&lt;br /&gt;
&lt;br /&gt;
[[Image:Conversation tutorial 2.png]]&lt;br /&gt;
&lt;br /&gt;
Red lines are those spoken by NPCs, blue lines are those spoken by the player (usually chosen from a group of alternatives). Grey lines are lines that are 'linked' to other lines, allowing the flow of the conversation to jump to other branches or repeat itself if needed.&lt;br /&gt;
&lt;br /&gt;
Below the main display is a tabbed pane containing options that can be set on a line-by-line basis.&lt;br /&gt;
&lt;br /&gt;
== Global Settings ==&lt;br /&gt;
&lt;br /&gt;
The global settings tab is only present when the root node of the entire conversation is selected. This is where one can set defaults for who is listening and who is talking (in conversations with more than two individuals you'll need to override these defaults on a line-by-line basis as needed).&lt;br /&gt;
&lt;br /&gt;
You can also set a number of flags involved in cinematic effects:&lt;br /&gt;
*Lock all gestures&lt;br /&gt;
*Lock all poses&lt;br /&gt;
*Lock all RoboBrad&lt;br /&gt;
*Lock all cameras&lt;br /&gt;
*Ambient Soundset Type&lt;br /&gt;
&lt;br /&gt;
Also available in the root node are a simplified plot and scripting tab (see below for details) that allows you to modify plot flags and trigger scripts when the conversation ends; this is helpful for preventing errors and saving time when crafting a conversation that is always supposed to have the same effect on the world when it's over but that has many different conversation end nodes scattered throughout it.&lt;br /&gt;
&lt;br /&gt;
The cinematics tab of the root node allows default cinematics information to be set, which is inherited by the rest of the nodes in the conversation unless overridden.&lt;br /&gt;
&lt;br /&gt;
Finally, the root node has a conversation synopsis text field where a summary of the content and purpose of the conversation can be placed for ease of reference.&lt;br /&gt;
&lt;br /&gt;
== Dialogue ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Conversation dialog.png]]&lt;br /&gt;
&lt;br /&gt;
This tab contains the string of text that is displayed to the player when this node in the tree is reached.&lt;br /&gt;
&lt;br /&gt;
At the lower left corner are some statistics for this line and for the conversation it's a part of.&lt;br /&gt;
&lt;br /&gt;
*Player Response Length Maximum: 60 characters &lt;br /&gt;
*NPC Response Length Maximum: 200 characters&lt;br /&gt;
&lt;br /&gt;
There is also a limit of six lines of player responses displayed for any particular line of NPC dialogue. If there are more than six responses available to be shown, only the first six will be visible.&lt;br /&gt;
&lt;br /&gt;
Also in the lower left corner is the string ID for this line of dialog, which is used when recording voice over audio. Don't forget to [[String_editor#Generated string IDs | check the dialogue and creature resources back in]] before exporting your talk tables, or else the conversation history in the player's journal won't be correct.&lt;br /&gt;
&lt;br /&gt;
=== Formatting tags ===&lt;br /&gt;
&lt;br /&gt;
==== Emphasis tags ====&lt;br /&gt;
&lt;br /&gt;
To indicate that a word in spoken text is emphasized, use &amp;amp;lt;emp&amp;amp;gt; tags. In subtitles, text inside the tags will be bolded.&lt;br /&gt;
&lt;br /&gt;
For example: &amp;quot;I don't &amp;amp;lt;emp&amp;amp;gt;think&amp;amp;lt;/emp&amp;amp;gt; so.&amp;quot; appears in-game as: &amp;quot;I don't '''think''' so.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Description tags ====&lt;br /&gt;
&lt;br /&gt;
Description &amp;amp;lt;desc&amp;amp;gt; tags are used in three ways: 1) To set apart a non-spoken sound (NPC lines), 2) To describe action that is not voiced (player lines), 2) To indicate that a persuade line is a lie or charm (player lines), 3) For text that describes an object (object lines). &lt;br /&gt;
&lt;br /&gt;
In subtitles, text inside &amp;amp;lt;desc&amp;amp;gt; tags will be italicized and put into parentheses.&lt;br /&gt;
&lt;br /&gt;
1) Unspoken sounds (such as a sigh, sob, or grunt of pain) - NPC lines only. &lt;br /&gt;
&lt;br /&gt;
Write out the sound, not a description of the sound. &lt;br /&gt;
* Incorrect: &amp;quot;No! Please don't kill me! &amp;amp;lt;desc&amp;amp;gt;gurgling sound as she is stabbed&amp;amp;lt;/desc&amp;amp;gt;&lt;br /&gt;
* Correct: &amp;quot;No! Please don't kill me! &amp;amp;lt;desc&amp;amp;gt;Aaargh!&amp;amp;lt;/desc&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;If only... &amp;amp;lt;desc&amp;amp;gt;sigh&amp;amp;lt;/desc&amp;amp;gt; Alas, it cannot be.&amp;quot; appears in-game as: &amp;quot;If only... ''(sigh)''' Alas, it cannot be.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2) Persuade lines that need to be marked as &amp;quot;lie&amp;quot; or &amp;quot;charm&amp;quot; - player lines only: When a line that has been flagged in the toolset as a &amp;quot;Persuade&amp;quot; line needs to me marked as a specific &amp;quot;lie&amp;quot; or &amp;quot;charm&amp;quot;, write Lie or Charm at the line's beginning. Then, use &amp;amp;lt;desc&amp;amp;gt; tags around that word so that it will be set off from the rest of the line.&lt;br /&gt;
For example: &amp;amp;lt;desc&amp;amp;gt;Lie&amp;amp;lt;/desc&amp;amp;gt; &amp;quot;Of course I didn't report you to the authorities.&amp;quot; appears in-game as: &amp;quot;''(Lie)'' Of course I didn't report you to the authorities.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3) Text that describes an object - Object lines only: When a line is created to describe an inanimate object, such as a bookcase or chest, descriptive lines for that object should be marked with &amp;amp;lt;desc&amp;amp;gt; tags. The writer creates a &amp;quot;character&amp;quot; in the toolset (&amp;quot;bhm700_bookcase&amp;quot;), and writes a line to describe that object. For example, &amp;amp;lt;desc&amp;amp;gt;This bookcase is full of dusty, moldering books.&amp;amp;lt;/desc&amp;amp;gt; or &amp;amp;lt;desc&amp;amp;gt;The phylactery is warm to the touch and filled with a small amount of viscous, red liquid. You see no way to open it.&amp;amp;lt;/desc&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Correct: &amp;amp;lt;desc&amp;amp;gt;This bookcase is full of dusty, moldering books.&amp;amp;lt;/desc&amp;amp;gt;&lt;br /&gt;
All such text should be written in third-person, present tense, with the player always referred to as &amp;quot;you&amp;quot;. &lt;br /&gt;
* Incorrect: &amp;amp;lt;desc&amp;amp;gt; The phylactery is warm to the touch and filled with a small amount of viscous, red liquid. I can't see any way to open it.&amp;amp;lt;/desc&amp;amp;gt; &lt;br /&gt;
* Correct: &amp;amp;lt;desc&amp;amp;gt;The phylactery is warm to the touch and filled with a small amount of viscous, red liquid. You see no way to open it.&amp;amp;lt;/desc&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The tech designer will need to create a placeable in the appropriate area. The character for that placeable should be set as &amp;quot;null&amp;quot;. (This indicates that no VO recording is needed for that line.) It should also be set to appear on the screen even if subtitles are turned off by default.&lt;br /&gt;
&lt;br /&gt;
==== Action Tags ====&lt;br /&gt;
&lt;br /&gt;
Action tags &amp;amp;lt;act&amp;amp;gt; describe player action. In subtitles, text inside &amp;amp;lt;act&amp;amp;gt; tags will be italicized and put into parentheses.&lt;br /&gt;
&lt;br /&gt;
For example: &amp;quot;If that's the way you want it. &amp;amp;lt;act&amp;amp;gt;Kill the soldier.&amp;amp;lt;/act&amp;amp;gt;&amp;quot; appears in-game as: &amp;quot;If that's the way you want it. ''(Kill the soldier.)''&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Incorrect: {Owner}: &amp;quot;Here. Take this. &amp;amp;lt;act&amp;amp;gt; Opens chest, removes sword.&amp;amp;lt;/act&amp;amp;gt; It was your father's.&amp;quot; &lt;br /&gt;
&lt;br /&gt;
=== Macros ===&lt;br /&gt;
&lt;br /&gt;
The &amp;amp;lt;FirstName/&amp;amp;gt; macro will be replaced with the first name entered by the player for his character. Since the player character's name can be anywhere up to 20 characters long, player lines using the &amp;amp;lt;FirstName/&amp;amp;gt; macro can only have 40 characters (not including the macro itself).&lt;br /&gt;
&lt;br /&gt;
Macros are used fairly rarely in Dragon Age since voiceovers accompany most lines and cannot be modified to match lines with variable text.&lt;br /&gt;
&lt;br /&gt;
=== Other settings ===&lt;br /&gt;
&lt;br /&gt;
Also on this tab are some additional flags and tags that can be set for this line.&lt;br /&gt;
*Skill/Icon - allows an icon to be placed next to this line indicating that a skill must be used when the line is selected by the player&lt;br /&gt;
*Speaker Tag and Listener Tag - defines which character is the speaker and which is the listener (can be set to default)&lt;br /&gt;
*Language - defines which language the line is spoken in.&lt;br /&gt;
*Fast Path - Any line with &amp;quot;Fast Path&amp;quot; set will be the first option presented to a player when they reach this conversation node. This can be useful if you want to provide an easy way to blow through the conversation tree without having to read it; if you mark the shortest path through the tree with this flag the player will only have to tap the &amp;quot;1&amp;quot; key to pass through it. You can also do this without the fast path flag by arranging your conversation nodes in the correct order, but restructuring an entire conversation tree for this purpose is a more complex task.&lt;br /&gt;
&lt;br /&gt;
== Plots and Scripting ==&lt;br /&gt;
&lt;br /&gt;
See [[conversation plots and scripting]] for details on how to use plots and scripts to make certain lines of dialog &amp;quot;conditional&amp;quot; (appearing or not appearing based on conditions in the game) and how to have certain lines cause scripted actions and change plot flags.&lt;br /&gt;
&lt;br /&gt;
This tab also includes an option to easily set a line so that it appears to a player only once (either once per conversation or once per game).&lt;br /&gt;
&lt;br /&gt;
== Cinematics and Animation ==&lt;br /&gt;
&lt;br /&gt;
See [[conversation cinematics and animation]] for details of how to control the performance of your virtual actors. Conversations without cinematic direction set for them will use a default over-the-shoulder camera style that's serviceable for most conversations, but which might become dull when used for all of them. Adding some animation and varying the camera angles can go a long way to spicing up a conversation, and for special events you can add much more than that - even integrating full-blown cutscenes into the middle of a conversation.&lt;br /&gt;
&lt;br /&gt;
== Cutscenes ==&lt;br /&gt;
&lt;br /&gt;
Even more control over how a conversation appears can be achieved by turning it into a cutscene.&lt;br /&gt;
&lt;br /&gt;
There are two ways of doing this.&lt;br /&gt;
&lt;br /&gt;
=== Cutscene-centred approach ===&lt;br /&gt;
&lt;br /&gt;
See [[Cutscene tutorial]] for a method of building one cutscene from many conversation lines (the entire conversation, perhaps).&lt;br /&gt;
&lt;br /&gt;
This may be useful if the conversation is essentially action-packed and linear.&lt;br /&gt;
&lt;br /&gt;
Because the cutscene is in control, the conversation logic is ignored.&lt;br /&gt;
&lt;br /&gt;
So this approach is less useful when there are player options, conditions and/or actions.&lt;br /&gt;
&lt;br /&gt;
Also, the conversation isn't logged.&lt;br /&gt;
&lt;br /&gt;
It is possible to run a plot script and/or regular conversation at the end of the cutscene (either via the End Script property or [[CS_LoadCutscene]]).&lt;br /&gt;
&lt;br /&gt;
=== Conversation-centred approach ===&lt;br /&gt;
&lt;br /&gt;
If conversation options, conditions, actions or logging are important, it's better to put the conversation in control.&lt;br /&gt;
&lt;br /&gt;
This may also be the easiest option if only one or two lines require the enhanced control afforded by a cutscene.&lt;br /&gt;
&lt;br /&gt;
Once a stage has been specified for the conversation, you can make one cutscene for each NPC line, using the &amp;quot;Convert Line to Cutscene&amp;quot; option on the Edit menu. &lt;br /&gt;
&lt;br /&gt;
By default, the cutscenes are collected in one folder per conversation, for convenience.&lt;br /&gt;
&lt;br /&gt;
In this approach, the conversation works normally, except that the cutscenes provide enhanced cinematics for the lines in question.&lt;br /&gt;
&lt;br /&gt;
== Fade In and Out ==&lt;br /&gt;
&lt;br /&gt;
A conversation can fade in or out by converting the line to a cutscene.&lt;br /&gt;
&lt;br /&gt;
It's not necessary to master the full complexity of the cutscene editor to do this.&lt;br /&gt;
&lt;br /&gt;
  Right-click Master. &lt;br /&gt;
  Add Track.&lt;br /&gt;
  Right-click the new track.&lt;br /&gt;
  Add effect Fade In or Out (default duration of fade is 60 frames i.e. 2 seconds).  &lt;br /&gt;
  Click anywhere that's not a track to view the cutscene properties in Object Inspector.&lt;br /&gt;
  The cutscene length is initially the dialogue duration (in frames). &lt;br /&gt;
  Change this to (dialogue duration + 30x + 60) where x is the time the screen will be completely black in seconds.&lt;br /&gt;
  Adjust start/end time of the new track (and the Speak Line track under OWNER, if fading in).&lt;br /&gt;
&lt;br /&gt;
For fade out, Speak Line happens first, then fade. The additional duration of the cutscene ensures the screen remains black for x seconds.&lt;br /&gt;
&lt;br /&gt;
For fade in, assuming the screen is already black, fade after 30x frames, then Speak Line after 30x + 60 frames.&lt;br /&gt;
&lt;br /&gt;
== Localization and Editing ==&lt;br /&gt;
&lt;br /&gt;
These two panels are used for keeping track of the status of the localization and editing process for this line. This is useful for large-scale collaborative projects, such as Dragon Age itself, but may not be of as much use for individual adventure designers.&lt;br /&gt;
&lt;br /&gt;
== Slide Show ==&lt;br /&gt;
&lt;br /&gt;
The Slide Show tab is used to produce a simple form of &amp;quot;cutscene&amp;quot; that consists of one or more pre-rendered still images. For example, the official DAO campaign ends with a slideshow that describes the aftermath.&lt;br /&gt;
&lt;br /&gt;
Images used in a slide show can be in [[TGA]], [[TPC]] or [[DDS]] format.&lt;br /&gt;
&lt;br /&gt;
Each image must be on its own NPC conversation line. The Dialogue text isn't used in game, but it must contain something (e.g. &amp;quot;Slideshow&amp;quot;), otherwise the slide won't appear. &lt;br /&gt;
&lt;br /&gt;
As usual, the NPC lines are connected by player lines (which don't need any Dialogue text).          &lt;br /&gt;
&lt;br /&gt;
See [[BeginSlideshow]] for the script function that triggers a slideshow.&lt;br /&gt;
&lt;br /&gt;
== Toolbars ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Conversation toolbar labeled.png]]&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Find links&amp;quot; generates a list of other places in the tree that have this line as their child. See the &amp;quot;looping conversations and re-using lines&amp;quot; section below.&lt;br /&gt;
*The highlighting toolbar is handy for rapidly finding and paging through conversation nodes with particular properties. There's forward and backward buttons for jumping from highlighted node to highlighted node, and a set of togglable highlight selection buttons that turn on and off highlighting based on node characteristics. &lt;br /&gt;
* &amp;quot;Once-per&amp;quot; lines include both once-per-conversation and once-per-game&lt;br /&gt;
* Highlighting lines with plot involvement will prompt you to select which particular plot to highlight.&lt;br /&gt;
&lt;br /&gt;
== Looping conversation and re-using lines in multiple places ==&lt;br /&gt;
&lt;br /&gt;
Although the basic structure is tree-shaped, the flow of the conversation can be structured to return back to previous nodes in the conversation. To cause a node in the tree to repeat:&lt;br /&gt;
&lt;br /&gt;
*select the node you want to return to,&lt;br /&gt;
*&amp;quot;Copy&amp;quot; it (control-C, or select copy from the right-click menu),&lt;br /&gt;
*select the node you want the repeated response to be a child of,&lt;br /&gt;
*select &amp;quot;Paste as link&amp;quot; from the right-click menu (keyboard shortcut: control-shift-V)&lt;br /&gt;
&lt;br /&gt;
The link node will appear in gray and cannot be edited. If you edit the original copy of the node all linked copies will reflect the change. You can only link nodes that have the same type (player/non-player), the paste-as-link option won't be available if the node currently saved to the clipboard can't be linked to a child of the currently selected node.&lt;br /&gt;
&lt;br /&gt;
To find the original copy of a linked node, right-click on the grey node and select &amp;quot;Jump to Target&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Using the &amp;quot;once per conversation&amp;quot; or &amp;quot;once per game&amp;quot; visibility setting for the children of a repeating node is useful for preventing the player from cycling multiple times through the exact same dialogue.&lt;br /&gt;
&lt;br /&gt;
== Voice-Over ==&lt;br /&gt;
&lt;br /&gt;
You can use both placeholder and real recorded voiceover in your conversation, depending on what your current status on the conversation is. After you have some sort of voiceover associated to your conversation, you may run &amp;quot;Tools-&amp;gt;Generate [[FaceFX]]&amp;quot; to add a facial expression to the NPCs performance.&lt;br /&gt;
&lt;br /&gt;
All information about [[Voice-Over]] (conventions, integration, etc.) is stored at a another page to keep a central organized structure.&lt;br /&gt;
&lt;br /&gt;
== Glossary of design terms ==&lt;br /&gt;
&lt;br /&gt;
* Branch: A dialogue option that adds flavor to a conversation, but doesn't change the direction of the plot or story. Branches always come back together at a choke point.&lt;br /&gt;
* Clarification Hub: This allows a player to return to an NPC and clarify plot elements, get directions, or find out information about the current area. Generally, an single NPC line asks the player what he wants; a list of questions is then available to the player. Once the player has received an answer, the same list reappears (minus the question just asked). The player can loop infinitely through this NPC dialogue. &lt;br /&gt;
* Path: The dialogue options players can select that change the direction of a plot or story. For example, when a player is given the option of accepting a quest, there are two different resulting paths (based on a &amp;quot;Yes&amp;quot; or &amp;quot;No&amp;quot; answer). Unlike branches, paths never come back together. Each path has a different ending condition. &lt;br /&gt;
* Question Hub: A list of questions presented to a player that allows him to ask multiple questions to clarify information he's just learned. After a response is given, the player can ask the remaining questions. It's possible to loop indefinitely through a question hub, but only by asking non-critical questions. Unlike a clarification hub, at least one question drives the conversation tree forward and eliminates all remaining questions. For example, an NPC gives plot critical information; once she relates the details, the player can ask four specific questions. Three of the questions are non-critical: they give flavor and/or enhance role-playing. These questions allow for infinite looping. However, the fourth question drives the conversation forward and eliminates all other questions. This important question should always be located beneath the &amp;quot;lesser&amp;quot; questions.&lt;br /&gt;
&lt;br /&gt;
== Associated Links ==&lt;br /&gt;
&lt;br /&gt;
*[[Conversation cinematics and animation]]&lt;br /&gt;
*[[Conversation plots and scripting]]&lt;br /&gt;
*[[Conversation tutorial]]&lt;br /&gt;
*[[Voice-Over]]&lt;br /&gt;
*[[Preparing a dialog for recording]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Conversations]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Builder_to_player&amp;diff=16079</id>
		<title>Builder to player</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Builder_to_player&amp;diff=16079"/>
				<updated>2011-04-18T17:49:32Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Step by Step */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox module}}&lt;br /&gt;
&amp;quot;Builder to player&amp;quot; packaging is a system for packaging up the playable binary files you've exported from your toolset into a form that is easily installed and played on another system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Builder to player&amp;quot; packs every resource that is needed to be installed on another computer into a single filetype called [[DAZIP]]. You however must select those needed resources from folders and files in a treelike view. The &amp;quot;builder to player&amp;quot; function allows only files to be included from your modules &amp;quot;core&amp;quot; and &amp;quot;module&amp;quot; override folders, and the &amp;quot;Core Game Resources&amp;quot; Folder. As so it is very important that your resources are organized correctly.&lt;br /&gt;
&lt;br /&gt;
It can be found under the &amp;quot;Tools -&amp;gt; Builder&amp;quot; menu.&lt;br /&gt;
&lt;br /&gt;
== Resources organized ==&lt;br /&gt;
&lt;br /&gt;
While the Toolset exports Designer Resources into their correct location, Art Resources and 2DA's which you created with external tools need to be arranged manually. &lt;br /&gt;
&lt;br /&gt;
Likely, in your first steps you have placed those into a random Override folder until it works. The Toolset can read every Override folder just fine, so this didnt cause harm until now. The &amp;quot;builder to player&amp;quot; function requires resources to be organized, so it can package them and get distributed. So that no file is missed in the package, which causes the Module to work for you ,but not for someone else. It can help if you place Resources correctly from the start up.&lt;br /&gt;
&lt;br /&gt;
The primary choice is always your custom Modules folders. Depending on whether your Resources shall be available only in your &amp;quot;module&amp;quot;, or to other modules &amp;quot;core&amp;quot;. &lt;br /&gt;
&amp;lt;pre&amp;gt;*My Documents*\BioWare\Dragon Age\AddIns\*Modulename*\module\override\toolsetexport\&lt;br /&gt;
*My Documents*\BioWare\Dragon Age\AddIns\*Modulename*\core\override\toolsetexport\&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The other folder that can be included is the &amp;quot;Core Game Resources&amp;quot; Folder. This Folder must be treated with care, as this place is reserved for Gamewide Core Resources..&lt;br /&gt;
&amp;lt;pre&amp;gt;*My Documents*\BioWare\Dragon Age\packages\core\override\toolsetexport\&amp;lt;/pre&amp;gt;&lt;br /&gt;
Resources in here is not advised, it allows Resources to be available to other modules even if you deactivate your custom Module. Additionally the Toolset has the habbit of exporting Core Game Resources here, which are mere duplicates unless you modified them. These duplicates need to be deleted, as potentially they still create problems in the singleplayer campaign. &amp;lt;small&amp;gt;''(See: [[Bug: export creates unnecessary core override|Bug Report]])''&amp;lt;/small&amp;gt;  If all your Resources are in your Modules Folder, this is an easy thing of selecting all and deleting.&lt;br /&gt;
&lt;br /&gt;
All Resources need to be present and fully exported (that is if you created them):&lt;br /&gt;
&lt;br /&gt;
*[[Designer Resources]]&lt;br /&gt;
*[[Art Resources]]&lt;br /&gt;
*[[2DA|2DA's]]&lt;br /&gt;
&lt;br /&gt;
== Step by Step ==&lt;br /&gt;
&lt;br /&gt;
Start the process by selecting from the menu:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;Tools -&amp;gt; Builder -&amp;gt; Builder to player package&amp;quot; &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will ask for a &amp;quot;Manifest&amp;quot;. The &amp;quot;Manifest&amp;quot; is a helper, which isnt available the first time. However can be created afterwards, which will save you resource selection, so that exporting the next time you can select this &amp;quot;Manifest&amp;quot; and wouldnt need to select all the resources again.&lt;br /&gt;
&amp;lt;pre&amp;gt;Click cancel, or select a previously saved Manifest.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The toolset will now list all the binary files you've exported, including 2DA's, art and designer resources, and give you the opportunity to select which ones to include in the package (you usually won't need to include core game resources &amp;quot;from \packages\core&amp;quot;, for example). It will then package them into 3 [[ERF]]s (one for each directory listed above), which will be bundled together into a [[DAZIP]] file along with a manifest file used by the program DAUpdater when installing the package on the end user's machine.&lt;br /&gt;
&lt;br /&gt;
If you followed a clean structure with your resources, you may only select the whole custom module folder and be ready. &lt;br /&gt;
&amp;lt;pre&amp;gt;Select a location to save the file in.&lt;br /&gt;
Click Save.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a Manifest if you wish, which will save your resources selection for the next time you do the process. &lt;br /&gt;
&lt;br /&gt;
Currently, there is a [[Bug:_toolset_export_generates_files_with_names_that_can%27t_be_packaged_in_builder_to_player | file name bug]] which affects external levels etc. Refer to that link for a workaround.&lt;br /&gt;
&lt;br /&gt;
{{languages}}&lt;br /&gt;
&lt;br /&gt;
[[category:database]]&lt;br /&gt;
[[category:modules]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_toolset_export_generates_files_with_names_that_can%27t_be_packaged_in_builder_to_player&amp;diff=16078</id>
		<title>Bug: toolset export generates files with names that can't be packaged in builder to player</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_toolset_export_generates_files_with_names_that_can%27t_be_packaged_in_builder_to_player&amp;diff=16078"/>
				<updated>2011-04-18T17:46:54Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Version found:''' 1.01 &amp;lt;!-- put the version number of your toolset here --&amp;gt;&lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
{{EV|212197|[[User:BryanDerksen|BryanDerksen]]}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&amp;lt;!-- Describe the bug here including as many details as possible. What situations trigger it and what effects it causes are the most important. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Certain operations in the toolset will cause files to be exported that can't be packaged into [[ERF]]s by the [[builder to player]] process due to filename restrictions (ERF doesn't like filenames with two dots). Examples include:&lt;br /&gt;
&lt;br /&gt;
*.gpu.rim files, generated when posting level layouts&lt;br /&gt;
*.mor.xml files, luckily they're not needed&lt;br /&gt;
&lt;br /&gt;
See [http://social.bioware.com/forum/1/topic/74/index/515072] for a forum thread where this bug is discussed.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
&amp;lt;!-- if you know of any ways to work around the bug describe them here. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The files that can't be packaged into ERFs can still be manually inserted into the [[DAZIP]] file using ordinary archive-manipulating programs, causing the installer to extract and place them in the correct locations when the DAZIP is installed.&lt;br /&gt;
&lt;br /&gt;
To keep it simple, since the problem typically occurs with external levels, exclude the entire core override toolsetexport folder from the Builder-to-Player, rename to .zip, drag the missing toolsetexport folder to the core data folder in the .zip manually, then rename to .dazip.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16072</id>
		<title>Builder to builder</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16072"/>
				<updated>2011-04-16T16:59:19Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Importing database resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox module}}&lt;br /&gt;
&amp;quot;Builder to builder&amp;quot; is a general term for the process of exchanging game resource information between builders, for example between several people who are collaborating on building a module. See [[builder to player]] for the process of packaging up finished works to distribute to players.&lt;br /&gt;
&lt;br /&gt;
There are three basic sorts of game resources that might need to be exchanged in this manner:&lt;br /&gt;
*Art resources&lt;br /&gt;
*[[2DA]]s&lt;br /&gt;
*Database resources&lt;br /&gt;
&lt;br /&gt;
Art resources are self-contained files stored in the computer's file system in the standard way, and so are straightforward to share between builders. 2DAs are generated from Excel files that are also straightforward to share, especially when the capabilities of M2DAs are taken advantage of (see the [[2DA]] page for more detail).&lt;br /&gt;
&lt;br /&gt;
Database resources are trickier. Almost every computer user is familiar with how to manipulate files in their filesystem but fewer are familiar with databases, and there are many interdependencies within Dragon Age's database resources that need to be taken into account when making any edit. To simplify this process the toolset has the ability to save and load selected database resources and their dependencies into XML files, which are then bundled up into a single archive file for convenience.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This is a different sort of export procedure than what's needed to make resources available for use in the game itself, either for testing by yourself or for distribution to players. For information on that see [[resource palette]].&lt;br /&gt;
&lt;br /&gt;
== Creating resource files for transfer ==&lt;br /&gt;
&lt;br /&gt;
To create a resource file archive, select the resources in the resource palette and then in the right-click menu select the &amp;quot;builder to builder create&amp;quot; command:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B create menu command.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
You'll be presented with a list of the resources to be exported:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B_create_panel.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Normally, you'll restrict the selection to your own module (unless you have a specific reason for exporting core resources).&lt;br /&gt;
&lt;br /&gt;
Once you're done reviewing your selection, click &amp;quot;Ok&amp;quot; to export. You'll be prompted for a filename to put the resources into.&lt;br /&gt;
&lt;br /&gt;
You can select multiple resources before doing builder to builder creation and they'll all be included in the B2B package.&lt;br /&gt;
&lt;br /&gt;
Also, you can open a builder to builder creation window with all of your available resources in it by going to the Tools menu and selecting Builder -&amp;gt; Builder to Builder Create.&lt;br /&gt;
&lt;br /&gt;
[[File:Builder to builder create via tools menu.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
As noted above, this only exports design resources from the database, so in addition to sharing the .dadbdata file created in this process, builders also need to exchange any simple files containing 2DAs and art resources.&lt;br /&gt;
&lt;br /&gt;
== Importing database resources ==&lt;br /&gt;
&lt;br /&gt;
See also [[Builder to builder#Copying a Module | Copying a Module]]. &lt;br /&gt;
&lt;br /&gt;
Importing resources is done via the &amp;quot;Builder to Builder Load&amp;quot; command under the &amp;quot;Tools&amp;quot; menu (there's also a B2B create command here, the same that can be reached via the palette right-click menu):&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B load menu command.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Again, note that this is a different set of commands than the main &amp;quot;export&amp;quot; commands.&lt;br /&gt;
&lt;br /&gt;
You'll be prompted to select a database resource file generated by a previous export. When you do, you'll be presented with an options pane listing all of the resources present in the file:&lt;br /&gt;
&lt;br /&gt;
[[File:B2B load panel 973.png|center|]]&lt;br /&gt;
&lt;br /&gt;
You can choose to import or not to import specific resources from this panel with the leftmost checkbox. Note that if you only import some of the files you may break dependencies. However, many of the dependencies in any significant export are likely to be core resources that you already have in your database and it's wise to avoid re-importing such resources unless you have a specific reason to.&lt;br /&gt;
&lt;br /&gt;
You have the option to assign new string ids, or retain the original string ids, which allows you to maintain integrity of reference to the talk table. There seems to be a [[Bug:_Builder_to_Builder_Load_may_not_reproduce_resource_detail_correctly | bug]] with &amp;quot;Use Theirs&amp;quot;. See [[String ID]] for a discussion of sharing issues.   &lt;br /&gt;
&lt;br /&gt;
ResRefID is the identifier that the resource had in the database it was exported from. ResRefIDs must be unique within any given database, so these numbers will be reassigned automatically during the import process.&lt;br /&gt;
&lt;br /&gt;
=== Resource name conflicts ===&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Exists/New&amp;quot; column indicates whether a resource with the same name already exists within the destination database. This is a good way to identify common core resources that were included as dependencies on export but that you don't want to re-import.&lt;br /&gt;
&lt;br /&gt;
In the event that you import a resource with the same name as an existing resource within your database, the default behavior is for the old resource within your database to be overwritten by the new resource coming in from the import. The last column, &amp;quot;create new&amp;quot;, allows this behavior to be overridden. If you enable &amp;quot;create new&amp;quot; for such a resource, the imported resource will be renamed with &amp;quot;_1&amp;quot; (or a higher number as needed) and the old resource will be untouched. Any other new imported resources in the file that depend on the renamed resource will have their dependencies updated to refer to the new copy of the resource.&lt;br /&gt;
&lt;br /&gt;
Note that if use &amp;quot;create new&amp;quot; when importing a resource's dependencies and then you later re-import the same resource the importer won't know that its dependencies have been renamed in this manner. It's best to avoid this situation as hard-to-debug problems can potentially result.&lt;br /&gt;
&lt;br /&gt;
Resources with the same name that already exist in the destination database and that are checked out by other users aren't editable, so the &amp;quot;checked out&amp;quot; column will warn you of any resources that the import process will be unable to update. This is unlikely to be a concern when only a single user (yourself) has access to your database but may become significant in a more sophisticated multi-user collaborative environment.&lt;br /&gt;
&lt;br /&gt;
== Copying a Module ==&lt;br /&gt;
&lt;br /&gt;
You might want to copy a module to a new machine, a new data base, or another builder's data base.&lt;br /&gt;
&lt;br /&gt;
Builder-to-Builder Create is a good way to backup your resources for transfer or recovery.&lt;br /&gt;
&lt;br /&gt;
When you want to make a copy, create a new module in the target data base, entering the resource name and Name property manually.&lt;br /&gt;
&lt;br /&gt;
If you have VO, you'll want to ensure string ids don't change during load (otherwise you'll have to rename all the VO files).&lt;br /&gt;
&lt;br /&gt;
If you know what string range was defined for the original module, change the new module to the same range.&lt;br /&gt;
&lt;br /&gt;
If you've lost the original module and have no independent record of the string range, you need to ensure that all the strings in the .dadbdata file are in range. Temporarily, you can set the start of the range to 1, and the end of the range to a very high value.&lt;br /&gt;
&lt;br /&gt;
Now do the Builder-to-Builder Load, with the Use Theirs option for string ids.&lt;br /&gt;
&lt;br /&gt;
If you have a temporary string id range, examine the new module in the String Editor to discover the lowest and highest string id values. Set the range start to the lowest, range next to one higher than the highest, and range end as high as you like.&lt;br /&gt;
&lt;br /&gt;
Finally, change the other module properties, such as the start area / waypoint and the module script. That has to happen last, because you select from the resources you just loaded.&lt;br /&gt;
&lt;br /&gt;
== Sharing a live database ==&lt;br /&gt;
&lt;br /&gt;
If passing bundles of files around between builders proves to be a cumbersome means of collaborating, a more advanced alternative exists: sharing a single database repository.&lt;br /&gt;
&lt;br /&gt;
With a default installation of the toolset on a user's computer, a database is installed on that local computer for that toolset's use. Using the toolset's configuration tool, however, it is possible to tell the toolset to use some other database instead - possibly on another machine entirely, provided it's accessible over a network. This is the collaboration mechanism that was used internally at BioWare during the development of the Dragon Age single-player campaign, along with a more traditional file repository for the art resources and 2DAs, and is the principal reason why the toolset supports the concept of &amp;quot;checking out&amp;quot; database resources for editing.&lt;br /&gt;
&lt;br /&gt;
General considerations you'll need to take into account:&lt;br /&gt;
*Firewall and router issues - The computers of all the various collaborators will need to be able to contact the central database. This may require port forwarding and other potentially tricky configuration settings.&lt;br /&gt;
*Availability - If all work is being done on a single database, nobody will be able to do anything when that database is unavailable. It may be a good idea to set up a machine dedicated solely to running the database.&lt;br /&gt;
*Security - You'll be exposing your database to potential intrusion attempts from the outside world, so make sure you understand the risks and the steps that can be taken to ameliorate them.&lt;br /&gt;
&lt;br /&gt;
Though this is fully possible in principle with the existing toolset, the specifics for how to accomplish this outside the BioWare intranet haven't been tested yet so we don't have documentation for it yet.&lt;br /&gt;
&lt;br /&gt;
{{languages}}&lt;br /&gt;
[[Category:Database]]&lt;br /&gt;
[[category:modules]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16071</id>
		<title>Builder to builder</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16071"/>
				<updated>2011-04-16T16:58:52Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Importing database resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox module}}&lt;br /&gt;
&amp;quot;Builder to builder&amp;quot; is a general term for the process of exchanging game resource information between builders, for example between several people who are collaborating on building a module. See [[builder to player]] for the process of packaging up finished works to distribute to players.&lt;br /&gt;
&lt;br /&gt;
There are three basic sorts of game resources that might need to be exchanged in this manner:&lt;br /&gt;
*Art resources&lt;br /&gt;
*[[2DA]]s&lt;br /&gt;
*Database resources&lt;br /&gt;
&lt;br /&gt;
Art resources are self-contained files stored in the computer's file system in the standard way, and so are straightforward to share between builders. 2DAs are generated from Excel files that are also straightforward to share, especially when the capabilities of M2DAs are taken advantage of (see the [[2DA]] page for more detail).&lt;br /&gt;
&lt;br /&gt;
Database resources are trickier. Almost every computer user is familiar with how to manipulate files in their filesystem but fewer are familiar with databases, and there are many interdependencies within Dragon Age's database resources that need to be taken into account when making any edit. To simplify this process the toolset has the ability to save and load selected database resources and their dependencies into XML files, which are then bundled up into a single archive file for convenience.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This is a different sort of export procedure than what's needed to make resources available for use in the game itself, either for testing by yourself or for distribution to players. For information on that see [[resource palette]].&lt;br /&gt;
&lt;br /&gt;
== Creating resource files for transfer ==&lt;br /&gt;
&lt;br /&gt;
To create a resource file archive, select the resources in the resource palette and then in the right-click menu select the &amp;quot;builder to builder create&amp;quot; command:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B create menu command.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
You'll be presented with a list of the resources to be exported:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B_create_panel.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Normally, you'll restrict the selection to your own module (unless you have a specific reason for exporting core resources).&lt;br /&gt;
&lt;br /&gt;
Once you're done reviewing your selection, click &amp;quot;Ok&amp;quot; to export. You'll be prompted for a filename to put the resources into.&lt;br /&gt;
&lt;br /&gt;
You can select multiple resources before doing builder to builder creation and they'll all be included in the B2B package.&lt;br /&gt;
&lt;br /&gt;
Also, you can open a builder to builder creation window with all of your available resources in it by going to the Tools menu and selecting Builder -&amp;gt; Builder to Builder Create.&lt;br /&gt;
&lt;br /&gt;
[[File:Builder to builder create via tools menu.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
As noted above, this only exports design resources from the database, so in addition to sharing the .dadbdata file created in this process, builders also need to exchange any simple files containing 2DAs and art resources.&lt;br /&gt;
&lt;br /&gt;
== Importing database resources ==&lt;br /&gt;
&lt;br /&gt;
See also [[Builder to builder#Copying a Module]]. &lt;br /&gt;
&lt;br /&gt;
Importing resources is done via the &amp;quot;Builder to Builder Load&amp;quot; command under the &amp;quot;Tools&amp;quot; menu (there's also a B2B create command here, the same that can be reached via the palette right-click menu):&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B load menu command.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Again, note that this is a different set of commands than the main &amp;quot;export&amp;quot; commands.&lt;br /&gt;
&lt;br /&gt;
You'll be prompted to select a database resource file generated by a previous export. When you do, you'll be presented with an options pane listing all of the resources present in the file:&lt;br /&gt;
&lt;br /&gt;
[[File:B2B load panel 973.png|center|]]&lt;br /&gt;
&lt;br /&gt;
You can choose to import or not to import specific resources from this panel with the leftmost checkbox. Note that if you only import some of the files you may break dependencies. However, many of the dependencies in any significant export are likely to be core resources that you already have in your database and it's wise to avoid re-importing such resources unless you have a specific reason to.&lt;br /&gt;
&lt;br /&gt;
You have the option to assign new string ids, or retain the original string ids, which allows you to maintain integrity of reference to the talk table. There seems to be a [[Bug:_Builder_to_Builder_Load_may_not_reproduce_resource_detail_correctly | bug]] with &amp;quot;Use Theirs&amp;quot;. See [[String ID]] for a discussion of sharing issues.   &lt;br /&gt;
&lt;br /&gt;
ResRefID is the identifier that the resource had in the database it was exported from. ResRefIDs must be unique within any given database, so these numbers will be reassigned automatically during the import process.&lt;br /&gt;
&lt;br /&gt;
=== Resource name conflicts ===&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Exists/New&amp;quot; column indicates whether a resource with the same name already exists within the destination database. This is a good way to identify common core resources that were included as dependencies on export but that you don't want to re-import.&lt;br /&gt;
&lt;br /&gt;
In the event that you import a resource with the same name as an existing resource within your database, the default behavior is for the old resource within your database to be overwritten by the new resource coming in from the import. The last column, &amp;quot;create new&amp;quot;, allows this behavior to be overridden. If you enable &amp;quot;create new&amp;quot; for such a resource, the imported resource will be renamed with &amp;quot;_1&amp;quot; (or a higher number as needed) and the old resource will be untouched. Any other new imported resources in the file that depend on the renamed resource will have their dependencies updated to refer to the new copy of the resource.&lt;br /&gt;
&lt;br /&gt;
Note that if use &amp;quot;create new&amp;quot; when importing a resource's dependencies and then you later re-import the same resource the importer won't know that its dependencies have been renamed in this manner. It's best to avoid this situation as hard-to-debug problems can potentially result.&lt;br /&gt;
&lt;br /&gt;
Resources with the same name that already exist in the destination database and that are checked out by other users aren't editable, so the &amp;quot;checked out&amp;quot; column will warn you of any resources that the import process will be unable to update. This is unlikely to be a concern when only a single user (yourself) has access to your database but may become significant in a more sophisticated multi-user collaborative environment.&lt;br /&gt;
&lt;br /&gt;
== Copying a Module ==&lt;br /&gt;
&lt;br /&gt;
You might want to copy a module to a new machine, a new data base, or another builder's data base.&lt;br /&gt;
&lt;br /&gt;
Builder-to-Builder Create is a good way to backup your resources for transfer or recovery.&lt;br /&gt;
&lt;br /&gt;
When you want to make a copy, create a new module in the target data base, entering the resource name and Name property manually.&lt;br /&gt;
&lt;br /&gt;
If you have VO, you'll want to ensure string ids don't change during load (otherwise you'll have to rename all the VO files).&lt;br /&gt;
&lt;br /&gt;
If you know what string range was defined for the original module, change the new module to the same range.&lt;br /&gt;
&lt;br /&gt;
If you've lost the original module and have no independent record of the string range, you need to ensure that all the strings in the .dadbdata file are in range. Temporarily, you can set the start of the range to 1, and the end of the range to a very high value.&lt;br /&gt;
&lt;br /&gt;
Now do the Builder-to-Builder Load, with the Use Theirs option for string ids.&lt;br /&gt;
&lt;br /&gt;
If you have a temporary string id range, examine the new module in the String Editor to discover the lowest and highest string id values. Set the range start to the lowest, range next to one higher than the highest, and range end as high as you like.&lt;br /&gt;
&lt;br /&gt;
Finally, change the other module properties, such as the start area / waypoint and the module script. That has to happen last, because you select from the resources you just loaded.&lt;br /&gt;
&lt;br /&gt;
== Sharing a live database ==&lt;br /&gt;
&lt;br /&gt;
If passing bundles of files around between builders proves to be a cumbersome means of collaborating, a more advanced alternative exists: sharing a single database repository.&lt;br /&gt;
&lt;br /&gt;
With a default installation of the toolset on a user's computer, a database is installed on that local computer for that toolset's use. Using the toolset's configuration tool, however, it is possible to tell the toolset to use some other database instead - possibly on another machine entirely, provided it's accessible over a network. This is the collaboration mechanism that was used internally at BioWare during the development of the Dragon Age single-player campaign, along with a more traditional file repository for the art resources and 2DAs, and is the principal reason why the toolset supports the concept of &amp;quot;checking out&amp;quot; database resources for editing.&lt;br /&gt;
&lt;br /&gt;
General considerations you'll need to take into account:&lt;br /&gt;
*Firewall and router issues - The computers of all the various collaborators will need to be able to contact the central database. This may require port forwarding and other potentially tricky configuration settings.&lt;br /&gt;
*Availability - If all work is being done on a single database, nobody will be able to do anything when that database is unavailable. It may be a good idea to set up a machine dedicated solely to running the database.&lt;br /&gt;
*Security - You'll be exposing your database to potential intrusion attempts from the outside world, so make sure you understand the risks and the steps that can be taken to ameliorate them.&lt;br /&gt;
&lt;br /&gt;
Though this is fully possible in principle with the existing toolset, the specifics for how to accomplish this outside the BioWare intranet haven't been tested yet so we don't have documentation for it yet.&lt;br /&gt;
&lt;br /&gt;
{{languages}}&lt;br /&gt;
[[Category:Database]]&lt;br /&gt;
[[category:modules]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16070</id>
		<title>Builder to builder</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16070"/>
				<updated>2011-04-16T16:56:32Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Importing database resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox module}}&lt;br /&gt;
&amp;quot;Builder to builder&amp;quot; is a general term for the process of exchanging game resource information between builders, for example between several people who are collaborating on building a module. See [[builder to player]] for the process of packaging up finished works to distribute to players.&lt;br /&gt;
&lt;br /&gt;
There are three basic sorts of game resources that might need to be exchanged in this manner:&lt;br /&gt;
*Art resources&lt;br /&gt;
*[[2DA]]s&lt;br /&gt;
*Database resources&lt;br /&gt;
&lt;br /&gt;
Art resources are self-contained files stored in the computer's file system in the standard way, and so are straightforward to share between builders. 2DAs are generated from Excel files that are also straightforward to share, especially when the capabilities of M2DAs are taken advantage of (see the [[2DA]] page for more detail).&lt;br /&gt;
&lt;br /&gt;
Database resources are trickier. Almost every computer user is familiar with how to manipulate files in their filesystem but fewer are familiar with databases, and there are many interdependencies within Dragon Age's database resources that need to be taken into account when making any edit. To simplify this process the toolset has the ability to save and load selected database resources and their dependencies into XML files, which are then bundled up into a single archive file for convenience.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This is a different sort of export procedure than what's needed to make resources available for use in the game itself, either for testing by yourself or for distribution to players. For information on that see [[resource palette]].&lt;br /&gt;
&lt;br /&gt;
== Creating resource files for transfer ==&lt;br /&gt;
&lt;br /&gt;
To create a resource file archive, select the resources in the resource palette and then in the right-click menu select the &amp;quot;builder to builder create&amp;quot; command:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B create menu command.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
You'll be presented with a list of the resources to be exported:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B_create_panel.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Normally, you'll restrict the selection to your own module (unless you have a specific reason for exporting core resources).&lt;br /&gt;
&lt;br /&gt;
Once you're done reviewing your selection, click &amp;quot;Ok&amp;quot; to export. You'll be prompted for a filename to put the resources into.&lt;br /&gt;
&lt;br /&gt;
You can select multiple resources before doing builder to builder creation and they'll all be included in the B2B package.&lt;br /&gt;
&lt;br /&gt;
Also, you can open a builder to builder creation window with all of your available resources in it by going to the Tools menu and selecting Builder -&amp;gt; Builder to Builder Create.&lt;br /&gt;
&lt;br /&gt;
[[File:Builder to builder create via tools menu.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
As noted above, this only exports design resources from the database, so in addition to sharing the .dadbdata file created in this process, builders also need to exchange any simple files containing 2DAs and art resources.&lt;br /&gt;
&lt;br /&gt;
== Importing database resources ==&lt;br /&gt;
&lt;br /&gt;
See also [[Copying a Module]]. &lt;br /&gt;
&lt;br /&gt;
Importing resources is done via the &amp;quot;Builder to Builder Load&amp;quot; command under the &amp;quot;Tools&amp;quot; menu (there's also a B2B create command here, the same that can be reached via the palette right-click menu):&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B load menu command.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Again, note that this is a different set of commands than the main &amp;quot;export&amp;quot; commands.&lt;br /&gt;
&lt;br /&gt;
You'll be prompted to select a database resource file generated by a previous export. When you do, you'll be presented with an options pane listing all of the resources present in the file:&lt;br /&gt;
&lt;br /&gt;
[[File:B2B load panel 973.png|center|]]&lt;br /&gt;
&lt;br /&gt;
You can choose to import or not to import specific resources from this panel with the leftmost checkbox. Note that if you only import some of the files you may break dependencies. However, many of the dependencies in any significant export are likely to be core resources that you already have in your database and it's wise to avoid re-importing such resources unless you have a specific reason to.&lt;br /&gt;
&lt;br /&gt;
You have the option to assign new string ids, or retain the original string ids, which allows you to maintain integrity of reference to the talk table. There seems to be a [[Bug:_Builder_to_Builder_Load_may_not_reproduce_resource_detail_correctly | bug]] with &amp;quot;Use Theirs&amp;quot;. See [[String ID]] for a discussion of sharing issues.   &lt;br /&gt;
&lt;br /&gt;
ResRefID is the identifier that the resource had in the database it was exported from. ResRefIDs must be unique within any given database, so these numbers will be reassigned automatically during the import process.&lt;br /&gt;
&lt;br /&gt;
=== Resource name conflicts ===&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Exists/New&amp;quot; column indicates whether a resource with the same name already exists within the destination database. This is a good way to identify common core resources that were included as dependencies on export but that you don't want to re-import.&lt;br /&gt;
&lt;br /&gt;
In the event that you import a resource with the same name as an existing resource within your database, the default behavior is for the old resource within your database to be overwritten by the new resource coming in from the import. The last column, &amp;quot;create new&amp;quot;, allows this behavior to be overridden. If you enable &amp;quot;create new&amp;quot; for such a resource, the imported resource will be renamed with &amp;quot;_1&amp;quot; (or a higher number as needed) and the old resource will be untouched. Any other new imported resources in the file that depend on the renamed resource will have their dependencies updated to refer to the new copy of the resource.&lt;br /&gt;
&lt;br /&gt;
Note that if use &amp;quot;create new&amp;quot; when importing a resource's dependencies and then you later re-import the same resource the importer won't know that its dependencies have been renamed in this manner. It's best to avoid this situation as hard-to-debug problems can potentially result.&lt;br /&gt;
&lt;br /&gt;
Resources with the same name that already exist in the destination database and that are checked out by other users aren't editable, so the &amp;quot;checked out&amp;quot; column will warn you of any resources that the import process will be unable to update. This is unlikely to be a concern when only a single user (yourself) has access to your database but may become significant in a more sophisticated multi-user collaborative environment.&lt;br /&gt;
&lt;br /&gt;
== Copying a Module ==&lt;br /&gt;
&lt;br /&gt;
You might want to copy a module to a new machine, a new data base, or another builder's data base.&lt;br /&gt;
&lt;br /&gt;
Builder-to-Builder Create is a good way to backup your resources for transfer or recovery.&lt;br /&gt;
&lt;br /&gt;
When you want to make a copy, create a new module in the target data base, entering the resource name and Name property manually.&lt;br /&gt;
&lt;br /&gt;
If you have VO, you'll want to ensure string ids don't change during load (otherwise you'll have to rename all the VO files).&lt;br /&gt;
&lt;br /&gt;
If you know what string range was defined for the original module, change the new module to the same range.&lt;br /&gt;
&lt;br /&gt;
If you've lost the original module and have no independent record of the string range, you need to ensure that all the strings in the .dadbdata file are in range. Temporarily, you can set the start of the range to 1, and the end of the range to a very high value.&lt;br /&gt;
&lt;br /&gt;
Now do the Builder-to-Builder Load, with the Use Theirs option for string ids.&lt;br /&gt;
&lt;br /&gt;
If you have a temporary string id range, examine the new module in the String Editor to discover the lowest and highest string id values. Set the range start to the lowest, range next to one higher than the highest, and range end as high as you like.&lt;br /&gt;
&lt;br /&gt;
Finally, change the other module properties, such as the start area / waypoint and the module script. That has to happen last, because you select from the resources you just loaded.&lt;br /&gt;
&lt;br /&gt;
== Sharing a live database ==&lt;br /&gt;
&lt;br /&gt;
If passing bundles of files around between builders proves to be a cumbersome means of collaborating, a more advanced alternative exists: sharing a single database repository.&lt;br /&gt;
&lt;br /&gt;
With a default installation of the toolset on a user's computer, a database is installed on that local computer for that toolset's use. Using the toolset's configuration tool, however, it is possible to tell the toolset to use some other database instead - possibly on another machine entirely, provided it's accessible over a network. This is the collaboration mechanism that was used internally at BioWare during the development of the Dragon Age single-player campaign, along with a more traditional file repository for the art resources and 2DAs, and is the principal reason why the toolset supports the concept of &amp;quot;checking out&amp;quot; database resources for editing.&lt;br /&gt;
&lt;br /&gt;
General considerations you'll need to take into account:&lt;br /&gt;
*Firewall and router issues - The computers of all the various collaborators will need to be able to contact the central database. This may require port forwarding and other potentially tricky configuration settings.&lt;br /&gt;
*Availability - If all work is being done on a single database, nobody will be able to do anything when that database is unavailable. It may be a good idea to set up a machine dedicated solely to running the database.&lt;br /&gt;
*Security - You'll be exposing your database to potential intrusion attempts from the outside world, so make sure you understand the risks and the steps that can be taken to ameliorate them.&lt;br /&gt;
&lt;br /&gt;
Though this is fully possible in principle with the existing toolset, the specifics for how to accomplish this outside the BioWare intranet haven't been tested yet so we don't have documentation for it yet.&lt;br /&gt;
&lt;br /&gt;
{{languages}}&lt;br /&gt;
[[Category:Database]]&lt;br /&gt;
[[category:modules]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16069</id>
		<title>Builder to builder</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16069"/>
				<updated>2011-04-16T16:56:04Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Importing database resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox module}}&lt;br /&gt;
&amp;quot;Builder to builder&amp;quot; is a general term for the process of exchanging game resource information between builders, for example between several people who are collaborating on building a module. See [[builder to player]] for the process of packaging up finished works to distribute to players.&lt;br /&gt;
&lt;br /&gt;
There are three basic sorts of game resources that might need to be exchanged in this manner:&lt;br /&gt;
*Art resources&lt;br /&gt;
*[[2DA]]s&lt;br /&gt;
*Database resources&lt;br /&gt;
&lt;br /&gt;
Art resources are self-contained files stored in the computer's file system in the standard way, and so are straightforward to share between builders. 2DAs are generated from Excel files that are also straightforward to share, especially when the capabilities of M2DAs are taken advantage of (see the [[2DA]] page for more detail).&lt;br /&gt;
&lt;br /&gt;
Database resources are trickier. Almost every computer user is familiar with how to manipulate files in their filesystem but fewer are familiar with databases, and there are many interdependencies within Dragon Age's database resources that need to be taken into account when making any edit. To simplify this process the toolset has the ability to save and load selected database resources and their dependencies into XML files, which are then bundled up into a single archive file for convenience.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This is a different sort of export procedure than what's needed to make resources available for use in the game itself, either for testing by yourself or for distribution to players. For information on that see [[resource palette]].&lt;br /&gt;
&lt;br /&gt;
== Creating resource files for transfer ==&lt;br /&gt;
&lt;br /&gt;
To create a resource file archive, select the resources in the resource palette and then in the right-click menu select the &amp;quot;builder to builder create&amp;quot; command:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B create menu command.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
You'll be presented with a list of the resources to be exported:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B_create_panel.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Normally, you'll restrict the selection to your own module (unless you have a specific reason for exporting core resources).&lt;br /&gt;
&lt;br /&gt;
Once you're done reviewing your selection, click &amp;quot;Ok&amp;quot; to export. You'll be prompted for a filename to put the resources into.&lt;br /&gt;
&lt;br /&gt;
You can select multiple resources before doing builder to builder creation and they'll all be included in the B2B package.&lt;br /&gt;
&lt;br /&gt;
Also, you can open a builder to builder creation window with all of your available resources in it by going to the Tools menu and selecting Builder -&amp;gt; Builder to Builder Create.&lt;br /&gt;
&lt;br /&gt;
[[File:Builder to builder create via tools menu.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
As noted above, this only exports design resources from the database, so in addition to sharing the .dadbdata file created in this process, builders also need to exchange any simple files containing 2DAs and art resources.&lt;br /&gt;
&lt;br /&gt;
== Importing database resources ==&lt;br /&gt;
&lt;br /&gt;
See also [[Importing a Module]]. &lt;br /&gt;
&lt;br /&gt;
Importing resources is done via the &amp;quot;Builder to Builder Load&amp;quot; command under the &amp;quot;Tools&amp;quot; menu (there's also a B2B create command here, the same that can be reached via the palette right-click menu):&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B load menu command.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Again, note that this is a different set of commands than the main &amp;quot;export&amp;quot; commands.&lt;br /&gt;
&lt;br /&gt;
You'll be prompted to select a database resource file generated by a previous export. When you do, you'll be presented with an options pane listing all of the resources present in the file:&lt;br /&gt;
&lt;br /&gt;
[[File:B2B load panel 973.png|center|]]&lt;br /&gt;
&lt;br /&gt;
You can choose to import or not to import specific resources from this panel with the leftmost checkbox. Note that if you only import some of the files you may break dependencies. However, many of the dependencies in any significant export are likely to be core resources that you already have in your database and it's wise to avoid re-importing such resources unless you have a specific reason to.&lt;br /&gt;
&lt;br /&gt;
You have the option to assign new string ids, or retain the original string ids, which allows you to maintain integrity of reference to the talk table. There seems to be a [[Bug:_Builder_to_Builder_Load_may_not_reproduce_resource_detail_correctly | bug]] with &amp;quot;Use Theirs&amp;quot;. See [[String ID]] for a discussion of sharing issues.   &lt;br /&gt;
&lt;br /&gt;
ResRefID is the identifier that the resource had in the database it was exported from. ResRefIDs must be unique within any given database, so these numbers will be reassigned automatically during the import process.&lt;br /&gt;
&lt;br /&gt;
=== Resource name conflicts ===&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Exists/New&amp;quot; column indicates whether a resource with the same name already exists within the destination database. This is a good way to identify common core resources that were included as dependencies on export but that you don't want to re-import.&lt;br /&gt;
&lt;br /&gt;
In the event that you import a resource with the same name as an existing resource within your database, the default behavior is for the old resource within your database to be overwritten by the new resource coming in from the import. The last column, &amp;quot;create new&amp;quot;, allows this behavior to be overridden. If you enable &amp;quot;create new&amp;quot; for such a resource, the imported resource will be renamed with &amp;quot;_1&amp;quot; (or a higher number as needed) and the old resource will be untouched. Any other new imported resources in the file that depend on the renamed resource will have their dependencies updated to refer to the new copy of the resource.&lt;br /&gt;
&lt;br /&gt;
Note that if use &amp;quot;create new&amp;quot; when importing a resource's dependencies and then you later re-import the same resource the importer won't know that its dependencies have been renamed in this manner. It's best to avoid this situation as hard-to-debug problems can potentially result.&lt;br /&gt;
&lt;br /&gt;
Resources with the same name that already exist in the destination database and that are checked out by other users aren't editable, so the &amp;quot;checked out&amp;quot; column will warn you of any resources that the import process will be unable to update. This is unlikely to be a concern when only a single user (yourself) has access to your database but may become significant in a more sophisticated multi-user collaborative environment.&lt;br /&gt;
&lt;br /&gt;
== Copying a Module ==&lt;br /&gt;
&lt;br /&gt;
You might want to copy a module to a new machine, a new data base, or another builder's data base.&lt;br /&gt;
&lt;br /&gt;
Builder-to-Builder Create is a good way to backup your resources for transfer or recovery.&lt;br /&gt;
&lt;br /&gt;
When you want to make a copy, create a new module in the target data base, entering the resource name and Name property manually.&lt;br /&gt;
&lt;br /&gt;
If you have VO, you'll want to ensure string ids don't change during load (otherwise you'll have to rename all the VO files).&lt;br /&gt;
&lt;br /&gt;
If you know what string range was defined for the original module, change the new module to the same range.&lt;br /&gt;
&lt;br /&gt;
If you've lost the original module and have no independent record of the string range, you need to ensure that all the strings in the .dadbdata file are in range. Temporarily, you can set the start of the range to 1, and the end of the range to a very high value.&lt;br /&gt;
&lt;br /&gt;
Now do the Builder-to-Builder Load, with the Use Theirs option for string ids.&lt;br /&gt;
&lt;br /&gt;
If you have a temporary string id range, examine the new module in the String Editor to discover the lowest and highest string id values. Set the range start to the lowest, range next to one higher than the highest, and range end as high as you like.&lt;br /&gt;
&lt;br /&gt;
Finally, change the other module properties, such as the start area / waypoint and the module script. That has to happen last, because you select from the resources you just loaded.&lt;br /&gt;
&lt;br /&gt;
== Sharing a live database ==&lt;br /&gt;
&lt;br /&gt;
If passing bundles of files around between builders proves to be a cumbersome means of collaborating, a more advanced alternative exists: sharing a single database repository.&lt;br /&gt;
&lt;br /&gt;
With a default installation of the toolset on a user's computer, a database is installed on that local computer for that toolset's use. Using the toolset's configuration tool, however, it is possible to tell the toolset to use some other database instead - possibly on another machine entirely, provided it's accessible over a network. This is the collaboration mechanism that was used internally at BioWare during the development of the Dragon Age single-player campaign, along with a more traditional file repository for the art resources and 2DAs, and is the principal reason why the toolset supports the concept of &amp;quot;checking out&amp;quot; database resources for editing.&lt;br /&gt;
&lt;br /&gt;
General considerations you'll need to take into account:&lt;br /&gt;
*Firewall and router issues - The computers of all the various collaborators will need to be able to contact the central database. This may require port forwarding and other potentially tricky configuration settings.&lt;br /&gt;
*Availability - If all work is being done on a single database, nobody will be able to do anything when that database is unavailable. It may be a good idea to set up a machine dedicated solely to running the database.&lt;br /&gt;
*Security - You'll be exposing your database to potential intrusion attempts from the outside world, so make sure you understand the risks and the steps that can be taken to ameliorate them.&lt;br /&gt;
&lt;br /&gt;
Though this is fully possible in principle with the existing toolset, the specifics for how to accomplish this outside the BioWare intranet haven't been tested yet so we don't have documentation for it yet.&lt;br /&gt;
&lt;br /&gt;
{{languages}}&lt;br /&gt;
[[Category:Database]]&lt;br /&gt;
[[category:modules]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16068</id>
		<title>Builder to builder</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Builder_to_builder&amp;diff=16068"/>
				<updated>2011-04-16T16:53:36Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Importing database resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox module}}&lt;br /&gt;
&amp;quot;Builder to builder&amp;quot; is a general term for the process of exchanging game resource information between builders, for example between several people who are collaborating on building a module. See [[builder to player]] for the process of packaging up finished works to distribute to players.&lt;br /&gt;
&lt;br /&gt;
There are three basic sorts of game resources that might need to be exchanged in this manner:&lt;br /&gt;
*Art resources&lt;br /&gt;
*[[2DA]]s&lt;br /&gt;
*Database resources&lt;br /&gt;
&lt;br /&gt;
Art resources are self-contained files stored in the computer's file system in the standard way, and so are straightforward to share between builders. 2DAs are generated from Excel files that are also straightforward to share, especially when the capabilities of M2DAs are taken advantage of (see the [[2DA]] page for more detail).&lt;br /&gt;
&lt;br /&gt;
Database resources are trickier. Almost every computer user is familiar with how to manipulate files in their filesystem but fewer are familiar with databases, and there are many interdependencies within Dragon Age's database resources that need to be taken into account when making any edit. To simplify this process the toolset has the ability to save and load selected database resources and their dependencies into XML files, which are then bundled up into a single archive file for convenience.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This is a different sort of export procedure than what's needed to make resources available for use in the game itself, either for testing by yourself or for distribution to players. For information on that see [[resource palette]].&lt;br /&gt;
&lt;br /&gt;
== Creating resource files for transfer ==&lt;br /&gt;
&lt;br /&gt;
To create a resource file archive, select the resources in the resource palette and then in the right-click menu select the &amp;quot;builder to builder create&amp;quot; command:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B create menu command.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
You'll be presented with a list of the resources to be exported:&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B_create_panel.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Normally, you'll restrict the selection to your own module (unless you have a specific reason for exporting core resources).&lt;br /&gt;
&lt;br /&gt;
Once you're done reviewing your selection, click &amp;quot;Ok&amp;quot; to export. You'll be prompted for a filename to put the resources into.&lt;br /&gt;
&lt;br /&gt;
You can select multiple resources before doing builder to builder creation and they'll all be included in the B2B package.&lt;br /&gt;
&lt;br /&gt;
Also, you can open a builder to builder creation window with all of your available resources in it by going to the Tools menu and selecting Builder -&amp;gt; Builder to Builder Create.&lt;br /&gt;
&lt;br /&gt;
[[File:Builder to builder create via tools menu.png|center|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
As noted above, this only exports design resources from the database, so in addition to sharing the .dadbdata file created in this process, builders also need to exchange any simple files containing 2DAs and art resources.&lt;br /&gt;
&lt;br /&gt;
== Importing database resources ==&lt;br /&gt;
&lt;br /&gt;
Importing resources is done via the &amp;quot;Builder to Builder Load&amp;quot; command under the &amp;quot;Tools&amp;quot; menu (there's also a B2B create command here, the same that can be reached via the palette right-click menu):&lt;br /&gt;
&lt;br /&gt;
[[Image:B2B load menu command.png|center|]]&lt;br /&gt;
&lt;br /&gt;
Again, note that this is a different set of commands than the main &amp;quot;export&amp;quot; commands.&lt;br /&gt;
&lt;br /&gt;
You'll be prompted to select a database resource file generated by a previous export. When you do, you'll be presented with an options pane listing all of the resources present in the file:&lt;br /&gt;
&lt;br /&gt;
[[File:B2B load panel 973.png|center|]]&lt;br /&gt;
&lt;br /&gt;
You can choose to import or not to import specific resources from this panel with the leftmost checkbox. Note that if you only import some of the files you may break dependencies. However, many of the dependencies in any significant export are likely to be core resources that you already have in your database and it's wise to avoid re-importing such resources unless you have a specific reason to.&lt;br /&gt;
&lt;br /&gt;
You have the option to assign new string ids, or retain the original string ids, which allows you to maintain integrity of reference to the talk table. There seems to be a [[Bug:_Builder_to_Builder_Load_may_not_reproduce_resource_detail_correctly | bug]] with &amp;quot;Use Theirs&amp;quot;. See [[String ID]] for a discussion of sharing issues.   &lt;br /&gt;
&lt;br /&gt;
ResRefID is the identifier that the resource had in the database it was exported from. ResRefIDs must be unique within any given database, so these numbers will be reassigned automatically during the import process.&lt;br /&gt;
&lt;br /&gt;
=== Resource name conflicts ===&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Exists/New&amp;quot; column indicates whether a resource with the same name already exists within the destination database. This is a good way to identify common core resources that were included as dependencies on export but that you don't want to re-import.&lt;br /&gt;
&lt;br /&gt;
In the event that you import a resource with the same name as an existing resource within your database, the default behavior is for the old resource within your database to be overwritten by the new resource coming in from the import. The last column, &amp;quot;create new&amp;quot;, allows this behavior to be overridden. If you enable &amp;quot;create new&amp;quot; for such a resource, the imported resource will be renamed with &amp;quot;_1&amp;quot; (or a higher number as needed) and the old resource will be untouched. Any other new imported resources in the file that depend on the renamed resource will have their dependencies updated to refer to the new copy of the resource.&lt;br /&gt;
&lt;br /&gt;
Note that if use &amp;quot;create new&amp;quot; when importing a resource's dependencies and then you later re-import the same resource the importer won't know that its dependencies have been renamed in this manner. It's best to avoid this situation as hard-to-debug problems can potentially result.&lt;br /&gt;
&lt;br /&gt;
Resources with the same name that already exist in the destination database and that are checked out by other users aren't editable, so the &amp;quot;checked out&amp;quot; column will warn you of any resources that the import process will be unable to update. This is unlikely to be a concern when only a single user (yourself) has access to your database but may become significant in a more sophisticated multi-user collaborative environment.&lt;br /&gt;
&lt;br /&gt;
== Copying a Module ==&lt;br /&gt;
&lt;br /&gt;
You might want to copy a module to a new machine, a new data base, or another builder's data base.&lt;br /&gt;
&lt;br /&gt;
Builder-to-Builder Create is a good way to backup your resources for transfer or recovery.&lt;br /&gt;
&lt;br /&gt;
When you want to make a copy, create a new module in the target data base, entering the resource name and Name property manually.&lt;br /&gt;
&lt;br /&gt;
If you have VO, you'll want to ensure string ids don't change during load (otherwise you'll have to rename all the VO files).&lt;br /&gt;
&lt;br /&gt;
If you know what string range was defined for the original module, change the new module to the same range.&lt;br /&gt;
&lt;br /&gt;
If you've lost the original module and have no independent record of the string range, you need to ensure that all the strings in the .dadbdata file are in range. Temporarily, you can set the start of the range to 1, and the end of the range to a very high value.&lt;br /&gt;
&lt;br /&gt;
Now do the Builder-to-Builder Load, with the Use Theirs option for string ids.&lt;br /&gt;
&lt;br /&gt;
If you have a temporary string id range, examine the new module in the String Editor to discover the lowest and highest string id values. Set the range start to the lowest, range next to one higher than the highest, and range end as high as you like.&lt;br /&gt;
&lt;br /&gt;
Finally, change the other module properties, such as the start area / waypoint and the module script. That has to happen last, because you select from the resources you just loaded.&lt;br /&gt;
&lt;br /&gt;
== Sharing a live database ==&lt;br /&gt;
&lt;br /&gt;
If passing bundles of files around between builders proves to be a cumbersome means of collaborating, a more advanced alternative exists: sharing a single database repository.&lt;br /&gt;
&lt;br /&gt;
With a default installation of the toolset on a user's computer, a database is installed on that local computer for that toolset's use. Using the toolset's configuration tool, however, it is possible to tell the toolset to use some other database instead - possibly on another machine entirely, provided it's accessible over a network. This is the collaboration mechanism that was used internally at BioWare during the development of the Dragon Age single-player campaign, along with a more traditional file repository for the art resources and 2DAs, and is the principal reason why the toolset supports the concept of &amp;quot;checking out&amp;quot; database resources for editing.&lt;br /&gt;
&lt;br /&gt;
General considerations you'll need to take into account:&lt;br /&gt;
*Firewall and router issues - The computers of all the various collaborators will need to be able to contact the central database. This may require port forwarding and other potentially tricky configuration settings.&lt;br /&gt;
*Availability - If all work is being done on a single database, nobody will be able to do anything when that database is unavailable. It may be a good idea to set up a machine dedicated solely to running the database.&lt;br /&gt;
*Security - You'll be exposing your database to potential intrusion attempts from the outside world, so make sure you understand the risks and the steps that can be taken to ameliorate them.&lt;br /&gt;
&lt;br /&gt;
Though this is fully possible in principle with the existing toolset, the specifics for how to accomplish this outside the BioWare intranet haven't been tested yet so we don't have documentation for it yet.&lt;br /&gt;
&lt;br /&gt;
{{languages}}&lt;br /&gt;
[[Category:Database]]&lt;br /&gt;
[[category:modules]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Creating_a_module&amp;diff=16067</id>
		<title>Creating a module</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Creating_a_module&amp;diff=16067"/>
				<updated>2011-04-16T16:33:04Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Creating a new Module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox module}}&lt;br /&gt;
To create and modify [[module]]s, select &amp;quot;Manage Modules&amp;quot; from the File menu. This will bring up a list of existing modules, with a &amp;quot;New&amp;quot; button for creating new modules and a &amp;quot;Properties&amp;quot; button for editing the properties of existing modules. You can only edit the properties of the module that's currently open.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating a new Module ==&lt;br /&gt;
&lt;br /&gt;
{| align=right&lt;br /&gt;
|-&lt;br /&gt;
| [[Image:Module menu command.png|frame|Select &amp;quot;Manage Modules&amp;quot;]]&lt;br /&gt;
| [[Image:Module manage module window.png|frame|Then click the &amp;quot;New&amp;quot; button to create a new module.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
#Open File/Manage Modules&lt;br /&gt;
#Click on &amp;quot;New&amp;quot; and the module properties window will open. &lt;br /&gt;
#Edit the &amp;quot;Name&amp;quot; field give the module a name (This is the name that will also be visible in Game as a Addin)&lt;br /&gt;
#Add a unique identifier string to the UID field. The File and Folder will appear in that name.&lt;br /&gt;
#Make an independent note of the StringID Begin value. This is vital information if you ever have to export the module to a new data base.&lt;br /&gt;
#Then click &amp;quot;OK&amp;quot;; the other properties can be changed later on once you have some content to set them to.&lt;br /&gt;
&lt;br /&gt;
=== Opening the Module ===&lt;br /&gt;
&lt;br /&gt;
#Select the module in the Manage Modules list &lt;br /&gt;
#Click the &amp;quot;Open&amp;quot; button. &lt;br /&gt;
&lt;br /&gt;
*The Open Module is displayed in the Title Bar. Only resources that are available to the open module will be visible.&lt;br /&gt;
&lt;br /&gt;
=== To create a standalone module: ===&lt;br /&gt;
&lt;br /&gt;
#Select the module in the Manage Modules list &lt;br /&gt;
#Click on the &amp;quot;Hierarchy&amp;quot; button&lt;br /&gt;
#Unmark any parent module (is by default)&lt;br /&gt;
&lt;br /&gt;
*The Extended Module property should be left as the default (None).&lt;br /&gt;
*You should use the default script &amp;quot;module_core&amp;quot; or your own custom script.&lt;br /&gt;
&lt;br /&gt;
=== Extending the game with addins (common) ===&lt;br /&gt;
&lt;br /&gt;
#Select the module in the Manage Modules list &lt;br /&gt;
#Click on the &amp;quot;Hierarchy&amp;quot; button&lt;br /&gt;
#Mark the parent module &amp;quot;Single Player&amp;quot;&lt;br /&gt;
#Hit OK&lt;br /&gt;
&lt;br /&gt;
*The Extended Module property should be set to &amp;quot;Single Player&amp;quot;.&lt;br /&gt;
*Note that as of toolset version 1.01 and game version 1.02b, you should NOT use &amp;quot;module_core&amp;quot; as the script (as found in module properties) for an add-in that extends an existing module, otherwise you will encounter issues that may include slow-downs during conversations and attribute allocation.  The exact cause of these issues is not yet known, but using a blank script with an empty main function will eliminate these issues.&lt;br /&gt;
*Resources of &amp;quot;Single Player&amp;quot; will now become available to this module.&lt;br /&gt;
&lt;br /&gt;
=== Advanced Properties ===&lt;br /&gt;
&lt;br /&gt;
#Select the module in the Manage Modules list &lt;br /&gt;
#Click on the &amp;quot;Properties&amp;quot; button&lt;br /&gt;
The Settings can be changed at any later time. To set up your Module prior Exporting see [[Manage modules]]&lt;br /&gt;
&lt;br /&gt;
*For a detailed explanation of the properties you will see here, See [[module|Module]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
The only module type that's supported by the toolset is &amp;quot;Addin&amp;quot;. You can use addins in two basic ways; either to extend an existing campaign (such as the main campaign) or as a stand-alone campaign in its own right. Addins can be enabled and disabled by the user in the &amp;quot;Downloadable content&amp;quot; menu from the game. You can also create addins that add to or modify core resources, which are available to all modules of the game.&lt;br /&gt;
&lt;br /&gt;
A module with no event script will start the player without going through character generation, which will leave the player with an almost unusable character to play with. See [[character generation]] for some simple character generation code you can use. &lt;br /&gt;
&lt;br /&gt;
'''NOTE:''' Currently there is no way to delete a module within the toolset once it's been created. See [[Deleting a module]]&lt;br /&gt;
&lt;br /&gt;
== Core resources: ==&lt;br /&gt;
&lt;br /&gt;
One way of using the same object template in more than one module is to create a core resource. &lt;br /&gt;
&lt;br /&gt;
When importing a character from one module to another, custom items in the player's inventory will be lost unless the resource template is available to both modules. A core resource is one way of doing this.&lt;br /&gt;
&lt;br /&gt;
Note that core resources are visible to every campaign, so, for compatibility purposes, it's better to use alternate methods where available. For example, an add-in inherits resources from the parent module, so there's no need to use core resources in that case. &lt;br /&gt;
&lt;br /&gt;
To create a core resource:&lt;br /&gt;
# Right click on properties for the resource in the Palette Window&lt;br /&gt;
# Change Module to: Core Game Resources&lt;br /&gt;
# Change Owner Module to: New Module Name&lt;br /&gt;
Be aware of dependencies between core and non-core resources; especially around scripts. If a core resource uses a non-core script, the script won't exist if you use the core resource in a different module.&lt;br /&gt;
&lt;br /&gt;
There will be a separate [[talk table]] created for the Addin in its directories. When the game loads it will combine all the talk tables across all the addins that it knows about.&lt;br /&gt;
&lt;br /&gt;
{{languages}}&lt;br /&gt;
[[category:modules]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Backgrounds_tutorial&amp;diff=16062</id>
		<title>Backgrounds tutorial</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Backgrounds_tutorial&amp;diff=16062"/>
				<updated>2011-04-06T07:04:17Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Creating the scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This tutorial shows you how to modify the character backgrounds that can be selected during character generation. This is likely only of use if you are creating your own module or campaign as there would be no point to changing the background in the single player campaign unless you were also going to make extensive additions to support the new backgrounds  (e.g a completely new origin story). So the example we will use for this tutorial is a new stand alone module in which we completely replace the existing backgrounds. Changing backgrounds is especially useful if your module is set in a different lore to the main Dragon Age game or if you simply want to reduce the scope of the number of different backgrounds.&lt;br /&gt;
&lt;br /&gt;
We will also demonstrate some important principals that can be followed when modifying other core rules such as available races or classes. Most importantly we will add the new backgrounds in a way that doesn’t require any editing of core resources. By leaving the core resources alone we make our changes compatible with future patches which might otherwise overwrite our work. Furthermore keeping the core resources in tact allows us to make different modifications to different modules within the same toolset.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the reader should have some experience with scripting or coding in order to carry out the operations involved. The more you are relying on just copy pasting these instructions the more likely you are to make mistakes that you won’t know how to fix.&lt;br /&gt;
&lt;br /&gt;
== The backgrounds demo module ==&lt;br /&gt;
Any basic module will do for the purposes of this tutorial. If you want to create a test module for this tutorial then just create a simple module with a single area and a starting location. Make sure that the only thing selected in the module’s hierarchy is ''Core game resources''. This will ensure that the module is a stand alone module rather than an add-in to the single player campaign or some other module. For the purposes of this tutorial we will assume the module is called ''Backgrounds demo'' and I will prefix my resources with ''bdm_'' to be sure that they are distinct from any that are already in existence.&lt;br /&gt;
&lt;br /&gt;
We are going to completely replace the existing backgrounds with 3 new ones of our own. You can use new backgrounds in your module however you see fit. You could create entire origin stories for each one like in the single player campaign (possibly a major undertaking depending on length) or you can just use them to influence dialogue and plot options in the main part of your game.&lt;br /&gt;
&lt;br /&gt;
For our demo we are creating a  module in which the player starts off in a small human village (we will not be creating the details of this module so this is just for the purpose of an example). There is a wizard in this village who plays a pivotal role in the story. We allow the player to start as the wizard’s apprentice (if they are a mage) or as his servant (if they are human or elven and not a mage) or as a wandering traveller who has come to visit the wizard (if they are not human and not a mage). So the three backgrounds will be:&lt;br /&gt;
&lt;br /&gt;
* Servant&lt;br /&gt;
* Apprentice&lt;br /&gt;
* Traveller&lt;br /&gt;
&lt;br /&gt;
== Creating the background strings ==&lt;br /&gt;
Before we start modifying the 2DA files we are going to create some strings. Open the string editor in the toolset and create the following strings in your ‘Backgrounds demo’ talk table:&lt;br /&gt;
&lt;br /&gt;
[[Image:Back_tut_talk_table.png]]&lt;br /&gt;
&lt;br /&gt;
Your string IDs might be different to these so be sure to reference the right string ID in the instructions that follow. Simply replace these string Ids with your own.&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT!''' ''There is currently a bug in the game that causes it to crash if a background description ID has a value greater than 109 912 680. To get around this you can go into your module’s properties and change the start and end IDs for strings to be less than that. After that the string editor will generate IDs in a range that won’t crash. You can always put those values back again after you create the background descriptions (that way you have less to alter once Bioware fix this). Hopefully Bioware will fix this bug soon as the official string range for non-Bioware / certified modules is over 610 000 000.''&lt;br /&gt;
&lt;br /&gt;
You may have noticed that we have given two different names and descriptions for the traveller background depending on the PC’s race. We will say more about that in the following section.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|String editor}}&lt;br /&gt;
&lt;br /&gt;
== Modifying the 2DAs ==&lt;br /&gt;
The next thing we need to do is to modify the worksheets in backgrounds.xls. Be sure to make a copy of the spreadsheet first so that you leave the original intact. See LINK for general information about editing 2DA files. The first worksheet is called ‘backgrounds’; modify it to look like the following:&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_backgrounds.png]]&lt;br /&gt;
&lt;br /&gt;
Note that since 2DAs combine together to form M2DAs, and we don’t want the existing backgrounds in our game, we have overwritten the last two slots as unused1 and unused2,  even though we won’t be using them. The name and desc  string refs on this tab will be overwritten by the race specific ones on the names tab so we can leave those blank (AFAIK these string refs are not used providing the ones on the names tab are provided - also the tooltip string ref seems not to be used anywhere – if you prefer you can set these to something just to be safe).&lt;br /&gt;
&lt;br /&gt;
The three race columns determine which backgrounds can be selected by which race and the 3 class columns determine which background can be selected by which class. So, as you can see from the picture our Servant background is accessible to elf or human warriors and rogues, the Apprentice background can be selected by elf or human mages and the Traveller background by elf or dwarf warriors and rogues.&lt;br /&gt;
&lt;br /&gt;
The last three tabs indicate a starting ability for each background by race. Note that by default these columns are not hooked up into the character generation script (instead they are hard coded in the script) and are not used, but we will correct that later on when we do the scripting. You have to be careful here because the columns relate to the race IDs, so 1=dwarf, 2=elf and 3=human, which is in a different order to the other race columns in this table. The number in the column is an ability ID as given in ABI_base.xls. For this demo we have just given the same skill for each race for a given background. Servants get combat tactics, Apprentices get persuade and Travellers get survival.&lt;br /&gt;
&lt;br /&gt;
The next tab table to modify is background_names.&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_bg_names.png]]&lt;br /&gt;
&lt;br /&gt;
Make sure that the IDs here match the IDs in your string table. Note that for Apprentices and Servants we use the same strings regardless of race, but for the Traveller background we use different strings. This is to illustrate how you can divide a single background up into multiple names and descriptions. Internally they are both stored as the same background ID but during character generation a different name, description and icon can be shown to the player. In the single player game this was done with the Noble background by splitting it into human and dwarf Noble variations.&lt;br /&gt;
&lt;br /&gt;
NOTE – you must be careful when splitting a single background into different parts for each race. You must make both the names and descriptions different! If you don’t make the descriptions different then the engine will not recognise them as different even if they have different names.&lt;br /&gt;
&lt;br /&gt;
Now modify the background_desc table as follows&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_bg_desc.png]]&lt;br /&gt;
&lt;br /&gt;
Again note the distinct descriptions for the Traveller background.&lt;br /&gt;
&lt;br /&gt;
Now for the background_icons table. For this demo we will just use some of the existing icons but you may want to create your own icons to add here.&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_bg_icons.png]]&lt;br /&gt;
&lt;br /&gt;
The background_defaults table must have an entry for each race, background and class combination that is allowed. The ID column must be calculated as follows:&lt;br /&gt;
&lt;br /&gt;
(1000 * raceID)  + (100 * classID) + backgroundID&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tute_bg_defaults.png]]&lt;br /&gt;
&lt;br /&gt;
The label column should give a description of the row (AFAIK this is not used anywhere).&lt;br /&gt;
For this simple demo we will have each background combination spawn in the same place (the module default start location) but if you wanted different origins to spawn in different places then you can use the next two columns to specify this (AFAIK you have to write your own scripts to accomplish this though).&lt;br /&gt;
&lt;br /&gt;
In the template column you can put the name of a creature resource that you want to use as a template for this race/background/class combination. In the picture you can see that we have just used some default templates that shipped with the toolset but you can easily create your own. Note that only the inventory is copied across to the PC so if you want to create your own templates you do not need to alter anything on the creature except for their inventory.&lt;br /&gt;
&lt;br /&gt;
The name columns take string Ids. If you want to add your own names then you’ll have to create new strings in the string editor.&lt;br /&gt;
&lt;br /&gt;
Finally we have the ability column. As with the skill columns in the backgrounds table these IDs correspond to entries in the ABI_base.xls file. It should be noted that race, class and background are all possible sources of starting abilities so before you decide what to put in this column you should familiarise yourself with what skills are already being added in different parts of character generation in order to ensure that you don’t duplicate an ability somewhere.&lt;br /&gt;
&lt;br /&gt;
The final table is the chargen_preload table. The two columns here should exactly match the entries from the ID and Template columns of the previous table.&lt;br /&gt;
&lt;br /&gt;
[[Image:back_tut_chargen_preload.png]]&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|2DA|2DA#Excel file formatting|Background.xls}}&lt;br /&gt;
&lt;br /&gt;
== Compiling and fixing the GDAs ==&lt;br /&gt;
Now compile backgrounds.xls and place the resulting GDAs into your ''AddIns\module_name\module\override'' directory.&lt;br /&gt;
Never place anything in your ''AddIns\module_name\core\override'' directory or it will affect other modules than the one you are editing.&lt;br /&gt;
&lt;br /&gt;
There used to be a [[Bug: ExcelProcessor doesn't handle row IDs above 8.3 million correctly|bug]] that prevented large string IDs from compiling correctly. This is now fixed. For the record, the old workaround was to edit the GDA files in the toolset to correct the string IDs manually, but you should now see that the string IDs are correct.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Compiling 2DAs|GDA}}&lt;br /&gt;
&lt;br /&gt;
== Creating the backgrounds plot ==&lt;br /&gt;
The background plot is used for keeping track of a PC’s background and can be used to affect conversation options.&lt;br /&gt;
 &lt;br /&gt;
The single player game uses a plot called gen00pt_backgrounds to keep track of the PC background. You can find it in the ''\_Global\Generic'' folder of the plots tab if you want to take a look. We will create a similar plot for our custom backgrounds. Create a new plot and call it ''bdm_000pt_backgrounds'' (My naming convention is to use 000 to indicate a resource that isn’t tied to any particular area – feel free to use your own convention but remember to update any references later in the tutorial). Add main plot flags as indicated in the picture below:&lt;br /&gt;
&lt;br /&gt;
[[Image:Back_tut_bg_plot.png]]&lt;br /&gt;
&lt;br /&gt;
You could also add some defined flags if you wanted. Defined flags can be used to return some combination of the main flags such as TRAVELLER or add some extra condition like FEMALE_APPRENTICE or ELVEN_APPRENTICE. Defined flags are beyond the scope of this tutorial however.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Designer Resources|Plot}}&lt;br /&gt;
&lt;br /&gt;
== Creating the scripts ==&lt;br /&gt;
We are not going to edit any of the original core game scripts, we will only be adding new scripts of our own. As we discuss how to do this you should examine the core scripts that are referred to, but under no circumstances should you make any changes to those files. By leaving the core scripts as they are we make our modification more compatible with any future patches that may be released. If you modified the core scripts and then a patch was released that overwrote those scripts you would lose your changes. Also keeping your modification contained within your own module allows you to make different modifications to different modules within the one toolset.&lt;br /&gt;
&lt;br /&gt;
Lets start off with a script to handle the character generation events that are normally handled by the module_core script. Create a new script called ''bdm_module_core''. It is up to you what directory structure to use for your scripts but it can be a good idea to keep all your scripts in a directory with your module name to make them distinct from the core scripts. Then if you are emulating the functionality of  a particular core script you can mirror the original directory structure underneath your main module folder. So in this case the module_core script is contained in the ''\_Core Scripts'' folder so we will put our bdm_module_core in ''\Backgrounds demo\_Core Scripts'' (the underscore ensures the core directories come first – looks like Bioware accidentally created one without it! I’m pretty sure Core and _Core are meant to be the same directory). Organising things this way will really help with keeping track of your scripts.&lt;br /&gt;
&lt;br /&gt;
The ''bdm_module_core'' script should contain the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;global_objects_h&amp;quot;&lt;br /&gt;
void main(){&lt;br /&gt;
    event ev = GetCurrentEvent();&lt;br /&gt;
    int nEvent = GetEventType(ev); //extract event type from current event&lt;br /&gt;
    int nEventHandled = FALSE; //keep track of whether the event has been handled&lt;br /&gt;
    switch(nEvent){&lt;br /&gt;
        case EVENT_TYPE_MODULE_START:{&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Initiate character generation.&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            PreloadCharGen(); //preloads resources for character generation&lt;br /&gt;
            StartCharGen(GetHero(),0,TRUE); //initiates character generation&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        default:&lt;br /&gt;
        {&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Handle character generation events sent by the engine.&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            if ((nEvent &amp;gt;= EVENT_TYPE_CHARGEN_START &amp;amp;&amp;amp; nEvent &amp;lt;= EVENT_TYPE_CHARGEN_END) &lt;br /&gt;
                || nEvent == EVENT_TYPE_PLAYERLEVELUP )&lt;br /&gt;
            {&lt;br /&gt;
                HandleEvent(ev, R&amp;quot;bdm_sys_chargen.ncs&amp;quot;);&lt;br /&gt;
                nEventHandled = TRUE;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    if (!nEventHandled) { //If this event wasn't handled by this script, let the core script try&lt;br /&gt;
        HandleEvent(ev, RESOURCE_SCRIPT_MODULE_CORE);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now go to ''file &amp;gt; manage modules'' and open the properties for your module and set the script property to point at this script.&lt;br /&gt;
&lt;br /&gt;
Our new script handles some of the events that are usually handled by the module_core script. Once it has handled the event it chooses whether or not to pass the event on to module_core. The first event that we handle is EVENT_TYPE_MODULE_START, which is where we initiate character generation. In this case we pass the event on to the core script to handle after we have done what we need to.&lt;br /&gt;
&lt;br /&gt;
NOTE : you may find that you don't need to change any other scripts. It's not clear what the scripts in the rest of this section are trying to do - see discussion.&lt;br /&gt;
&lt;br /&gt;
The second thing we handle is actually a group of events. If you look in the module_core script you will see that right down the bottom in the default event handler is some code that looks just like the code we have added in our default event, with a couple of little differences. Instead of passing the character generation events to the sys_chargen.ncs script we are going to pass it to our own script called ''bdm_sys_chargen.ncs'' which we will write shortly. If we catch one of those character generation events then we want to handle it ourselves and prevent the core script from handling it so we set nEventHandled = TRUE. Note that any other event that is caught by the default handler but isn’t a character generation event is going to go straight on through to the core script.&lt;br /&gt;
&lt;br /&gt;
Before we create the ''bdm_sys_chargen'' script we are going to need some new constants defined. Create a new script called ''bdm_2da_constants_h'' and put it in folder ''\Backgrounds demo\_Core Includes''. Now add the following to this script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// -----------------------------------------------------------------------------&lt;br /&gt;
// Backgrounds - rules/backgrounds.xls&lt;br /&gt;
// -----------------------------------------------------------------------------&lt;br /&gt;
const int BACKGROUND_SERVANT = 1;&lt;br /&gt;
const int BACKGROUND_APPRENTICE = 2;&lt;br /&gt;
const int BACKGROUND_TRAVELLER = 3;&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These constants provide a way for us to refer to the background IDs that we defined in the 2DA files without having to remember the numbers. Constants like this also make your code more readable.  If you need to add more new items to 2DAs when you are modding something else you can also add constants for them here. From now on we will be using these background constants instead of the original single player background constants that you can find in the ''2da_constants_h'' script. That means we’d better find all the places where those constants are used and update them with our own scripts.&lt;br /&gt;
&lt;br /&gt;
Create another new script and call it ''bdm_sys_chargen'' and put it in a folder called ''\Backgrounds demo\_Systems''. Put the following code in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;bdm_sys_chargen_h&amp;quot;&lt;br /&gt;
#include &amp;quot;log_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
const int CHARGEN_QUICKSTART_QUICK = 0;&lt;br /&gt;
const int CHARGEN_QUICKSTART_NORMAL = 1;&lt;br /&gt;
const int CHARGEN_QUICKSTART_ADVANCED = 2;&lt;br /&gt;
&lt;br /&gt;
void _RunChargen(int nRace, int nClass, object oChar, int nBackground)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    Chargen_InitializeCharacter(oChar);&lt;br /&gt;
    Chargen_SelectGender(oChar,GENDER_MALE);&lt;br /&gt;
    Chargen_SelectRace(oChar,nRace);&lt;br /&gt;
    Chargen_SelectCoreClass(oChar,nClass);&lt;br /&gt;
    Chargen_SelectBackground(oChar, nBackground,FALSE);&lt;br /&gt;
&lt;br /&gt;
    int nEquipIdx = Chargen_GetEquipIndex(nRace, nClass, nBackground);&lt;br /&gt;
    Chargen_InitInventory(oChar,0,nEquipIdx);&lt;br /&gt;
    Chargen_SpendAttributePoints(oChar,PROPERTY_ATTRIBUTE_STRENGTH, 3,FALSE);&lt;br /&gt;
    Chargen_SpendAttributePoints(oChar,PROPERTY_ATTRIBUTE_DEXTERITY, 2,FALSE);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main(){&lt;br /&gt;
    event   ev              =   GetCurrentEvent();&lt;br /&gt;
    int     nEventType      =   GetEventType(ev);&lt;br /&gt;
    object  oChar           =   GetEventObject(ev,0);&lt;br /&gt;
&lt;br /&gt;
    int nMode;&lt;br /&gt;
    int nInt0 = GetEventInteger(ev,0);&lt;br /&gt;
    int nInt1 = GetEventInteger(ev,1);&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    // Debug Data.&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    Log_Trace(LOG_CHANNEL_EVENTS_CHARGEN,&amp;quot;bdm_sys_chargen&amp;quot;,&amp;quot;Chargen Event:&amp;quot; + Log_GetEventNameById (nEventType) &lt;br /&gt;
               + &amp;quot; &amp;quot; + ToString(nInt0) + &amp;quot;,&amp;quot; + ToString(nInt1), oChar);&lt;br /&gt;
&lt;br /&gt;
    int nEventHandled = FALSE;&lt;br /&gt;
&lt;br /&gt;
    switch (nEventType)&lt;br /&gt;
    {&lt;br /&gt;
        // ----------------------------------------------------------------------&lt;br /&gt;
        // This fires when the player selects the icon corresponding to any of&lt;br /&gt;
        // the available backgrounds&lt;br /&gt;
        //&lt;br /&gt;
        // nInt0 - Constant BACKGROUND_* integer&lt;br /&gt;
        // ----------------------------------------------------------------------&lt;br /&gt;
        case EVENT_TYPE_CHARGEN_SELECT_BACKGROUND: {&lt;br /&gt;
            int nBackground = nInt0;&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Set the background on the player and reinitialize plot flags&lt;br /&gt;
            // for the background&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            Chargen_InitializeCharacter(oChar,TRUE);&lt;br /&gt;
            Chargen_SelectGender(oChar,GetCreatureGender(oChar));&lt;br /&gt;
            Chargen_SelectRace(oChar,GetCreatureRacialType(oChar));&lt;br /&gt;
            Chargen_SelectCoreClass(oChar,GetCreatureCoreClass(oChar));&lt;br /&gt;
&lt;br /&gt;
            bdm_Chargen_SelectBackground(oChar, nBackground, FALSE);&lt;br /&gt;
            bdm_Chargen_SetupPlotFlags(oChar);&lt;br /&gt;
&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            // Generate the index into the equipment template 2da and&lt;br /&gt;
            // then load the starting equipment based on the data returned.&lt;br /&gt;
            // -----------------------------------------------------------------&lt;br /&gt;
            int nClass = GetCreatureCoreClass(oChar);&lt;br /&gt;
            int nRace = GetCreatureRacialType(oChar);&lt;br /&gt;
            int nEquipIdx = Chargen_GetEquipIndex(nRace, nClass, nBackground);&lt;br /&gt;
           Chargen_InitInventory(oChar,0,nEquipIdx);&lt;br /&gt;
            nEventHandled = TRUE;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        case EVENT_TYPE_CHARGEN_END: {&lt;br /&gt;
            nMode = nInt0;&lt;br /&gt;
            int nQuickStart = nInt1;&lt;br /&gt;
            // 0 - quickstart&lt;br /&gt;
            // 1 - normal    \&lt;br /&gt;
            // 2 - advanced  / treat as the same&lt;br /&gt;
            Log_Trace(LOG_CHANNEL_CHARACTER,&amp;quot;bdm_sys_chargen&amp;quot;,&amp;quot;MODE: &amp;quot; + IntToString(nMode) &lt;br /&gt;
                       + &amp;quot;, Quick Start: &amp;quot; + IntToString(nQuickStart));&lt;br /&gt;
            if (nMode == CHARGEN_MODE_CREATE &amp;amp;&amp;amp; nQuickStart == CHARGEN_QUICKSTART_QUICK){&lt;br /&gt;
                Log_Trace(LOG_CHANNEL_CHARACTER,&amp;quot;bdm_sys_chargen&amp;quot;,&amp;quot;Setting default values for player character&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    int nRandClass = abs((GetLowResTimer()%3)+1);&lt;br /&gt;
&lt;br /&gt;
                    if(nRandClass == CLASS_ROGUE || nRandClass == CLASS_WARRIOR)&lt;br /&gt;
                    {&lt;br /&gt;
                        _RunChargen(RACE_HUMAN, nRandClass, oChar, BACKGROUND_SERVANT );&lt;br /&gt;
&lt;br /&gt;
                        WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT, TRUE);&lt;br /&gt;
                    }&lt;br /&gt;
                    else // mage&lt;br /&gt;
                    {&lt;br /&gt;
                        _RunChargen(RACE_HUMAN, nRandClass, oChar, BACKGROUND_APPRENTICE );&lt;br /&gt;
                        WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE, TRUE);&lt;br /&gt;
                    }&lt;br /&gt;
                    Chargen_SetNumTactics(oChar);&lt;br /&gt;
                    SetCanLevelUp(oChar,Chargen_HasPointsToSpend(oChar));&lt;br /&gt;
                    SendEventModuleChargenDone(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
                    nEventHandled = TRUE;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
    }    //end switch&lt;br /&gt;
&lt;br /&gt;
    if (!nEventHandled){&lt;br /&gt;
        HandleEvent(ev, R&amp;quot;sys_chargen.ncs&amp;quot;);&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;
There are two events in the original sys_chargen script that we need to replace because they deal with backgrounds. The first of these is EVENT_TYPE_CHARGEN_SELECT_BACKGROUND and the other is EVENT_TYPE_CHARGEN_END. For the second event we only need to change the case where the character is being created in quickstart mode, so we just handle that section of the code. The objective here is to change only as much as we need to and then pass any remaining events through to the original sys_chargen script. Take some time to compare the new script with Bioware’s ''sys_chargen'' script .&lt;br /&gt;
&lt;br /&gt;
You will notice that we include a script called ''bdm_sys_chargen_h'' and that we use some functions with a ''bdm_'' prefix. Those functions are contained in that include file which we’ll write now. Essentially these are modifications of a couple of functions from the ''sys_chargen_h'' include file. Create a new script and call it ''bdm_sys_chargen_h''. Put it in folder ''\Backgrounds demo\_Systems\Includes'' and add the following code:&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;bdm_2da_constants_h&amp;quot;&lt;br /&gt;
#include &amp;quot;wrappers_h&amp;quot;&lt;br /&gt;
#include &amp;quot;plt_bdm_000pt_backgrounds&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void bdm_Chargen_SelectBackground(object oChar, int nBackground, int bUnApply = FALSE)&lt;br /&gt;
{&lt;br /&gt;
     Log_Chargen(&amp;quot;bdm_Chargen_SelectBackground&amp;quot;,&amp;quot;-- &amp;quot; + (bUnApply?&amp;quot;Un&amp;quot;:&amp;quot;&amp;quot;) +&amp;quot;Selecting BG: &amp;quot; + ToString(nBackground),oChar);&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    // 1. Set the background variable&lt;br /&gt;
    //          - Create creature property (or check what we used so far&lt;br /&gt;
    //          - We don't set backgrounds on non player generated chars.&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    if (bUnApply)&lt;br /&gt;
    {&lt;br /&gt;
        SetCreatureProperty(oChar, PROPERTY_SIMPLE_BACKGROUND, 0.0, PROPERTY_VALUE_BASE);&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
       SetCreatureProperty(oChar, PROPERTY_SIMPLE_BACKGROUND, IntToFloat(nBackground), PROPERTY_VALUE_BASE);&lt;br /&gt;
    }&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    // 2. Give one skill&lt;br /&gt;
    //    - retrieve the skill that is granted by the background from backgrounds.xls&lt;br /&gt;
    //    - give it to the player.&lt;br /&gt;
    // -------------------------------------------------------------------------&lt;br /&gt;
    int nAbility = ChargenGetBackgroundSkill(GetCreatureRacialType(oChar), nBackground);&lt;br /&gt;
    if (nAbility)&lt;br /&gt;
    {&lt;br /&gt;
        _AddAbility (oChar, nAbility, bUnApply);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bdm_Chargen_SetupPlotFlags(object oChar)&lt;br /&gt;
{&lt;br /&gt;
    int nRace       =  GetCreatureRacialType(oChar);&lt;br /&gt;
    int nBackground = GetPlayerBackground(oChar);&lt;br /&gt;
&lt;br /&gt;
    Log_Trace(LOG_CHANNEL_CHARACTER,&amp;quot;bdm_sys_chargen_h&amp;quot;,&amp;quot;Setting plot flags, race: &amp;quot; &lt;br /&gt;
               + IntToString(nRace) + &amp;quot;, background: &amp;quot; + IntToString(nBackground));&lt;br /&gt;
&lt;br /&gt;
    // First, init all flags (debug setup)&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT,FALSE);&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE,FALSE);&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_DWARF_TRAVELLER,FALSE);&lt;br /&gt;
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_ELF_TRAVELLER,FALSE);&lt;br /&gt;
&lt;br /&gt;
    switch (nBackground)&lt;br /&gt;
    {&lt;br /&gt;
        case BACKGROUND_SERVANT:&lt;br /&gt;
        {&lt;br /&gt;
            WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT,TRUE); break;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        case BACKGROUND_APPRENTICE:&lt;br /&gt;
        {&lt;br /&gt;
            WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE,TRUE); break;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
        case BACKGROUND_TRAVELLER:&lt;br /&gt;
        {&lt;br /&gt;
            switch(nRace)&lt;br /&gt;
            {&lt;br /&gt;
                case RACE_DWARF: WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_DWARF_TRAVELLER,TRUE); break;&lt;br /&gt;
                case RACE_ELF: WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_ELF_TRAVELLER,TRUE); break;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lets examine these two functions. First you should compare them to their original versions. For ''bdm_Chargen_SelectBackground()'' we have actually made a more generic version of the function that should work with any backgrounds. We have removed the hard coded values for the background abilities and now use the function ChargenGetBackgroundSkill() which actually gets the background skill from the backgrounds 2DA file that we edited earlier (recall the last three columns that give a skill depending on background and race). If you need fancier logic than just reading the values form the GDA (e.g. like Bioware’s logic for the Noble background) then you can always go back to hard coding them the way Bioware did.&lt;br /&gt;
&lt;br /&gt;
The second function is ''bdm_Chargen_SetupPlotFlags()'' which does just what it says. Remember the plot we created earlier? Here we set the appropriate flag based on race and background.&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Script}}&lt;br /&gt;
&lt;br /&gt;
== Testing that everything works ==&lt;br /&gt;
Now compile your scripts and export your module. Also, make sure that you export your talk table.&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT!''' ''Always make sure you empty your \Dragon Age\packages\core\override folder after doing an export. Due to a bug in the current toolset your single player game will become damaged if you don’t do this before playing.''&lt;br /&gt;
&lt;br /&gt;
You should now be able to run your game and see the backgrounds you created appear in character generation. If you want to test that the background plots have been set correctly, add an NPC to the start area and create a conversation for them in which each line is switched according to a background plot flag. You can also check that the character is receiving the abilities that we set in the 2DAs.&lt;br /&gt;
&lt;br /&gt;
'''NOTE''' ''There seems to be no way to change the popup message that comes up at the beginning of character generation. Altering the Pre-chargen string ID in the loadhints GDA does not seem to do anything.''&lt;br /&gt;
&lt;br /&gt;
{{TutorialRef|Exporting a module}}&lt;br /&gt;
&lt;br /&gt;
== Optional extras ==&lt;br /&gt;
There are a couple of other Bioware scripts that reference the background constants. They are not essential to modify because they are not used anywhere by default. The genev_tutorial script uses a background check but unless you plan on firing the tutorial from your module then you won’t have need of it. Also there is at least one debug script that makes use of the original single player backgrounds (to grant a background plot flag to the PC) so if you want similar debug functionality you may have to roll your own function.&lt;br /&gt;
&lt;br /&gt;
== Race &amp;amp; Gender descriptions ==&lt;br /&gt;
If your module is not set in Ferelden, you may wish to change the descriptions of the Race and Gender buttons that appear during Character Creation.&lt;br /&gt;
&lt;br /&gt;
The Race descriptions are in the Description column of the RACE_base 2DA, so you can replace them with new strings. As before, until the bug is fixed, use a string id in the 100000000 range. &lt;br /&gt;
&lt;br /&gt;
Unfortunately, the gender description is hard-coded in the game as string id 377283. Fortunately, you can make a  [[String_editor#Editing_a_string_with_a_specific_id | local version]] of this string, which only applies to your campaign. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you an advanced user who is familar with the [[UI_Tutorial_%28draft%29 | UI Tutorial]], it's set in the GUI's Localization.as file as LOC_GENDER_DESCRIPTION = 377283, which is then used in the RaceGenderScene.as file. after editing the Localization.as file, you compile it and inject it into the appropriate .gfx'es.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
In this tutorial we have demonstrated a way to modify the backgrounds used in the game without altering any of the core scripts. It is expected that a similar approach could be taken to modding other aspects of the game such as adding classes or races. In these cases the scripts that were created in this tutorial could be extended to handle other parts of the character generation process such as class and race selection.&lt;br /&gt;
&lt;br /&gt;
[[Category:Character generation]]&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_Custom_Placeables_appear/disapear_randomly&amp;diff=16061</id>
		<title>Bug: Custom Placeables appear/disapear randomly</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_Custom_Placeables_appear/disapear_randomly&amp;diff=16061"/>
				<updated>2011-04-06T06:38:53Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Workarounds */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Version found:''' 1.0.1008.0&lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
Custom Placeables appear/disappear randomly from the game between area exports from the Toolset. Sometimes when opening an area in the toolset an error message is printed in the log &amp;quot;''E: 16:31:34 - Could not get the name for the appearance: Resource &amp;quot;keystone.utp&amp;quot;, Tag &amp;quot;keystone&amp;quot;.''&amp;quot;. Usually restarting the Toolset will make the error to go away but it's usual that a placeable doesn't appear in the game evenif there were no errors during export. Sometimes everything is working perfectly fine. Also the same error is sometimes displayed for Creatures using a custom appearance.   &lt;br /&gt;
&lt;br /&gt;
The problem will only appear with custom placeables/appearances those are brought to the toolset using the 2DA &amp;quot;system&amp;quot; like ''placeable_types_myplaceables.GDA'' or ''APR_myappearances.GDA''. I would presume that the Toolset somehow fails to collect and combine all these GDAs.&lt;br /&gt;
&lt;br /&gt;
If the Toolset manage to export everything properly, I don't recall seeing anything to disappear from the game when restarting or reloading a saved game. I am aware of that some modifications doesn't appear in the game unless restart the module from a &amp;quot;clean table&amp;quot;. But that's not the problem here.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
Restarting the Toolset before exporting anything will reduce the frequency of the problem and improves a chance of successful export.&lt;br /&gt;
&lt;br /&gt;
This may well be a special case of the [[Bug:_Toolset_loses_M2DA_dropdown_selection,_resets_to_default | M2DA dropdown bug]]. Close the toolset as soon as the error message is encountered, and export the resource affected again on reopening. &lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Bug:_Custom_Placeables_appear/disapear_randomly&amp;diff=16060</id>
		<title>Bug: Custom Placeables appear/disapear randomly</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Bug:_Custom_Placeables_appear/disapear_randomly&amp;diff=16060"/>
				<updated>2011-04-06T06:38:35Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*'''Version found:''' 1.0.1008.0&lt;br /&gt;
*'''Status:''' Open&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
Custom Placeables appear/disappear randomly from the game between area exports from the Toolset. Sometimes when opening an area in the toolset an error message is printed in the log &amp;quot;''E: 16:31:34 - Could not get the name for the appearance: Resource &amp;quot;keystone.utp&amp;quot;, Tag &amp;quot;keystone&amp;quot;.''&amp;quot;. Usually restarting the Toolset will make the error to go away but it's usual that a placeable doesn't appear in the game evenif there were no errors during export. Sometimes everything is working perfectly fine. Also the same error is sometimes displayed for Creatures using a custom appearance.   &lt;br /&gt;
&lt;br /&gt;
The problem will only appear with custom placeables/appearances those are brought to the toolset using the 2DA &amp;quot;system&amp;quot; like ''placeable_types_myplaceables.GDA'' or ''APR_myappearances.GDA''. I would presume that the Toolset somehow fails to collect and combine all these GDAs.&lt;br /&gt;
&lt;br /&gt;
If the Toolset manage to export everything properly, I don't recall seeing anything to disappear from the game when restarting or reloading a saved game. I am aware of that some modifications doesn't appear in the game unless restart the module from a &amp;quot;clean table&amp;quot;. But that's not the problem here.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
Restarting the Toolset before exporting anything will reduce the frequency of the problem and improves a chance of successful export.&lt;br /&gt;
&lt;br /&gt;
This may well be a special case of the [Bug:_Toolset_loses_M2DA_dropdown_selection,_resets_to_default | M2DA dropdown bug]. Close the toolset as soon as the error message is encountered, and export the resource affected again on reopening. &lt;br /&gt;
&lt;br /&gt;
[[Category:Toolset bugs]]&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16059</id>
		<title>Scripting overview</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16059"/>
				<updated>2011-04-05T14:48:07Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Searching Scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox script}}&lt;br /&gt;
&lt;br /&gt;
Scripting is used whenever the designers need control over the game's behaviour. The syntax for DA scripts is very similar to the C programming language. &lt;br /&gt;
&lt;br /&gt;
Detailed documentation for the scripting language can be found in the &amp;quot;dascript.chm&amp;quot; file, available in your &amp;quot;Dragon Age\packages\core&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
The main uses for it are to: &lt;br /&gt;
&lt;br /&gt;
*Trigger plot events &lt;br /&gt;
*Script conversation &lt;br /&gt;
*Handle creature and party member [[AI]]&lt;br /&gt;
*Script abilities - skills, talents, and spells &lt;br /&gt;
&lt;br /&gt;
DA also has a client-side scripting language whose primary responsibility is automated testing of the game. See [[client script]]s for more details.&lt;br /&gt;
&lt;br /&gt;
AI Scripts are event based. Objects will have only one event-handling script assigned to them that will be run whenever they receive a game event. This script will receive the event type as a parameter and will need to determine the appropriate response for itself.&lt;br /&gt;
&lt;br /&gt;
There are several file extensions associated with scripts:&lt;br /&gt;
* NSS - script source file&lt;br /&gt;
* NCS - compiled script&lt;br /&gt;
* NDB - debug information file (required for using the script debugger to trace through this file)&lt;br /&gt;
&lt;br /&gt;
== Script editor ==&lt;br /&gt;
&lt;br /&gt;
Scripts are created in the Designer Toolset using the Script Editor. Once created, scripts must be assigned to such things as Creatures before they can be used. Once assigned, both the referencing object and the script must be exported in order to be viewed in the game. Exporting happens automatically or can be done manually by the designer during testing. &lt;br /&gt;
&lt;br /&gt;
The script editor supports the following features: &lt;br /&gt;
&lt;br /&gt;
*Undo and redo &lt;br /&gt;
*Find and replace &lt;br /&gt;
*Bookmarking: View -&amp;gt; Other Windows -&amp;gt; Bookmarks&lt;br /&gt;
*Function, variable, constant, and template browser (visible on the right-hand side of the screen).&lt;br /&gt;
*Auto-complete when typing function and variable names &lt;br /&gt;
*Syntax highlighting &lt;br /&gt;
*Auto-indention &lt;br /&gt;
*Brace matching/highlighting &lt;br /&gt;
*Ability to test compile a script &lt;br /&gt;
*Jump to definition&lt;br /&gt;
&lt;br /&gt;
To the right of the script editor is a sidebar with a browser that can display all currently-defined functions, variables, or constants, or a set of 'template' scripts that can serve as a starting point when writing a script from scratch. The browser also has a filter field where you can type in a partial string and have the list automatically exclude everything that doesn't include it in the name.&lt;br /&gt;
&lt;br /&gt;
This is the constant browser:&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser.png]]&lt;br /&gt;
&lt;br /&gt;
Here it is with &amp;quot;team&amp;quot; typed into the filter field, displaying only constants with names that contain the substring &amp;quot;team&amp;quot; (not case sensitive):&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser filtered.png]]&lt;br /&gt;
&lt;br /&gt;
The templates that come with Dragon Age include frameworks for the most common event scripts found in the game. You can add your own templates quite easily, just create a text file with the template code in it and place it in the Dragon Age\Toolset\scripttemplates directory with the others.&lt;br /&gt;
&lt;br /&gt;
[[Image:scripting template browser.png]]&lt;br /&gt;
&lt;br /&gt;
Dragon Age's toolset supports Doxygen-style comments. If you double-click on a function name a help window will pop open to display its documentation. You can also jump to a function's definition (provided it isn't an engine-defined function in script.ldf) by right-clicking on it and selecting &amp;quot;go to definition&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting help window.png]]&lt;br /&gt;
&lt;br /&gt;
== Writing scripts ==&lt;br /&gt;
&lt;br /&gt;
For a script to compile, it needs a body:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The parameters on this can't be changed or the script won't compile.&lt;br /&gt;
&lt;br /&gt;
Scripts associated with a dialog node take this alternate form:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Including files ===&lt;br /&gt;
Other script files can be included by using the #include directive. &lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;rules_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    DoSomethingOrOther();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The included file is '''inserted''' into the main file before the script is compiled. Any number of files can be included.&lt;br /&gt;
'''Important:''' this means that whenever you change an &amp;quot;include file&amp;quot; you must export all script that include it before they will use the new version!&lt;br /&gt;
&lt;br /&gt;
No other C-style preprocessor commands are supported.&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
The scripting language supports the following operators:&lt;br /&gt;
&lt;br /&gt;
====Arithmetic Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Prefix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while ( ++a &amp;lt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt; for (i = 0; i &amp;lt; 10; i++) { } &amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by addition&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a += b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Subtraction (difference)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a - b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Addition (sum)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a + b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Prefix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (--a &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (a-- &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by subtraction&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a -= b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Multiplication (product)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a * b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Division (quotient)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a / b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Modulo (remainder)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a % b == 1) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Comparison Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Less than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Less than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Not Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a != b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a == b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Logical Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Logical negation (NOT)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (!a) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical AND&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;amp;&amp;amp; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical OR&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a || b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Other Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Basic assignment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a = b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Function call&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a();&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Array subscript&lt;br /&gt;
| &amp;lt;dascript&amp;gt;array[0] = 1;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Member (on structures)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;structure.member = 0;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Ternary conditional&lt;br /&gt;
| &amp;lt;dascript&amp;gt;return a &amp;lt; b ? c : d;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Types &amp;amp; Variable  ===&lt;br /&gt;
&lt;br /&gt;
The scripting language natively supports:&lt;br /&gt;
* [[float]] - floating-point numbers. &amp;lt;dascript&amp;gt;float fFloat = 0.1234f;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[int]] - integer numbers. &amp;lt;dascript&amp;gt;int nInteger = 1234;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[object]] -game object files. &amp;lt;dascript&amp;gt;object oObject = GetObjectByTag(&amp;quot;monster_001&amp;quot;);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[resource]] - game resource files. &amp;lt;dascript&amp;gt;resource rGameIntroCutscene = R&amp;quot;game_intro_.cut&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[string]] - text strings. &amp;lt;dascript&amp;gt;string sString = &amp;quot;Hello World!&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[vector]] - positions or directions. &amp;lt;dascript&amp;gt;vector vVector = Vector(0.0, 1.1, 2.2);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server language has been expanded to support these engine defined structures:&lt;br /&gt;
* [[Event (dascript type)|event]] - events are signals that are sent to scripts by other scripts or by the world engine.&lt;br /&gt;
* [[location]]&lt;br /&gt;
* [[command]] - a command for a creature or object to do something. Commands are constructed using functions that return them, and then are added to a target's command queue with the AddCommand function.&lt;br /&gt;
* [[effect]]&lt;br /&gt;
* [[itemproperty]]&lt;br /&gt;
* [[player]]&lt;br /&gt;
&lt;br /&gt;
All of these types are always passed by value, which means a new copy is made whenever they are passed into a function or copied to another variable.&lt;br /&gt;
&lt;br /&gt;
This means that most functions that are supposed to modify a structure in some way need to return the modified one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    effect e1 = Effect(100);&lt;br /&gt;
    effect e2 = SetEffectType(e1, 101); // e1 != e2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Structures ====&lt;br /&gt;
&lt;br /&gt;
Users can define their own structures using the [[struct]] keyword:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// user-defined type&lt;br /&gt;
struct quaternion&lt;br /&gt;
{&lt;br /&gt;
    float w, x, y, z;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// constructor&lt;br /&gt;
struct quaternion Quaternion(float fW, float fX, float fY, float fZ)&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q;&lt;br /&gt;
&lt;br /&gt;
    q.w = fW;&lt;br /&gt;
    q.x = fX;&lt;br /&gt;
    q.y = fY;&lt;br /&gt;
    q.z = fZ;&lt;br /&gt;
&lt;br /&gt;
    return q;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q = Quaternion(0.0, 0.0, 0.0, 0.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
Variables can be declared as arrays for any type except user-defined structs. Designers can create their own arrays of any major data type (int, string, object). Many functions will also return arrays (for example, creatures in an area will be returned as an array, and the action queue will be returned as an array).&lt;br /&gt;
&lt;br /&gt;
These are different from C-style arrays in that they can be resized like STL vectors, and their notation is slightly different.&lt;br /&gt;
&lt;br /&gt;
Arrays also behave differently from other objects in the scripting language because they are passed by reference.  If an array is passed into a function and modified:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    int[] i;                 // new array of integers with a size of zero &lt;br /&gt;
    i[0] = 5;                // value of array position 0 is now 5&lt;br /&gt;
    i[1] = -1;               // value of array position 1 is now -1&lt;br /&gt;
&lt;br /&gt;
    int[] j = i;             // i and j point to the same array&lt;br /&gt;
    j[1] = 12;               // value of array position 1 for both i and j is now 12!&lt;br /&gt;
&lt;br /&gt;
    SortArrayDescending(i);  // i and j are both sorted now, this function has no return value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[GetArraySize]] returns the size of an array.&lt;br /&gt;
&lt;br /&gt;
==== Local Variables ====&lt;br /&gt;
&lt;br /&gt;
In Neverwinter Nights, variables for various objects could be created and set with functions such as SetLocalInt(). Dragon Age does not have analogous functions. Instead, all of the variables that a given object is able to have values assigned to must be defined ahead of time in a 2DA. This more restrictive approach is intended to improve performance and reduce the opportunity for errors (for example, making a typo in the name of a variable and losing track of it as a result).&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to discover a function and what it does.&lt;br /&gt;
&lt;br /&gt;
If you type in the name of a function that's been defined and then an opening bracket, a tooltip will pop up showing the function's parameter types and return type.&lt;br /&gt;
&lt;br /&gt;
Alternately, if you have the help window open (View -&amp;gt; Other Windows -&amp;gt; Help Window), then whenever you select a function in the function browser a help page describing the function will be displayed.&lt;br /&gt;
&lt;br /&gt;
=== Passing parameters to scripts ===&lt;br /&gt;
&lt;br /&gt;
To pass parameters to scripts they must be called with the 'runscript' command. This can be useful for writing debug scripts or changing actions based on input. To accept parameters simply add this line to your script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
string sParams = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then type 'runscript scriptname parameter1 parameter2 ... paramaterN' to pass parameters.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: heals the object with the given tag. If tag is invalid, nothing happens&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sTag = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    object oCreature = GetObjectByTag(sTag);&lt;br /&gt;
    effect   eHeal = EffectHeal(25.0f)&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: applies the visual effect passed in as parameter to the player&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sEffect = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    int    nEffect = StringToInt(sEffect);&lt;br /&gt;
    effect eVfx = EffectVisualEffect(nEffect);&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error messages and logging ===&lt;br /&gt;
&lt;br /&gt;
See [[Script error]] for details of how to correct errors in scripts.&lt;br /&gt;
&lt;br /&gt;
To enable script logging, edit or create &amp;lt;DragonAgeInstallDirectory&amp;gt;\bin_ship\[[ECLog.ini]] and set Script=1 in the [LogTypes] section.&lt;br /&gt;
&lt;br /&gt;
The [[PrintToLog]] function prints messages to the log file once logging is enabled.&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
&lt;br /&gt;
Commands, delayed events and object destruction all take place after the current script is finished running. Plot flags set in script are set in-line but the triggered plot script runs before the flag is actually set (this is clarified a bit in the plot script template).&lt;br /&gt;
&lt;br /&gt;
Given that ExecuteScript is deprecated, HandleEvent should be used when you want the script to run in-line and DelayEvent should be used when you want to delay execution.&lt;br /&gt;
&lt;br /&gt;
To delay execution when dealing with creatures, custom AI and (safe) command complete are nice tools. DelayEvent should be used whenever you know how long you want to wait before the event fires. (It can also be used in quite small time increments to give the illusion of smoothly sliding placeables with SetPosition or interpolate between two different atmosphere/lighting settings, but the overhead of this is noticeable if overused).&lt;br /&gt;
&lt;br /&gt;
== Searching Scripts ==&lt;br /&gt;
&lt;br /&gt;
To find examples of how Bioware does things, or simply to discover where a function or variable is used, it's useful to be able to search all the scripts in the data base for a string.&lt;br /&gt;
&lt;br /&gt;
You'll need Microsoft SQL Server Management Studio Express - see [[Preparing_a_dialog_for_recording | Preparing a dialog for recording&lt;br /&gt;
]].&lt;br /&gt;
&lt;br /&gt;
Enter the following query:&lt;br /&gt;
&lt;br /&gt;
   SELECT DISTINCT Module.Name, Resource.Name &lt;br /&gt;
     FROM   [bw_dragonage_content].[dbo].[t_Module] Module, &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_ModuleResRefVersion] Resource, &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_Script] Script &lt;br /&gt;
     WHERE  Module.ID   = Resource.ModuleID&lt;br /&gt;
     AND    Resource.ID = Script.ModuleResRefVersionID&lt;br /&gt;
     AND    Script.Text LIKE '%######%'&lt;br /&gt;
     ORDER BY 1, 2; &lt;br /&gt;
&lt;br /&gt;
where ###### is the string you want to find.&lt;br /&gt;
&lt;br /&gt;
This will list the name of every script that contains the string ######.&lt;br /&gt;
[[Category:Scripts]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16058</id>
		<title>Scripting overview</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16058"/>
				<updated>2011-04-05T14:14:36Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Searching Scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox script}}&lt;br /&gt;
&lt;br /&gt;
Scripting is used whenever the designers need control over the game's behaviour. The syntax for DA scripts is very similar to the C programming language. &lt;br /&gt;
&lt;br /&gt;
Detailed documentation for the scripting language can be found in the &amp;quot;dascript.chm&amp;quot; file, available in your &amp;quot;Dragon Age\packages\core&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
The main uses for it are to: &lt;br /&gt;
&lt;br /&gt;
*Trigger plot events &lt;br /&gt;
*Script conversation &lt;br /&gt;
*Handle creature and party member [[AI]]&lt;br /&gt;
*Script abilities - skills, talents, and spells &lt;br /&gt;
&lt;br /&gt;
DA also has a client-side scripting language whose primary responsibility is automated testing of the game. See [[client script]]s for more details.&lt;br /&gt;
&lt;br /&gt;
AI Scripts are event based. Objects will have only one event-handling script assigned to them that will be run whenever they receive a game event. This script will receive the event type as a parameter and will need to determine the appropriate response for itself.&lt;br /&gt;
&lt;br /&gt;
There are several file extensions associated with scripts:&lt;br /&gt;
* NSS - script source file&lt;br /&gt;
* NCS - compiled script&lt;br /&gt;
* NDB - debug information file (required for using the script debugger to trace through this file)&lt;br /&gt;
&lt;br /&gt;
== Script editor ==&lt;br /&gt;
&lt;br /&gt;
Scripts are created in the Designer Toolset using the Script Editor. Once created, scripts must be assigned to such things as Creatures before they can be used. Once assigned, both the referencing object and the script must be exported in order to be viewed in the game. Exporting happens automatically or can be done manually by the designer during testing. &lt;br /&gt;
&lt;br /&gt;
The script editor supports the following features: &lt;br /&gt;
&lt;br /&gt;
*Undo and redo &lt;br /&gt;
*Find and replace &lt;br /&gt;
*Bookmarking: View -&amp;gt; Other Windows -&amp;gt; Bookmarks&lt;br /&gt;
*Function, variable, constant, and template browser (visible on the right-hand side of the screen).&lt;br /&gt;
*Auto-complete when typing function and variable names &lt;br /&gt;
*Syntax highlighting &lt;br /&gt;
*Auto-indention &lt;br /&gt;
*Brace matching/highlighting &lt;br /&gt;
*Ability to test compile a script &lt;br /&gt;
*Jump to definition&lt;br /&gt;
&lt;br /&gt;
To the right of the script editor is a sidebar with a browser that can display all currently-defined functions, variables, or constants, or a set of 'template' scripts that can serve as a starting point when writing a script from scratch. The browser also has a filter field where you can type in a partial string and have the list automatically exclude everything that doesn't include it in the name.&lt;br /&gt;
&lt;br /&gt;
This is the constant browser:&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser.png]]&lt;br /&gt;
&lt;br /&gt;
Here it is with &amp;quot;team&amp;quot; typed into the filter field, displaying only constants with names that contain the substring &amp;quot;team&amp;quot; (not case sensitive):&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser filtered.png]]&lt;br /&gt;
&lt;br /&gt;
The templates that come with Dragon Age include frameworks for the most common event scripts found in the game. You can add your own templates quite easily, just create a text file with the template code in it and place it in the Dragon Age\Toolset\scripttemplates directory with the others.&lt;br /&gt;
&lt;br /&gt;
[[Image:scripting template browser.png]]&lt;br /&gt;
&lt;br /&gt;
Dragon Age's toolset supports Doxygen-style comments. If you double-click on a function name a help window will pop open to display its documentation. You can also jump to a function's definition (provided it isn't an engine-defined function in script.ldf) by right-clicking on it and selecting &amp;quot;go to definition&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting help window.png]]&lt;br /&gt;
&lt;br /&gt;
== Writing scripts ==&lt;br /&gt;
&lt;br /&gt;
For a script to compile, it needs a body:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The parameters on this can't be changed or the script won't compile.&lt;br /&gt;
&lt;br /&gt;
Scripts associated with a dialog node take this alternate form:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Including files ===&lt;br /&gt;
Other script files can be included by using the #include directive. &lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;rules_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    DoSomethingOrOther();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The included file is '''inserted''' into the main file before the script is compiled. Any number of files can be included.&lt;br /&gt;
'''Important:''' this means that whenever you change an &amp;quot;include file&amp;quot; you must export all script that include it before they will use the new version!&lt;br /&gt;
&lt;br /&gt;
No other C-style preprocessor commands are supported.&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
The scripting language supports the following operators:&lt;br /&gt;
&lt;br /&gt;
====Arithmetic Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Prefix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while ( ++a &amp;lt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt; for (i = 0; i &amp;lt; 10; i++) { } &amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by addition&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a += b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Subtraction (difference)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a - b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Addition (sum)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a + b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Prefix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (--a &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (a-- &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by subtraction&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a -= b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Multiplication (product)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a * b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Division (quotient)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a / b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Modulo (remainder)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a % b == 1) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Comparison Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Less than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Less than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Not Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a != b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a == b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Logical Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Logical negation (NOT)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (!a) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical AND&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;amp;&amp;amp; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical OR&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a || b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Other Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Basic assignment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a = b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Function call&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a();&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Array subscript&lt;br /&gt;
| &amp;lt;dascript&amp;gt;array[0] = 1;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Member (on structures)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;structure.member = 0;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Ternary conditional&lt;br /&gt;
| &amp;lt;dascript&amp;gt;return a &amp;lt; b ? c : d;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Types &amp;amp; Variable  ===&lt;br /&gt;
&lt;br /&gt;
The scripting language natively supports:&lt;br /&gt;
* [[float]] - floating-point numbers. &amp;lt;dascript&amp;gt;float fFloat = 0.1234f;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[int]] - integer numbers. &amp;lt;dascript&amp;gt;int nInteger = 1234;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[object]] -game object files. &amp;lt;dascript&amp;gt;object oObject = GetObjectByTag(&amp;quot;monster_001&amp;quot;);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[resource]] - game resource files. &amp;lt;dascript&amp;gt;resource rGameIntroCutscene = R&amp;quot;game_intro_.cut&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[string]] - text strings. &amp;lt;dascript&amp;gt;string sString = &amp;quot;Hello World!&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[vector]] - positions or directions. &amp;lt;dascript&amp;gt;vector vVector = Vector(0.0, 1.1, 2.2);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server language has been expanded to support these engine defined structures:&lt;br /&gt;
* [[Event (dascript type)|event]] - events are signals that are sent to scripts by other scripts or by the world engine.&lt;br /&gt;
* [[location]]&lt;br /&gt;
* [[command]] - a command for a creature or object to do something. Commands are constructed using functions that return them, and then are added to a target's command queue with the AddCommand function.&lt;br /&gt;
* [[effect]]&lt;br /&gt;
* [[itemproperty]]&lt;br /&gt;
* [[player]]&lt;br /&gt;
&lt;br /&gt;
All of these types are always passed by value, which means a new copy is made whenever they are passed into a function or copied to another variable.&lt;br /&gt;
&lt;br /&gt;
This means that most functions that are supposed to modify a structure in some way need to return the modified one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    effect e1 = Effect(100);&lt;br /&gt;
    effect e2 = SetEffectType(e1, 101); // e1 != e2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Structures ====&lt;br /&gt;
&lt;br /&gt;
Users can define their own structures using the [[struct]] keyword:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// user-defined type&lt;br /&gt;
struct quaternion&lt;br /&gt;
{&lt;br /&gt;
    float w, x, y, z;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// constructor&lt;br /&gt;
struct quaternion Quaternion(float fW, float fX, float fY, float fZ)&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q;&lt;br /&gt;
&lt;br /&gt;
    q.w = fW;&lt;br /&gt;
    q.x = fX;&lt;br /&gt;
    q.y = fY;&lt;br /&gt;
    q.z = fZ;&lt;br /&gt;
&lt;br /&gt;
    return q;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q = Quaternion(0.0, 0.0, 0.0, 0.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
Variables can be declared as arrays for any type except user-defined structs. Designers can create their own arrays of any major data type (int, string, object). Many functions will also return arrays (for example, creatures in an area will be returned as an array, and the action queue will be returned as an array).&lt;br /&gt;
&lt;br /&gt;
These are different from C-style arrays in that they can be resized like STL vectors, and their notation is slightly different.&lt;br /&gt;
&lt;br /&gt;
Arrays also behave differently from other objects in the scripting language because they are passed by reference.  If an array is passed into a function and modified:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    int[] i;                 // new array of integers with a size of zero &lt;br /&gt;
    i[0] = 5;                // value of array position 0 is now 5&lt;br /&gt;
    i[1] = -1;               // value of array position 1 is now -1&lt;br /&gt;
&lt;br /&gt;
    int[] j = i;             // i and j point to the same array&lt;br /&gt;
    j[1] = 12;               // value of array position 1 for both i and j is now 12!&lt;br /&gt;
&lt;br /&gt;
    SortArrayDescending(i);  // i and j are both sorted now, this function has no return value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[GetArraySize]] returns the size of an array.&lt;br /&gt;
&lt;br /&gt;
==== Local Variables ====&lt;br /&gt;
&lt;br /&gt;
In Neverwinter Nights, variables for various objects could be created and set with functions such as SetLocalInt(). Dragon Age does not have analogous functions. Instead, all of the variables that a given object is able to have values assigned to must be defined ahead of time in a 2DA. This more restrictive approach is intended to improve performance and reduce the opportunity for errors (for example, making a typo in the name of a variable and losing track of it as a result).&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to discover a function and what it does.&lt;br /&gt;
&lt;br /&gt;
If you type in the name of a function that's been defined and then an opening bracket, a tooltip will pop up showing the function's parameter types and return type.&lt;br /&gt;
&lt;br /&gt;
Alternately, if you have the help window open (View -&amp;gt; Other Windows -&amp;gt; Help Window), then whenever you select a function in the function browser a help page describing the function will be displayed.&lt;br /&gt;
&lt;br /&gt;
=== Passing parameters to scripts ===&lt;br /&gt;
&lt;br /&gt;
To pass parameters to scripts they must be called with the 'runscript' command. This can be useful for writing debug scripts or changing actions based on input. To accept parameters simply add this line to your script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
string sParams = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then type 'runscript scriptname parameter1 parameter2 ... paramaterN' to pass parameters.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: heals the object with the given tag. If tag is invalid, nothing happens&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sTag = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    object oCreature = GetObjectByTag(sTag);&lt;br /&gt;
    effect   eHeal = EffectHeal(25.0f)&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: applies the visual effect passed in as parameter to the player&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sEffect = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    int    nEffect = StringToInt(sEffect);&lt;br /&gt;
    effect eVfx = EffectVisualEffect(nEffect);&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error messages and logging ===&lt;br /&gt;
&lt;br /&gt;
See [[Script error]] for details of how to correct errors in scripts.&lt;br /&gt;
&lt;br /&gt;
To enable script logging, edit or create &amp;lt;DragonAgeInstallDirectory&amp;gt;\bin_ship\[[ECLog.ini]] and set Script=1 in the [LogTypes] section.&lt;br /&gt;
&lt;br /&gt;
The [[PrintToLog]] function prints messages to the log file once logging is enabled.&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
&lt;br /&gt;
Commands, delayed events and object destruction all take place after the current script is finished running. Plot flags set in script are set in-line but the triggered plot script runs before the flag is actually set (this is clarified a bit in the plot script template).&lt;br /&gt;
&lt;br /&gt;
Given that ExecuteScript is deprecated, HandleEvent should be used when you want the script to run in-line and DelayEvent should be used when you want to delay execution.&lt;br /&gt;
&lt;br /&gt;
To delay execution when dealing with creatures, custom AI and (safe) command complete are nice tools. DelayEvent should be used whenever you know how long you want to wait before the event fires. (It can also be used in quite small time increments to give the illusion of smoothly sliding placeables with SetPosition or interpolate between two different atmosphere/lighting settings, but the overhead of this is noticeable if overused).&lt;br /&gt;
&lt;br /&gt;
== Searching Scripts ==&lt;br /&gt;
&lt;br /&gt;
To find examples of how Bioware does things, or simply to discover where a function or variable is used, it's useful to be able to search all the scripts in the data base for a string.&lt;br /&gt;
&lt;br /&gt;
You'll need Microsoft SQL Server Management Studio Express - see [[Preparing_a_dialog_for_recording | Preparing a dialog for recording&lt;br /&gt;
]].&lt;br /&gt;
&lt;br /&gt;
Enter the following query:&lt;br /&gt;
&lt;br /&gt;
   SELECT DISTINCT Module.Name, Resource.Name &lt;br /&gt;
     FROM   [bw_dragonage_content].[dbo].[t_Module] Module, &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_ModuleResRefVersion] Resource, &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_Script] Script &lt;br /&gt;
     WHERE  Module.ID   = Resource.ModuleID&lt;br /&gt;
     AND    Resource.ID = Script.ModuleResRefVersionID&lt;br /&gt;
     AND    Script.Text LIKE '%partypicker%'&lt;br /&gt;
     ORDER BY 1, 2; &lt;br /&gt;
&lt;br /&gt;
where ###### is the string you want to find.&lt;br /&gt;
&lt;br /&gt;
This will list the name of every script that contains the string ######.&lt;br /&gt;
[[Category:Scripts]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16057</id>
		<title>Scripting overview</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16057"/>
				<updated>2011-04-05T11:32:37Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Searching Scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox script}}&lt;br /&gt;
&lt;br /&gt;
Scripting is used whenever the designers need control over the game's behaviour. The syntax for DA scripts is very similar to the C programming language. &lt;br /&gt;
&lt;br /&gt;
Detailed documentation for the scripting language can be found in the &amp;quot;dascript.chm&amp;quot; file, available in your &amp;quot;Dragon Age\packages\core&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
The main uses for it are to: &lt;br /&gt;
&lt;br /&gt;
*Trigger plot events &lt;br /&gt;
*Script conversation &lt;br /&gt;
*Handle creature and party member [[AI]]&lt;br /&gt;
*Script abilities - skills, talents, and spells &lt;br /&gt;
&lt;br /&gt;
DA also has a client-side scripting language whose primary responsibility is automated testing of the game. See [[client script]]s for more details.&lt;br /&gt;
&lt;br /&gt;
AI Scripts are event based. Objects will have only one event-handling script assigned to them that will be run whenever they receive a game event. This script will receive the event type as a parameter and will need to determine the appropriate response for itself.&lt;br /&gt;
&lt;br /&gt;
There are several file extensions associated with scripts:&lt;br /&gt;
* NSS - script source file&lt;br /&gt;
* NCS - compiled script&lt;br /&gt;
* NDB - debug information file (required for using the script debugger to trace through this file)&lt;br /&gt;
&lt;br /&gt;
== Script editor ==&lt;br /&gt;
&lt;br /&gt;
Scripts are created in the Designer Toolset using the Script Editor. Once created, scripts must be assigned to such things as Creatures before they can be used. Once assigned, both the referencing object and the script must be exported in order to be viewed in the game. Exporting happens automatically or can be done manually by the designer during testing. &lt;br /&gt;
&lt;br /&gt;
The script editor supports the following features: &lt;br /&gt;
&lt;br /&gt;
*Undo and redo &lt;br /&gt;
*Find and replace &lt;br /&gt;
*Bookmarking: View -&amp;gt; Other Windows -&amp;gt; Bookmarks&lt;br /&gt;
*Function, variable, constant, and template browser (visible on the right-hand side of the screen).&lt;br /&gt;
*Auto-complete when typing function and variable names &lt;br /&gt;
*Syntax highlighting &lt;br /&gt;
*Auto-indention &lt;br /&gt;
*Brace matching/highlighting &lt;br /&gt;
*Ability to test compile a script &lt;br /&gt;
*Jump to definition&lt;br /&gt;
&lt;br /&gt;
To the right of the script editor is a sidebar with a browser that can display all currently-defined functions, variables, or constants, or a set of 'template' scripts that can serve as a starting point when writing a script from scratch. The browser also has a filter field where you can type in a partial string and have the list automatically exclude everything that doesn't include it in the name.&lt;br /&gt;
&lt;br /&gt;
This is the constant browser:&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser.png]]&lt;br /&gt;
&lt;br /&gt;
Here it is with &amp;quot;team&amp;quot; typed into the filter field, displaying only constants with names that contain the substring &amp;quot;team&amp;quot; (not case sensitive):&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser filtered.png]]&lt;br /&gt;
&lt;br /&gt;
The templates that come with Dragon Age include frameworks for the most common event scripts found in the game. You can add your own templates quite easily, just create a text file with the template code in it and place it in the Dragon Age\Toolset\scripttemplates directory with the others.&lt;br /&gt;
&lt;br /&gt;
[[Image:scripting template browser.png]]&lt;br /&gt;
&lt;br /&gt;
Dragon Age's toolset supports Doxygen-style comments. If you double-click on a function name a help window will pop open to display its documentation. You can also jump to a function's definition (provided it isn't an engine-defined function in script.ldf) by right-clicking on it and selecting &amp;quot;go to definition&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting help window.png]]&lt;br /&gt;
&lt;br /&gt;
== Writing scripts ==&lt;br /&gt;
&lt;br /&gt;
For a script to compile, it needs a body:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The parameters on this can't be changed or the script won't compile.&lt;br /&gt;
&lt;br /&gt;
Scripts associated with a dialog node take this alternate form:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Including files ===&lt;br /&gt;
Other script files can be included by using the #include directive. &lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;rules_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    DoSomethingOrOther();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The included file is '''inserted''' into the main file before the script is compiled. Any number of files can be included.&lt;br /&gt;
'''Important:''' this means that whenever you change an &amp;quot;include file&amp;quot; you must export all script that include it before they will use the new version!&lt;br /&gt;
&lt;br /&gt;
No other C-style preprocessor commands are supported.&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
The scripting language supports the following operators:&lt;br /&gt;
&lt;br /&gt;
====Arithmetic Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Prefix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while ( ++a &amp;lt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt; for (i = 0; i &amp;lt; 10; i++) { } &amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by addition&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a += b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Subtraction (difference)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a - b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Addition (sum)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a + b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Prefix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (--a &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (a-- &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by subtraction&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a -= b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Multiplication (product)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a * b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Division (quotient)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a / b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Modulo (remainder)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a % b == 1) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Comparison Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Less than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Less than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Not Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a != b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a == b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Logical Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Logical negation (NOT)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (!a) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical AND&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;amp;&amp;amp; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical OR&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a || b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Other Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Basic assignment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a = b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Function call&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a();&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Array subscript&lt;br /&gt;
| &amp;lt;dascript&amp;gt;array[0] = 1;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Member (on structures)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;structure.member = 0;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Ternary conditional&lt;br /&gt;
| &amp;lt;dascript&amp;gt;return a &amp;lt; b ? c : d;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Types &amp;amp; Variable  ===&lt;br /&gt;
&lt;br /&gt;
The scripting language natively supports:&lt;br /&gt;
* [[float]] - floating-point numbers. &amp;lt;dascript&amp;gt;float fFloat = 0.1234f;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[int]] - integer numbers. &amp;lt;dascript&amp;gt;int nInteger = 1234;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[object]] -game object files. &amp;lt;dascript&amp;gt;object oObject = GetObjectByTag(&amp;quot;monster_001&amp;quot;);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[resource]] - game resource files. &amp;lt;dascript&amp;gt;resource rGameIntroCutscene = R&amp;quot;game_intro_.cut&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[string]] - text strings. &amp;lt;dascript&amp;gt;string sString = &amp;quot;Hello World!&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[vector]] - positions or directions. &amp;lt;dascript&amp;gt;vector vVector = Vector(0.0, 1.1, 2.2);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server language has been expanded to support these engine defined structures:&lt;br /&gt;
* [[Event (dascript type)|event]] - events are signals that are sent to scripts by other scripts or by the world engine.&lt;br /&gt;
* [[location]]&lt;br /&gt;
* [[command]] - a command for a creature or object to do something. Commands are constructed using functions that return them, and then are added to a target's command queue with the AddCommand function.&lt;br /&gt;
* [[effect]]&lt;br /&gt;
* [[itemproperty]]&lt;br /&gt;
* [[player]]&lt;br /&gt;
&lt;br /&gt;
All of these types are always passed by value, which means a new copy is made whenever they are passed into a function or copied to another variable.&lt;br /&gt;
&lt;br /&gt;
This means that most functions that are supposed to modify a structure in some way need to return the modified one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    effect e1 = Effect(100);&lt;br /&gt;
    effect e2 = SetEffectType(e1, 101); // e1 != e2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Structures ====&lt;br /&gt;
&lt;br /&gt;
Users can define their own structures using the [[struct]] keyword:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// user-defined type&lt;br /&gt;
struct quaternion&lt;br /&gt;
{&lt;br /&gt;
    float w, x, y, z;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// constructor&lt;br /&gt;
struct quaternion Quaternion(float fW, float fX, float fY, float fZ)&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q;&lt;br /&gt;
&lt;br /&gt;
    q.w = fW;&lt;br /&gt;
    q.x = fX;&lt;br /&gt;
    q.y = fY;&lt;br /&gt;
    q.z = fZ;&lt;br /&gt;
&lt;br /&gt;
    return q;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q = Quaternion(0.0, 0.0, 0.0, 0.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
Variables can be declared as arrays for any type except user-defined structs. Designers can create their own arrays of any major data type (int, string, object). Many functions will also return arrays (for example, creatures in an area will be returned as an array, and the action queue will be returned as an array).&lt;br /&gt;
&lt;br /&gt;
These are different from C-style arrays in that they can be resized like STL vectors, and their notation is slightly different.&lt;br /&gt;
&lt;br /&gt;
Arrays also behave differently from other objects in the scripting language because they are passed by reference.  If an array is passed into a function and modified:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    int[] i;                 // new array of integers with a size of zero &lt;br /&gt;
    i[0] = 5;                // value of array position 0 is now 5&lt;br /&gt;
    i[1] = -1;               // value of array position 1 is now -1&lt;br /&gt;
&lt;br /&gt;
    int[] j = i;             // i and j point to the same array&lt;br /&gt;
    j[1] = 12;               // value of array position 1 for both i and j is now 12!&lt;br /&gt;
&lt;br /&gt;
    SortArrayDescending(i);  // i and j are both sorted now, this function has no return value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[GetArraySize]] returns the size of an array.&lt;br /&gt;
&lt;br /&gt;
==== Local Variables ====&lt;br /&gt;
&lt;br /&gt;
In Neverwinter Nights, variables for various objects could be created and set with functions such as SetLocalInt(). Dragon Age does not have analogous functions. Instead, all of the variables that a given object is able to have values assigned to must be defined ahead of time in a 2DA. This more restrictive approach is intended to improve performance and reduce the opportunity for errors (for example, making a typo in the name of a variable and losing track of it as a result).&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to discover a function and what it does.&lt;br /&gt;
&lt;br /&gt;
If you type in the name of a function that's been defined and then an opening bracket, a tooltip will pop up showing the function's parameter types and return type.&lt;br /&gt;
&lt;br /&gt;
Alternately, if you have the help window open (View -&amp;gt; Other Windows -&amp;gt; Help Window), then whenever you select a function in the function browser a help page describing the function will be displayed.&lt;br /&gt;
&lt;br /&gt;
=== Passing parameters to scripts ===&lt;br /&gt;
&lt;br /&gt;
To pass parameters to scripts they must be called with the 'runscript' command. This can be useful for writing debug scripts or changing actions based on input. To accept parameters simply add this line to your script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
string sParams = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then type 'runscript scriptname parameter1 parameter2 ... paramaterN' to pass parameters.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: heals the object with the given tag. If tag is invalid, nothing happens&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sTag = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    object oCreature = GetObjectByTag(sTag);&lt;br /&gt;
    effect   eHeal = EffectHeal(25.0f)&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: applies the visual effect passed in as parameter to the player&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sEffect = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    int    nEffect = StringToInt(sEffect);&lt;br /&gt;
    effect eVfx = EffectVisualEffect(nEffect);&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error messages and logging ===&lt;br /&gt;
&lt;br /&gt;
See [[Script error]] for details of how to correct errors in scripts.&lt;br /&gt;
&lt;br /&gt;
To enable script logging, edit or create &amp;lt;DragonAgeInstallDirectory&amp;gt;\bin_ship\[[ECLog.ini]] and set Script=1 in the [LogTypes] section.&lt;br /&gt;
&lt;br /&gt;
The [[PrintToLog]] function prints messages to the log file once logging is enabled.&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
&lt;br /&gt;
Commands, delayed events and object destruction all take place after the current script is finished running. Plot flags set in script are set in-line but the triggered plot script runs before the flag is actually set (this is clarified a bit in the plot script template).&lt;br /&gt;
&lt;br /&gt;
Given that ExecuteScript is deprecated, HandleEvent should be used when you want the script to run in-line and DelayEvent should be used when you want to delay execution.&lt;br /&gt;
&lt;br /&gt;
To delay execution when dealing with creatures, custom AI and (safe) command complete are nice tools. DelayEvent should be used whenever you know how long you want to wait before the event fires. (It can also be used in quite small time increments to give the illusion of smoothly sliding placeables with SetPosition or interpolate between two different atmosphere/lighting settings, but the overhead of this is noticeable if overused).&lt;br /&gt;
&lt;br /&gt;
== Searching Scripts ==&lt;br /&gt;
&lt;br /&gt;
To find examples of how Bioware does things, or simply to discover where a function or variable is used, it's useful to be able to search all the scripts in the data base for a string.&lt;br /&gt;
&lt;br /&gt;
You'll need Microsoft SQL Server Management Studio Express - see [[Preparing_a_dialog_for_recording | Preparing a dialog for recording&lt;br /&gt;
]].&lt;br /&gt;
&lt;br /&gt;
Enter the following query:&lt;br /&gt;
&lt;br /&gt;
   SELECT [bw_dragonage_content].[dbo].[t_Module].Name, [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].Name &lt;br /&gt;
     FROM   [bw_dragonage_content].[dbo].[t_Module], [bw_dragonage_content].[dbo].[t_ModuleResRefVersion], &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_Script] &lt;br /&gt;
     WHERE  [bw_dragonage_content].[dbo].[t_Module].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ModuleID&lt;br /&gt;
     AND    [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_Script].ModuleResRefVersionID&lt;br /&gt;
     AND Text LIKE '%######%'&lt;br /&gt;
     ORDER BY 1, 2; &lt;br /&gt;
&lt;br /&gt;
where ###### is the string you want to find.&lt;br /&gt;
&lt;br /&gt;
This will list the name of every script that contains the string ######.&lt;br /&gt;
&lt;br /&gt;
There will be duplicates if the data base contains multiple versions of a script (maybe an SQL programmer can improve the query to eliminate this, but it's no big deal).&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripts]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16056</id>
		<title>Scripting overview</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16056"/>
				<updated>2011-04-05T11:32:04Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Searching Scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox script}}&lt;br /&gt;
&lt;br /&gt;
Scripting is used whenever the designers need control over the game's behaviour. The syntax for DA scripts is very similar to the C programming language. &lt;br /&gt;
&lt;br /&gt;
Detailed documentation for the scripting language can be found in the &amp;quot;dascript.chm&amp;quot; file, available in your &amp;quot;Dragon Age\packages\core&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
The main uses for it are to: &lt;br /&gt;
&lt;br /&gt;
*Trigger plot events &lt;br /&gt;
*Script conversation &lt;br /&gt;
*Handle creature and party member [[AI]]&lt;br /&gt;
*Script abilities - skills, talents, and spells &lt;br /&gt;
&lt;br /&gt;
DA also has a client-side scripting language whose primary responsibility is automated testing of the game. See [[client script]]s for more details.&lt;br /&gt;
&lt;br /&gt;
AI Scripts are event based. Objects will have only one event-handling script assigned to them that will be run whenever they receive a game event. This script will receive the event type as a parameter and will need to determine the appropriate response for itself.&lt;br /&gt;
&lt;br /&gt;
There are several file extensions associated with scripts:&lt;br /&gt;
* NSS - script source file&lt;br /&gt;
* NCS - compiled script&lt;br /&gt;
* NDB - debug information file (required for using the script debugger to trace through this file)&lt;br /&gt;
&lt;br /&gt;
== Script editor ==&lt;br /&gt;
&lt;br /&gt;
Scripts are created in the Designer Toolset using the Script Editor. Once created, scripts must be assigned to such things as Creatures before they can be used. Once assigned, both the referencing object and the script must be exported in order to be viewed in the game. Exporting happens automatically or can be done manually by the designer during testing. &lt;br /&gt;
&lt;br /&gt;
The script editor supports the following features: &lt;br /&gt;
&lt;br /&gt;
*Undo and redo &lt;br /&gt;
*Find and replace &lt;br /&gt;
*Bookmarking: View -&amp;gt; Other Windows -&amp;gt; Bookmarks&lt;br /&gt;
*Function, variable, constant, and template browser (visible on the right-hand side of the screen).&lt;br /&gt;
*Auto-complete when typing function and variable names &lt;br /&gt;
*Syntax highlighting &lt;br /&gt;
*Auto-indention &lt;br /&gt;
*Brace matching/highlighting &lt;br /&gt;
*Ability to test compile a script &lt;br /&gt;
*Jump to definition&lt;br /&gt;
&lt;br /&gt;
To the right of the script editor is a sidebar with a browser that can display all currently-defined functions, variables, or constants, or a set of 'template' scripts that can serve as a starting point when writing a script from scratch. The browser also has a filter field where you can type in a partial string and have the list automatically exclude everything that doesn't include it in the name.&lt;br /&gt;
&lt;br /&gt;
This is the constant browser:&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser.png]]&lt;br /&gt;
&lt;br /&gt;
Here it is with &amp;quot;team&amp;quot; typed into the filter field, displaying only constants with names that contain the substring &amp;quot;team&amp;quot; (not case sensitive):&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser filtered.png]]&lt;br /&gt;
&lt;br /&gt;
The templates that come with Dragon Age include frameworks for the most common event scripts found in the game. You can add your own templates quite easily, just create a text file with the template code in it and place it in the Dragon Age\Toolset\scripttemplates directory with the others.&lt;br /&gt;
&lt;br /&gt;
[[Image:scripting template browser.png]]&lt;br /&gt;
&lt;br /&gt;
Dragon Age's toolset supports Doxygen-style comments. If you double-click on a function name a help window will pop open to display its documentation. You can also jump to a function's definition (provided it isn't an engine-defined function in script.ldf) by right-clicking on it and selecting &amp;quot;go to definition&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting help window.png]]&lt;br /&gt;
&lt;br /&gt;
== Writing scripts ==&lt;br /&gt;
&lt;br /&gt;
For a script to compile, it needs a body:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The parameters on this can't be changed or the script won't compile.&lt;br /&gt;
&lt;br /&gt;
Scripts associated with a dialog node take this alternate form:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Including files ===&lt;br /&gt;
Other script files can be included by using the #include directive. &lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;rules_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    DoSomethingOrOther();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The included file is '''inserted''' into the main file before the script is compiled. Any number of files can be included.&lt;br /&gt;
'''Important:''' this means that whenever you change an &amp;quot;include file&amp;quot; you must export all script that include it before they will use the new version!&lt;br /&gt;
&lt;br /&gt;
No other C-style preprocessor commands are supported.&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
The scripting language supports the following operators:&lt;br /&gt;
&lt;br /&gt;
====Arithmetic Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Prefix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while ( ++a &amp;lt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt; for (i = 0; i &amp;lt; 10; i++) { } &amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by addition&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a += b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Subtraction (difference)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a - b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Addition (sum)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a + b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Prefix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (--a &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (a-- &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by subtraction&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a -= b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Multiplication (product)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a * b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Division (quotient)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a / b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Modulo (remainder)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a % b == 1) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Comparison Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Less than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Less than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Not Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a != b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a == b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Logical Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Logical negation (NOT)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (!a) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical AND&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;amp;&amp;amp; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical OR&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a || b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Other Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Basic assignment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a = b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Function call&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a();&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Array subscript&lt;br /&gt;
| &amp;lt;dascript&amp;gt;array[0] = 1;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Member (on structures)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;structure.member = 0;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Ternary conditional&lt;br /&gt;
| &amp;lt;dascript&amp;gt;return a &amp;lt; b ? c : d;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Types &amp;amp; Variable  ===&lt;br /&gt;
&lt;br /&gt;
The scripting language natively supports:&lt;br /&gt;
* [[float]] - floating-point numbers. &amp;lt;dascript&amp;gt;float fFloat = 0.1234f;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[int]] - integer numbers. &amp;lt;dascript&amp;gt;int nInteger = 1234;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[object]] -game object files. &amp;lt;dascript&amp;gt;object oObject = GetObjectByTag(&amp;quot;monster_001&amp;quot;);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[resource]] - game resource files. &amp;lt;dascript&amp;gt;resource rGameIntroCutscene = R&amp;quot;game_intro_.cut&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[string]] - text strings. &amp;lt;dascript&amp;gt;string sString = &amp;quot;Hello World!&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[vector]] - positions or directions. &amp;lt;dascript&amp;gt;vector vVector = Vector(0.0, 1.1, 2.2);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server language has been expanded to support these engine defined structures:&lt;br /&gt;
* [[Event (dascript type)|event]] - events are signals that are sent to scripts by other scripts or by the world engine.&lt;br /&gt;
* [[location]]&lt;br /&gt;
* [[command]] - a command for a creature or object to do something. Commands are constructed using functions that return them, and then are added to a target's command queue with the AddCommand function.&lt;br /&gt;
* [[effect]]&lt;br /&gt;
* [[itemproperty]]&lt;br /&gt;
* [[player]]&lt;br /&gt;
&lt;br /&gt;
All of these types are always passed by value, which means a new copy is made whenever they are passed into a function or copied to another variable.&lt;br /&gt;
&lt;br /&gt;
This means that most functions that are supposed to modify a structure in some way need to return the modified one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    effect e1 = Effect(100);&lt;br /&gt;
    effect e2 = SetEffectType(e1, 101); // e1 != e2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Structures ====&lt;br /&gt;
&lt;br /&gt;
Users can define their own structures using the [[struct]] keyword:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// user-defined type&lt;br /&gt;
struct quaternion&lt;br /&gt;
{&lt;br /&gt;
    float w, x, y, z;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// constructor&lt;br /&gt;
struct quaternion Quaternion(float fW, float fX, float fY, float fZ)&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q;&lt;br /&gt;
&lt;br /&gt;
    q.w = fW;&lt;br /&gt;
    q.x = fX;&lt;br /&gt;
    q.y = fY;&lt;br /&gt;
    q.z = fZ;&lt;br /&gt;
&lt;br /&gt;
    return q;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q = Quaternion(0.0, 0.0, 0.0, 0.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
Variables can be declared as arrays for any type except user-defined structs. Designers can create their own arrays of any major data type (int, string, object). Many functions will also return arrays (for example, creatures in an area will be returned as an array, and the action queue will be returned as an array).&lt;br /&gt;
&lt;br /&gt;
These are different from C-style arrays in that they can be resized like STL vectors, and their notation is slightly different.&lt;br /&gt;
&lt;br /&gt;
Arrays also behave differently from other objects in the scripting language because they are passed by reference.  If an array is passed into a function and modified:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    int[] i;                 // new array of integers with a size of zero &lt;br /&gt;
    i[0] = 5;                // value of array position 0 is now 5&lt;br /&gt;
    i[1] = -1;               // value of array position 1 is now -1&lt;br /&gt;
&lt;br /&gt;
    int[] j = i;             // i and j point to the same array&lt;br /&gt;
    j[1] = 12;               // value of array position 1 for both i and j is now 12!&lt;br /&gt;
&lt;br /&gt;
    SortArrayDescending(i);  // i and j are both sorted now, this function has no return value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[GetArraySize]] returns the size of an array.&lt;br /&gt;
&lt;br /&gt;
==== Local Variables ====&lt;br /&gt;
&lt;br /&gt;
In Neverwinter Nights, variables for various objects could be created and set with functions such as SetLocalInt(). Dragon Age does not have analogous functions. Instead, all of the variables that a given object is able to have values assigned to must be defined ahead of time in a 2DA. This more restrictive approach is intended to improve performance and reduce the opportunity for errors (for example, making a typo in the name of a variable and losing track of it as a result).&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to discover a function and what it does.&lt;br /&gt;
&lt;br /&gt;
If you type in the name of a function that's been defined and then an opening bracket, a tooltip will pop up showing the function's parameter types and return type.&lt;br /&gt;
&lt;br /&gt;
Alternately, if you have the help window open (View -&amp;gt; Other Windows -&amp;gt; Help Window), then whenever you select a function in the function browser a help page describing the function will be displayed.&lt;br /&gt;
&lt;br /&gt;
=== Passing parameters to scripts ===&lt;br /&gt;
&lt;br /&gt;
To pass parameters to scripts they must be called with the 'runscript' command. This can be useful for writing debug scripts or changing actions based on input. To accept parameters simply add this line to your script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
string sParams = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then type 'runscript scriptname parameter1 parameter2 ... paramaterN' to pass parameters.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: heals the object with the given tag. If tag is invalid, nothing happens&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sTag = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    object oCreature = GetObjectByTag(sTag);&lt;br /&gt;
    effect   eHeal = EffectHeal(25.0f)&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: applies the visual effect passed in as parameter to the player&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sEffect = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    int    nEffect = StringToInt(sEffect);&lt;br /&gt;
    effect eVfx = EffectVisualEffect(nEffect);&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error messages and logging ===&lt;br /&gt;
&lt;br /&gt;
See [[Script error]] for details of how to correct errors in scripts.&lt;br /&gt;
&lt;br /&gt;
To enable script logging, edit or create &amp;lt;DragonAgeInstallDirectory&amp;gt;\bin_ship\[[ECLog.ini]] and set Script=1 in the [LogTypes] section.&lt;br /&gt;
&lt;br /&gt;
The [[PrintToLog]] function prints messages to the log file once logging is enabled.&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
&lt;br /&gt;
Commands, delayed events and object destruction all take place after the current script is finished running. Plot flags set in script are set in-line but the triggered plot script runs before the flag is actually set (this is clarified a bit in the plot script template).&lt;br /&gt;
&lt;br /&gt;
Given that ExecuteScript is deprecated, HandleEvent should be used when you want the script to run in-line and DelayEvent should be used when you want to delay execution.&lt;br /&gt;
&lt;br /&gt;
To delay execution when dealing with creatures, custom AI and (safe) command complete are nice tools. DelayEvent should be used whenever you know how long you want to wait before the event fires. (It can also be used in quite small time increments to give the illusion of smoothly sliding placeables with SetPosition or interpolate between two different atmosphere/lighting settings, but the overhead of this is noticeable if overused).&lt;br /&gt;
&lt;br /&gt;
== Searching Scripts ==&lt;br /&gt;
&lt;br /&gt;
To find examples of how Bioware does things, or simply to discover where a function or variable is used, it's useful to be able to search all the scripts in the data base for a string.&lt;br /&gt;
&lt;br /&gt;
You'll need Microsoft SQL Server Management Studio Express - see [[Preparing_a_dialog_for_recording]].&lt;br /&gt;
&lt;br /&gt;
Enter the following query:&lt;br /&gt;
&lt;br /&gt;
   SELECT [bw_dragonage_content].[dbo].[t_Module].Name, [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].Name &lt;br /&gt;
     FROM   [bw_dragonage_content].[dbo].[t_Module], [bw_dragonage_content].[dbo].[t_ModuleResRefVersion], &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_Script] &lt;br /&gt;
     WHERE  [bw_dragonage_content].[dbo].[t_Module].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ModuleID&lt;br /&gt;
     AND    [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_Script].ModuleResRefVersionID&lt;br /&gt;
     AND Text LIKE '%######%'&lt;br /&gt;
     ORDER BY 1, 2; &lt;br /&gt;
&lt;br /&gt;
where ###### is the string you want to find.&lt;br /&gt;
&lt;br /&gt;
This will list the name of every script that contains the string ######.&lt;br /&gt;
&lt;br /&gt;
There will be duplicates if the data base contains multiple versions of a script (maybe an SQL programmer can improve the query to eliminate this, but it's no big deal).&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripts]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16055</id>
		<title>Scripting overview</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16055"/>
				<updated>2011-04-05T11:30:58Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox script}}&lt;br /&gt;
&lt;br /&gt;
Scripting is used whenever the designers need control over the game's behaviour. The syntax for DA scripts is very similar to the C programming language. &lt;br /&gt;
&lt;br /&gt;
Detailed documentation for the scripting language can be found in the &amp;quot;dascript.chm&amp;quot; file, available in your &amp;quot;Dragon Age\packages\core&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
The main uses for it are to: &lt;br /&gt;
&lt;br /&gt;
*Trigger plot events &lt;br /&gt;
*Script conversation &lt;br /&gt;
*Handle creature and party member [[AI]]&lt;br /&gt;
*Script abilities - skills, talents, and spells &lt;br /&gt;
&lt;br /&gt;
DA also has a client-side scripting language whose primary responsibility is automated testing of the game. See [[client script]]s for more details.&lt;br /&gt;
&lt;br /&gt;
AI Scripts are event based. Objects will have only one event-handling script assigned to them that will be run whenever they receive a game event. This script will receive the event type as a parameter and will need to determine the appropriate response for itself.&lt;br /&gt;
&lt;br /&gt;
There are several file extensions associated with scripts:&lt;br /&gt;
* NSS - script source file&lt;br /&gt;
* NCS - compiled script&lt;br /&gt;
* NDB - debug information file (required for using the script debugger to trace through this file)&lt;br /&gt;
&lt;br /&gt;
== Script editor ==&lt;br /&gt;
&lt;br /&gt;
Scripts are created in the Designer Toolset using the Script Editor. Once created, scripts must be assigned to such things as Creatures before they can be used. Once assigned, both the referencing object and the script must be exported in order to be viewed in the game. Exporting happens automatically or can be done manually by the designer during testing. &lt;br /&gt;
&lt;br /&gt;
The script editor supports the following features: &lt;br /&gt;
&lt;br /&gt;
*Undo and redo &lt;br /&gt;
*Find and replace &lt;br /&gt;
*Bookmarking: View -&amp;gt; Other Windows -&amp;gt; Bookmarks&lt;br /&gt;
*Function, variable, constant, and template browser (visible on the right-hand side of the screen).&lt;br /&gt;
*Auto-complete when typing function and variable names &lt;br /&gt;
*Syntax highlighting &lt;br /&gt;
*Auto-indention &lt;br /&gt;
*Brace matching/highlighting &lt;br /&gt;
*Ability to test compile a script &lt;br /&gt;
*Jump to definition&lt;br /&gt;
&lt;br /&gt;
To the right of the script editor is a sidebar with a browser that can display all currently-defined functions, variables, or constants, or a set of 'template' scripts that can serve as a starting point when writing a script from scratch. The browser also has a filter field where you can type in a partial string and have the list automatically exclude everything that doesn't include it in the name.&lt;br /&gt;
&lt;br /&gt;
This is the constant browser:&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser.png]]&lt;br /&gt;
&lt;br /&gt;
Here it is with &amp;quot;team&amp;quot; typed into the filter field, displaying only constants with names that contain the substring &amp;quot;team&amp;quot; (not case sensitive):&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser filtered.png]]&lt;br /&gt;
&lt;br /&gt;
The templates that come with Dragon Age include frameworks for the most common event scripts found in the game. You can add your own templates quite easily, just create a text file with the template code in it and place it in the Dragon Age\Toolset\scripttemplates directory with the others.&lt;br /&gt;
&lt;br /&gt;
[[Image:scripting template browser.png]]&lt;br /&gt;
&lt;br /&gt;
Dragon Age's toolset supports Doxygen-style comments. If you double-click on a function name a help window will pop open to display its documentation. You can also jump to a function's definition (provided it isn't an engine-defined function in script.ldf) by right-clicking on it and selecting &amp;quot;go to definition&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting help window.png]]&lt;br /&gt;
&lt;br /&gt;
== Writing scripts ==&lt;br /&gt;
&lt;br /&gt;
For a script to compile, it needs a body:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The parameters on this can't be changed or the script won't compile.&lt;br /&gt;
&lt;br /&gt;
Scripts associated with a dialog node take this alternate form:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Including files ===&lt;br /&gt;
Other script files can be included by using the #include directive. &lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;rules_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    DoSomethingOrOther();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The included file is '''inserted''' into the main file before the script is compiled. Any number of files can be included.&lt;br /&gt;
'''Important:''' this means that whenever you change an &amp;quot;include file&amp;quot; you must export all script that include it before they will use the new version!&lt;br /&gt;
&lt;br /&gt;
No other C-style preprocessor commands are supported.&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
The scripting language supports the following operators:&lt;br /&gt;
&lt;br /&gt;
====Arithmetic Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Prefix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while ( ++a &amp;lt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt; for (i = 0; i &amp;lt; 10; i++) { } &amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by addition&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a += b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Subtraction (difference)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a - b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Addition (sum)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a + b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Prefix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (--a &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (a-- &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by subtraction&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a -= b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Multiplication (product)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a * b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Division (quotient)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a / b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Modulo (remainder)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a % b == 1) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Comparison Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Less than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Less than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Not Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a != b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a == b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Logical Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Logical negation (NOT)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (!a) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical AND&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;amp;&amp;amp; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical OR&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a || b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Other Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Basic assignment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a = b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Function call&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a();&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Array subscript&lt;br /&gt;
| &amp;lt;dascript&amp;gt;array[0] = 1;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Member (on structures)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;structure.member = 0;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Ternary conditional&lt;br /&gt;
| &amp;lt;dascript&amp;gt;return a &amp;lt; b ? c : d;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Types &amp;amp; Variable  ===&lt;br /&gt;
&lt;br /&gt;
The scripting language natively supports:&lt;br /&gt;
* [[float]] - floating-point numbers. &amp;lt;dascript&amp;gt;float fFloat = 0.1234f;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[int]] - integer numbers. &amp;lt;dascript&amp;gt;int nInteger = 1234;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[object]] -game object files. &amp;lt;dascript&amp;gt;object oObject = GetObjectByTag(&amp;quot;monster_001&amp;quot;);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[resource]] - game resource files. &amp;lt;dascript&amp;gt;resource rGameIntroCutscene = R&amp;quot;game_intro_.cut&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[string]] - text strings. &amp;lt;dascript&amp;gt;string sString = &amp;quot;Hello World!&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[vector]] - positions or directions. &amp;lt;dascript&amp;gt;vector vVector = Vector(0.0, 1.1, 2.2);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server language has been expanded to support these engine defined structures:&lt;br /&gt;
* [[Event (dascript type)|event]] - events are signals that are sent to scripts by other scripts or by the world engine.&lt;br /&gt;
* [[location]]&lt;br /&gt;
* [[command]] - a command for a creature or object to do something. Commands are constructed using functions that return them, and then are added to a target's command queue with the AddCommand function.&lt;br /&gt;
* [[effect]]&lt;br /&gt;
* [[itemproperty]]&lt;br /&gt;
* [[player]]&lt;br /&gt;
&lt;br /&gt;
All of these types are always passed by value, which means a new copy is made whenever they are passed into a function or copied to another variable.&lt;br /&gt;
&lt;br /&gt;
This means that most functions that are supposed to modify a structure in some way need to return the modified one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    effect e1 = Effect(100);&lt;br /&gt;
    effect e2 = SetEffectType(e1, 101); // e1 != e2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Structures ====&lt;br /&gt;
&lt;br /&gt;
Users can define their own structures using the [[struct]] keyword:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// user-defined type&lt;br /&gt;
struct quaternion&lt;br /&gt;
{&lt;br /&gt;
    float w, x, y, z;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// constructor&lt;br /&gt;
struct quaternion Quaternion(float fW, float fX, float fY, float fZ)&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q;&lt;br /&gt;
&lt;br /&gt;
    q.w = fW;&lt;br /&gt;
    q.x = fX;&lt;br /&gt;
    q.y = fY;&lt;br /&gt;
    q.z = fZ;&lt;br /&gt;
&lt;br /&gt;
    return q;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q = Quaternion(0.0, 0.0, 0.0, 0.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
Variables can be declared as arrays for any type except user-defined structs. Designers can create their own arrays of any major data type (int, string, object). Many functions will also return arrays (for example, creatures in an area will be returned as an array, and the action queue will be returned as an array).&lt;br /&gt;
&lt;br /&gt;
These are different from C-style arrays in that they can be resized like STL vectors, and their notation is slightly different.&lt;br /&gt;
&lt;br /&gt;
Arrays also behave differently from other objects in the scripting language because they are passed by reference.  If an array is passed into a function and modified:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    int[] i;                 // new array of integers with a size of zero &lt;br /&gt;
    i[0] = 5;                // value of array position 0 is now 5&lt;br /&gt;
    i[1] = -1;               // value of array position 1 is now -1&lt;br /&gt;
&lt;br /&gt;
    int[] j = i;             // i and j point to the same array&lt;br /&gt;
    j[1] = 12;               // value of array position 1 for both i and j is now 12!&lt;br /&gt;
&lt;br /&gt;
    SortArrayDescending(i);  // i and j are both sorted now, this function has no return value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[GetArraySize]] returns the size of an array.&lt;br /&gt;
&lt;br /&gt;
==== Local Variables ====&lt;br /&gt;
&lt;br /&gt;
In Neverwinter Nights, variables for various objects could be created and set with functions such as SetLocalInt(). Dragon Age does not have analogous functions. Instead, all of the variables that a given object is able to have values assigned to must be defined ahead of time in a 2DA. This more restrictive approach is intended to improve performance and reduce the opportunity for errors (for example, making a typo in the name of a variable and losing track of it as a result).&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to discover a function and what it does.&lt;br /&gt;
&lt;br /&gt;
If you type in the name of a function that's been defined and then an opening bracket, a tooltip will pop up showing the function's parameter types and return type.&lt;br /&gt;
&lt;br /&gt;
Alternately, if you have the help window open (View -&amp;gt; Other Windows -&amp;gt; Help Window), then whenever you select a function in the function browser a help page describing the function will be displayed.&lt;br /&gt;
&lt;br /&gt;
=== Passing parameters to scripts ===&lt;br /&gt;
&lt;br /&gt;
To pass parameters to scripts they must be called with the 'runscript' command. This can be useful for writing debug scripts or changing actions based on input. To accept parameters simply add this line to your script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
string sParams = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then type 'runscript scriptname parameter1 parameter2 ... paramaterN' to pass parameters.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: heals the object with the given tag. If tag is invalid, nothing happens&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sTag = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    object oCreature = GetObjectByTag(sTag);&lt;br /&gt;
    effect   eHeal = EffectHeal(25.0f)&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: applies the visual effect passed in as parameter to the player&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sEffect = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    int    nEffect = StringToInt(sEffect);&lt;br /&gt;
    effect eVfx = EffectVisualEffect(nEffect);&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error messages and logging ===&lt;br /&gt;
&lt;br /&gt;
See [[Script error]] for details of how to correct errors in scripts.&lt;br /&gt;
&lt;br /&gt;
To enable script logging, edit or create &amp;lt;DragonAgeInstallDirectory&amp;gt;\bin_ship\[[ECLog.ini]] and set Script=1 in the [LogTypes] section.&lt;br /&gt;
&lt;br /&gt;
The [[PrintToLog]] function prints messages to the log file once logging is enabled.&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
&lt;br /&gt;
Commands, delayed events and object destruction all take place after the current script is finished running. Plot flags set in script are set in-line but the triggered plot script runs before the flag is actually set (this is clarified a bit in the plot script template).&lt;br /&gt;
&lt;br /&gt;
Given that ExecuteScript is deprecated, HandleEvent should be used when you want the script to run in-line and DelayEvent should be used when you want to delay execution.&lt;br /&gt;
&lt;br /&gt;
To delay execution when dealing with creatures, custom AI and (safe) command complete are nice tools. DelayEvent should be used whenever you know how long you want to wait before the event fires. (It can also be used in quite small time increments to give the illusion of smoothly sliding placeables with SetPosition or interpolate between two different atmosphere/lighting settings, but the overhead of this is noticeable if overused).&lt;br /&gt;
&lt;br /&gt;
== Searching Scripts ==&lt;br /&gt;
&lt;br /&gt;
To find examples of how Bioware does things, or simply to discover where a function or variable is used, it's useful to be able to search all the scripts in the data base for a string.&lt;br /&gt;
&lt;br /&gt;
You'll need [[Preparing_a_dialog_for_recording | Microsoft SQL Server Management Studio Express]] for this.&lt;br /&gt;
&lt;br /&gt;
Enter the following query:&lt;br /&gt;
&lt;br /&gt;
   SELECT [bw_dragonage_content].[dbo].[t_Module].Name, [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].Name &lt;br /&gt;
     FROM   [bw_dragonage_content].[dbo].[t_Module], [bw_dragonage_content].[dbo].[t_ModuleResRefVersion], &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_Script] &lt;br /&gt;
     WHERE  [bw_dragonage_content].[dbo].[t_Module].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ModuleID&lt;br /&gt;
     AND    [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_Script].ModuleResRefVersionID&lt;br /&gt;
     AND Text LIKE '%######%'&lt;br /&gt;
     ORDER BY 1, 2; &lt;br /&gt;
&lt;br /&gt;
where ###### is the string you want to find.&lt;br /&gt;
&lt;br /&gt;
This will list the name of every script that contains the string ######.&lt;br /&gt;
&lt;br /&gt;
There will be duplicates if the data base contains multiple versions of a script (maybe an SQL programmer can improve the query to eliminate this, but it's no big deal).&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripts]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	<entry>
		<id>http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16054</id>
		<title>Scripting overview</title>
		<link rel="alternate" type="text/html" href="http://www.datoolset.net/mw/index.php?title=Scripting_overview&amp;diff=16054"/>
				<updated>2011-04-05T11:30:12Z</updated>
		
		<summary type="html">&lt;p&gt;Proleric1: /* Timing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox script}}&lt;br /&gt;
&lt;br /&gt;
Scripting is used whenever the designers need control over the game's behaviour. The syntax for DA scripts is very similar to the C programming language. &lt;br /&gt;
&lt;br /&gt;
Detailed documentation for the scripting language can be found in the &amp;quot;dascript.chm&amp;quot; file, available in your &amp;quot;Dragon Age\packages\core&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
The main uses for it are to: &lt;br /&gt;
&lt;br /&gt;
*Trigger plot events &lt;br /&gt;
*Script conversation &lt;br /&gt;
*Handle creature and party member [[AI]]&lt;br /&gt;
*Script abilities - skills, talents, and spells &lt;br /&gt;
&lt;br /&gt;
DA also has a client-side scripting language whose primary responsibility is automated testing of the game. See [[client script]]s for more details.&lt;br /&gt;
&lt;br /&gt;
AI Scripts are event based. Objects will have only one event-handling script assigned to them that will be run whenever they receive a game event. This script will receive the event type as a parameter and will need to determine the appropriate response for itself.&lt;br /&gt;
&lt;br /&gt;
There are several file extensions associated with scripts:&lt;br /&gt;
* NSS - script source file&lt;br /&gt;
* NCS - compiled script&lt;br /&gt;
* NDB - debug information file (required for using the script debugger to trace through this file)&lt;br /&gt;
&lt;br /&gt;
== Script editor ==&lt;br /&gt;
&lt;br /&gt;
Scripts are created in the Designer Toolset using the Script Editor. Once created, scripts must be assigned to such things as Creatures before they can be used. Once assigned, both the referencing object and the script must be exported in order to be viewed in the game. Exporting happens automatically or can be done manually by the designer during testing. &lt;br /&gt;
&lt;br /&gt;
The script editor supports the following features: &lt;br /&gt;
&lt;br /&gt;
*Undo and redo &lt;br /&gt;
*Find and replace &lt;br /&gt;
*Bookmarking: View -&amp;gt; Other Windows -&amp;gt; Bookmarks&lt;br /&gt;
*Function, variable, constant, and template browser (visible on the right-hand side of the screen).&lt;br /&gt;
*Auto-complete when typing function and variable names &lt;br /&gt;
*Syntax highlighting &lt;br /&gt;
*Auto-indention &lt;br /&gt;
*Brace matching/highlighting &lt;br /&gt;
*Ability to test compile a script &lt;br /&gt;
*Jump to definition&lt;br /&gt;
&lt;br /&gt;
To the right of the script editor is a sidebar with a browser that can display all currently-defined functions, variables, or constants, or a set of 'template' scripts that can serve as a starting point when writing a script from scratch. The browser also has a filter field where you can type in a partial string and have the list automatically exclude everything that doesn't include it in the name.&lt;br /&gt;
&lt;br /&gt;
This is the constant browser:&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser.png]]&lt;br /&gt;
&lt;br /&gt;
Here it is with &amp;quot;team&amp;quot; typed into the filter field, displaying only constants with names that contain the substring &amp;quot;team&amp;quot; (not case sensitive):&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting constant browser filtered.png]]&lt;br /&gt;
&lt;br /&gt;
The templates that come with Dragon Age include frameworks for the most common event scripts found in the game. You can add your own templates quite easily, just create a text file with the template code in it and place it in the Dragon Age\Toolset\scripttemplates directory with the others.&lt;br /&gt;
&lt;br /&gt;
[[Image:scripting template browser.png]]&lt;br /&gt;
&lt;br /&gt;
Dragon Age's toolset supports Doxygen-style comments. If you double-click on a function name a help window will pop open to display its documentation. You can also jump to a function's definition (provided it isn't an engine-defined function in script.ldf) by right-clicking on it and selecting &amp;quot;go to definition&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Image:Scripting help window.png]]&lt;br /&gt;
&lt;br /&gt;
== Writing scripts ==&lt;br /&gt;
&lt;br /&gt;
For a script to compile, it needs a body:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The parameters on this can't be changed or the script won't compile.&lt;br /&gt;
&lt;br /&gt;
Scripts associated with a dialog node take this alternate form:&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
int StartingConditional()&lt;br /&gt;
{&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Including files ===&lt;br /&gt;
Other script files can be included by using the #include directive. &lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
#include &amp;quot;rules_h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    DoSomethingOrOther();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
The included file is '''inserted''' into the main file before the script is compiled. Any number of files can be included.&lt;br /&gt;
'''Important:''' this means that whenever you change an &amp;quot;include file&amp;quot; you must export all script that include it before they will use the new version!&lt;br /&gt;
&lt;br /&gt;
No other C-style preprocessor commands are supported.&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
The scripting language supports the following operators:&lt;br /&gt;
&lt;br /&gt;
====Arithmetic Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Prefix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while ( ++a &amp;lt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix Increment&lt;br /&gt;
| &amp;lt;dascript&amp;gt; for (i = 0; i &amp;lt; 10; i++) { } &amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by addition&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a += b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Subtraction (difference)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a - b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Addition (sum)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a + b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Prefix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (--a &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Postfix decrement&lt;br /&gt;
| &amp;lt;dascript&amp;gt;while (a-- &amp;gt; 10) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Assignment by subtraction&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a -= b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Multiplication (product)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a * b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Division (quotient)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;x = a / b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Modulo (remainder)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a % b == 1) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Comparison Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Less than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Less than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;lt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Greater than or equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;gt;= b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Not Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a != b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Equal to&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a == b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Logical Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Logical negation (NOT)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (!a) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical AND&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a &amp;amp;&amp;amp; b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Logical OR&lt;br /&gt;
| &amp;lt;dascript&amp;gt;if (a || b) { }&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Other Operators====&lt;br /&gt;
{|style=&amp;quot;width:100%;border:solid 1px black;&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%;background-color:#ffffcc;&amp;quot; | Operator Name&lt;br /&gt;
! style=&amp;quot;width:75%;background-color:#ffffcc;&amp;quot; | Example&lt;br /&gt;
|-&lt;br /&gt;
| Basic assignment&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a = b;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Function call&lt;br /&gt;
| &amp;lt;dascript&amp;gt;a();&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Array subscript&lt;br /&gt;
| &amp;lt;dascript&amp;gt;array[0] = 1;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Member (on structures)&lt;br /&gt;
| &amp;lt;dascript&amp;gt;structure.member = 0;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Ternary conditional&lt;br /&gt;
| &amp;lt;dascript&amp;gt;return a &amp;lt; b ? c : d;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Types &amp;amp; Variable  ===&lt;br /&gt;
&lt;br /&gt;
The scripting language natively supports:&lt;br /&gt;
* [[float]] - floating-point numbers. &amp;lt;dascript&amp;gt;float fFloat = 0.1234f;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[int]] - integer numbers. &amp;lt;dascript&amp;gt;int nInteger = 1234;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[object]] -game object files. &amp;lt;dascript&amp;gt;object oObject = GetObjectByTag(&amp;quot;monster_001&amp;quot;);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[resource]] - game resource files. &amp;lt;dascript&amp;gt;resource rGameIntroCutscene = R&amp;quot;game_intro_.cut&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[string]] - text strings. &amp;lt;dascript&amp;gt;string sString = &amp;quot;Hello World!&amp;quot;;&amp;lt;/dascript&amp;gt;&lt;br /&gt;
* [[vector]] - positions or directions. &amp;lt;dascript&amp;gt;vector vVector = Vector(0.0, 1.1, 2.2);&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server language has been expanded to support these engine defined structures:&lt;br /&gt;
* [[Event (dascript type)|event]] - events are signals that are sent to scripts by other scripts or by the world engine.&lt;br /&gt;
* [[location]]&lt;br /&gt;
* [[command]] - a command for a creature or object to do something. Commands are constructed using functions that return them, and then are added to a target's command queue with the AddCommand function.&lt;br /&gt;
* [[effect]]&lt;br /&gt;
* [[itemproperty]]&lt;br /&gt;
* [[player]]&lt;br /&gt;
&lt;br /&gt;
All of these types are always passed by value, which means a new copy is made whenever they are passed into a function or copied to another variable.&lt;br /&gt;
&lt;br /&gt;
This means that most functions that are supposed to modify a structure in some way need to return the modified one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    effect e1 = Effect(100);&lt;br /&gt;
    effect e2 = SetEffectType(e1, 101); // e1 != e2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Structures ====&lt;br /&gt;
&lt;br /&gt;
Users can define their own structures using the [[struct]] keyword:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
// user-defined type&lt;br /&gt;
struct quaternion&lt;br /&gt;
{&lt;br /&gt;
    float w, x, y, z;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// constructor&lt;br /&gt;
struct quaternion Quaternion(float fW, float fX, float fY, float fZ)&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q;&lt;br /&gt;
&lt;br /&gt;
    q.w = fW;&lt;br /&gt;
    q.x = fX;&lt;br /&gt;
    q.y = fY;&lt;br /&gt;
    q.z = fZ;&lt;br /&gt;
&lt;br /&gt;
    return q;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    struct quaternion q = Quaternion(0.0, 0.0, 0.0, 0.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
Variables can be declared as arrays for any type except user-defined structs. Designers can create their own arrays of any major data type (int, string, object). Many functions will also return arrays (for example, creatures in an area will be returned as an array, and the action queue will be returned as an array).&lt;br /&gt;
&lt;br /&gt;
These are different from C-style arrays in that they can be resized like STL vectors, and their notation is slightly different.&lt;br /&gt;
&lt;br /&gt;
Arrays also behave differently from other objects in the scripting language because they are passed by reference.  If an array is passed into a function and modified:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
    int[] i;                 // new array of integers with a size of zero &lt;br /&gt;
    i[0] = 5;                // value of array position 0 is now 5&lt;br /&gt;
    i[1] = -1;               // value of array position 1 is now -1&lt;br /&gt;
&lt;br /&gt;
    int[] j = i;             // i and j point to the same array&lt;br /&gt;
    j[1] = 12;               // value of array position 1 for both i and j is now 12!&lt;br /&gt;
&lt;br /&gt;
    SortArrayDescending(i);  // i and j are both sorted now, this function has no return value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[GetArraySize]] returns the size of an array.&lt;br /&gt;
&lt;br /&gt;
==== Local Variables ====&lt;br /&gt;
&lt;br /&gt;
In Neverwinter Nights, variables for various objects could be created and set with functions such as SetLocalInt(). Dragon Age does not have analogous functions. Instead, all of the variables that a given object is able to have values assigned to must be defined ahead of time in a 2DA. This more restrictive approach is intended to improve performance and reduce the opportunity for errors (for example, making a typo in the name of a variable and losing track of it as a result).&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
&lt;br /&gt;
There are two ways to discover a function and what it does.&lt;br /&gt;
&lt;br /&gt;
If you type in the name of a function that's been defined and then an opening bracket, a tooltip will pop up showing the function's parameter types and return type.&lt;br /&gt;
&lt;br /&gt;
Alternately, if you have the help window open (View -&amp;gt; Other Windows -&amp;gt; Help Window), then whenever you select a function in the function browser a help page describing the function will be displayed.&lt;br /&gt;
&lt;br /&gt;
=== Passing parameters to scripts ===&lt;br /&gt;
&lt;br /&gt;
To pass parameters to scripts they must be called with the 'runscript' command. This can be useful for writing debug scripts or changing actions based on input. To accept parameters simply add this line to your script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
string sParams = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then type 'runscript scriptname parameter1 parameter2 ... paramaterN' to pass parameters.&lt;br /&gt;
&lt;br /&gt;
Some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: heals the object with the given tag. If tag is invalid, nothing happens&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sTag = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    object oCreature = GetObjectByTag(sTag);&lt;br /&gt;
    effect   eHeal = EffectHeal(25.0f)&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Debug script: applies the visual effect passed in as parameter to the player&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
 &lt;br /&gt;
    string sEffect = GetLocalString(GetModule(),&amp;quot;RUNSCRIPT_VAR&amp;quot;);    &lt;br /&gt;
    int    nEffect = StringToInt(sEffect);&lt;br /&gt;
    effect eVfx = EffectVisualEffect(nEffect);&lt;br /&gt;
    //ApplyEffect...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error messages and logging ===&lt;br /&gt;
&lt;br /&gt;
See [[Script error]] for details of how to correct errors in scripts.&lt;br /&gt;
&lt;br /&gt;
To enable script logging, edit or create &amp;lt;DragonAgeInstallDirectory&amp;gt;\bin_ship\[[ECLog.ini]] and set Script=1 in the [LogTypes] section.&lt;br /&gt;
&lt;br /&gt;
The [[PrintToLog]] function prints messages to the log file once logging is enabled.&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
&lt;br /&gt;
Commands, delayed events and object destruction all take place after the current script is finished running. Plot flags set in script are set in-line but the triggered plot script runs before the flag is actually set (this is clarified a bit in the plot script template).&lt;br /&gt;
&lt;br /&gt;
Given that ExecuteScript is deprecated, HandleEvent should be used when you want the script to run in-line and DelayEvent should be used when you want to delay execution.&lt;br /&gt;
&lt;br /&gt;
To delay execution when dealing with creatures, custom AI and (safe) command complete are nice tools. DelayEvent should be used whenever you know how long you want to wait before the event fires. (It can also be used in quite small time increments to give the illusion of smoothly sliding placeables with SetPosition or interpolate between two different atmosphere/lighting settings, but the overhead of this is noticeable if overused).&lt;br /&gt;
&lt;br /&gt;
== Searching Scripts ==&lt;br /&gt;
&lt;br /&gt;
To find examples of how Bioware does things, or simply to discover where a function or variable is used, it's useful to be able to search all the scripts in the data base for a string.&lt;br /&gt;
&lt;br /&gt;
You'll need [Preparing_a_dialog_for_recording | Microsoft SQL Server Management Studio Express] for this.&lt;br /&gt;
&lt;br /&gt;
Enter the following query:&lt;br /&gt;
&lt;br /&gt;
   SELECT [bw_dragonage_content].[dbo].[t_Module].Name, [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].Name &lt;br /&gt;
     FROM   [bw_dragonage_content].[dbo].[t_Module], [bw_dragonage_content].[dbo].[t_ModuleResRefVersion], &lt;br /&gt;
            [bw_dragonage_content].[dbo].[t_Script] &lt;br /&gt;
     WHERE  [bw_dragonage_content].[dbo].[t_Module].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ModuleID&lt;br /&gt;
     AND    [bw_dragonage_content].[dbo].[t_ModuleResRefVersion].ID &lt;br /&gt;
            = [bw_dragonage_content].[dbo].[t_Script].ModuleResRefVersionID&lt;br /&gt;
     AND Text LIKE '%######%'&lt;br /&gt;
     ORDER BY 1, 2; &lt;br /&gt;
&lt;br /&gt;
where ###### is the string you want to find.&lt;br /&gt;
&lt;br /&gt;
This will list the name of every script that contains the string ######.&lt;br /&gt;
&lt;br /&gt;
There will be duplicates if the data base contains multiple versions of a script (maybe an SQL programmer can improve the query to eliminate this, but it's no big deal).&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripts]]&lt;br /&gt;
{{Languages}}&lt;/div&gt;</summary>
		<author><name>Proleric1</name></author>	</entry>

	</feed>