User:Satans karma
Noob-Friendly Follower Tutorial:
NOTE: This is a work-in-progress. If you find something amiss, PM me on Bioware (screenname = satans_karma).
Contents
Assumptions:
1) You know how to create a new module. If not, read through the module tutorial first. Making_a_new,_playable_module#Creating_a_Module
2) You know how to create a basic dialogue. If not, read through the conversation tutorial first. Conversation_tutorial
3) You know how to make a creature. If not, read through the creature tutorial first. Creature_tutorial
4) You know how to add waypoints to an area. If not, read through the area tutorial first. Area_tutorial#Setting_the_start_point
5) You know how to create a plot. If not, read through the plot tutorial first. Plot#Journal_entries
6) You know how to create a blank script and can copy-and-paste.
7) You know how to turn an Excel document (.xls extension) into a 2DA file (.gda extension). If not, read through the tutorial on how to compile 2DAs first. Compiling_2DAs
Directions:
1) Create a new module. Make sure that "Extended Module" option in the "Properties" section is set to "Single Player."
2) Create a dialogue that has conversation branches that:
- a. allows you to hire the follower (e.g. "Can I join your party?" --> "Yes" or "No")
- b. allows you to fire the follower (e.g. "I want you to leave")
- c. allows you to back out of the conversation (e.g. "Nevermind. I didn't mean to bother you.")
- d. any other optional dialogue lines
3) Create your follower. Be sure to list the dialogue you created in the "Conversation" option. Make sure you give the creature/follower a UNIQUE tag (usually only an issue if you are duplicating an existing NPC). Save and check in.
4) Find the area called "char_stage." Duplicate it. When you name it, add a prefix to char_stage (so it'll be called something like "xxx_char_stage"). The Folder, Module, and Owner Module should all be your module. Add a waypoint to the area. The tag of the waypoint should be your creature's unique tag with a "char_" prefix (so it'll be called something like "char_YourUniqueCreatureTag"). Save and check in the area. [The other Follower_tutorial has some nice images that might help you with this. You should check them out.]
5) Create a new plot. Call it something like gen00pt_party_xxx. Insert (at minimum) four new main flags - CREATURENAME_HIRED, CREATURENAME_IN_PARTY, CREATURENAME_IN_CAMP, and CREATURENAME_FIRED. Replace "CREATURENAME" with your follower's name. Save and check in.
6) Create a new script. Name it something like xxx_module_core. Copy and paste the module_core script below into this script. Save and check in.
7) Create a new script. Name it something like xxx_hire_creaturename. Copy and paste the hiring script below into this script. Save and check in.
8) Create a new script. Name it something like xxx_fire_creaturename. Copy and paste the firing script below into this script. Save and check in.
9) Create a new script. Name it something like xxx_spawn_camp. Copy and paste one of the spawn follower in camp scripts into this script. Try the short version first. In theory, it should work, but when I tested it in game, Leliana would sometimes disappear. If you have that problem, replace the short version with the long version. Save and check in.
10) Open a new excel document. It doesn't matter what it's called. Rename the Sheet1, Sheet2, and Sheet3 tabs at the bottom to partypicker_xxx, party_picker_xxx, and PRCSCR_xxx.
In partypicker_xxx, create columns like those below. Replace ### with a very large number, and add in your creature's tag and name.
In party_picker_xxx, create columns like those below. Replace ### with the same very large number you used above, and add in your creature's tag.
In PRCSCR_xxx, create columns like those below. Replace ### with a very large number, and change the script to whatever you called the spawn follower in camp script (probably something like xxx_spawn_camp).
Convert the excel document into a 2DA.
11) Go back to your dialogue. In the hiring branch, set the action to fire the hiring script. In the firing branch, set the action to fire the firing script.
12) OPTIONAL: If you want to increase/decrease approval with your dialogue, you can create a new script below using the simple approval script below. You may have to make several copies for varying levels of approval/disapproval. After you have saved and checked in the approval scripts, you can set your conversation to fire these scripts.
Scripts:
module_core script
#include "events_h"
#include "wrappers_h"
#include "utility_h"
#include "plt_gen00pt_party_xxx"
void main()
{
event ev = GetCurrentEvent();
int nEventType = GetEventType(ev);
object oEventCreator = GetEventCreator(ev);
object oHero = GetHero();
object oParty = GetParty(oHero);
int nEventHandled = FALSE;
switch(nEventType)
{
case EVENT_TYPE_MODULE_GETCHARSTAGE:
{
SetPartyPickerStage("xxx_char_stage", "partypicker");
break;
}
case EVENT_TYPE_PARTYMEMBER_ADDED:
{
object oFollower = GetEventObject(ev, 0);
SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);
SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);
AddCommand(oFollower, CommandJumpToLocation(GetLocation(GetHero())));
if (GetTag(oFollower) == "INSERT CREATURE TAG HERE")
{
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_PARTY, TRUE, FALSE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_CAMP, FALSE, FALSE);
}
break;
}
case EVENT_TYPE_PARTYMEMBER_DROPPED:
{
object oFollower = GetEventObject(ev, 0);
if (GetTag(oFollower) == "INSERT CREATURE TAG HERE")
{
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_CAMP, TRUE, FALSE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_PARTY, FALSE, FALSE);
}
break;
}
}
}
Hiring script
#include "utility_h"
#include "wrappers_h"
#include "plot_h"
#include "party_h"
#include "events_h"
#include "core_h"
#include "global_objects_h"
#include "sys_autolevelup_h"
#include "sys_chargen_h"
#include "sys_rewards_h"
#include "approval_h"
#include "plt_gen00pt_party_xxx"
void main()
{
object oHero = GetHero();
object oFollower = CreateObject(OBJECT_TYPE_CREATURE, R"INSERT CREATURE TAG HERE.utc", GetLocation(oHero));
UT_HireFollower(oFollower, FALSE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_HIRED, TRUE, FALSE);
SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0);
SetGroupId(oFollower, GetGroupId(oHero));
SetFollowerApprovalEnabled(oFollower, TRUE);
SetFollowerApprovalDescription(oFollower, 371487);
SetPartyPickerGUIStatus(2);
ShowPartyPickerGUI();
}
Firing Script
#include "utility_h"
#include "wrappers_h"
#include "events_h"
#include "plt_gen00pt_party_xxx"
void main()
{
object oFollower = GetObjectByTag("INSERT CREATURE TAG HERE");
UT_FireFollower(oFollower, TRUE, TRUE);
DestroyObject(oFollower);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_FIRED, TRUE);
}
Spawn Follower in Camp Script (short version) - Try using this before trying the long version
#include "utility_h"
#include "plt_gen00pt_party_xxx"
void main()
{
object oFollower = GetObjectByTag("INSERT TAG OF CREATURE");
//Follower's position (currently by one of tents; change vector coordinates if you don't like the positioning)
vector vTent = Vector(138.564f, 111.815f, -1.08586f);
location lTent = Location(GetArea(GetHero()), vTent, 180.0f);
command cMove = CommandJumpToLocation(lTent);
if(GetFollowerState(oFollower) != FOLLOWER_STATE_ACTIVE)
{
SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);
SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE);
AddCommand(oFollower, cMove);
WR_SetObjectActive(oFollower, TRUE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_PARTY, FALSE, FALSE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_CAMP, TRUE, FALSE);
}
SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE);
AddCommand(oFollower, cMove);
WR_SetObjectActive(oFollower, TRUE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_PARTY, FALSE, FALSE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_CAMP, TRUE, FALSE);
}
Spawn Follower in Camp Script (Long Version) - Only use if Leliana is not appearing in camp as she should
#include "utility_h"
#include "wrappers_h"
#include "party_h"
#include "camp_functions_h"
#include "plt_gen00pt_party_xxx"
void main()
{
object oFollower = GetObjectByTag("INSERT TAG OF CREATURE HERE");
object oAlistair = GetObjectByTag("gen00fl_alistair");
object oMorrigan = GetObjectByTag("gen00fl_morrigan");
object oDog = GetObjectByTag("gen00fl_dog");
object oWynne = GetObjectByTag("gen00fl_wynne");
object oShale = GetObjectByTag("gen00fl_shale");
object oSten = GetObjectByTag("gen00fl_sten");
object oZevran = GetObjectByTag("gen00fl_zevran");
object oOghren = GetObjectByTag("gen00fl_oghren");
object oLeliana = GetObjectByTag("gen00fl_leliana");
object oLoghain = GetObjectByTag("gen00fl_loghain");
string sWPA = "wp_camp_gen_fl_alistair";
string sWPM = "wp_camp_gen_fl_morrigan";
string sWPD = "wp_camp_gen_fl_dog";
string sWPW = "wp_camp_gen_fl_wynne";
string sWPSh = "wp_camp_gen_fl_shale";
string sWPS = "wp_camp_gen_fl_sten";
string sWPZ = "wp_camp_gen_fl_zevran";
string sWPO = "wp_camp_gen_fl_oghren";
string sWPL = "wp_camp_gen_fl_leliana";
string sWPLo = "wp_camp_gen_fl_loghain";
object oWPA = GetObjectByTag(sWPA);
object oWPM = GetObjectByTag(sWPM);
object oWPD = GetObjectByTag(sWPD);
object oWPW = GetObjectByTag(sWPW);
object oWPSh = GetObjectByTag(sWPSh);
object oWPS = GetObjectByTag(sWPS);
object oWPZ = GetObjectByTag(sWPZ);
object oWPO = GetObjectByTag(sWPO);
object oWPL = GetObjectByTag(sWPL);
object oWPLo = GetObjectByTag(sWPLo);
//Follower's position (currently by one of tents; change vector coordinates if you don't like the positioning)
vector vTent = Vector(138.564f, 111.815f, -1.08586f);
location lTent = Location(GetArea(GetHero()), vTent, 180.0f);
command cMove = CommandJumpToLocation(lTent);
// Activating any followers that are in the party
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_ALISTAIR_RECRUITED))
{
WR_SetObjectActive(oAlistair, TRUE);
SetFollowerState(oAlistair, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_DOG_RECRUITED))
{
WR_SetObjectActive(oDog, TRUE);
SetFollowerState(oDog, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_WYNNE_RECRUITED))
{
WR_SetObjectActive(oWynne, TRUE);
SetFollowerState(oWynne, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_SHALE_RECRUITED))
{
WR_SetObjectActive(oShale, TRUE);
SetFollowerState(oShale, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_STEN_RECRUITED))
{
WR_SetObjectActive(oSten, TRUE);
SetFollowerState(oSten, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_ZEVRAN_RECRUITED))
{
WR_SetObjectActive(oZevran, TRUE);
SetFollowerState(oZevran, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_OGHREN_RECRUITED))
{
WR_SetObjectActive(oOghren, TRUE);
SetFollowerState(oOghren, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_LELIANA_RECRUITED))
{
WR_SetObjectActive(oLeliana, TRUE);
SetFollowerState(oLeliana, FOLLOWER_STATE_AVAILABLE);
}
if (GetFollowerState(oLeliana) != FOLLOWER_STATE_ACTIVE)
{
WR_SetObjectActive(oLeliana, TRUE);
Rubber_SetHome(oLeliana, oWPL);
Rubber_JumpHome(oLeliana);
}
if (GetFollowerState(oFollower) == FOLLOWER_STATE_ACTIVE)
{
WR_SetObjectActive(oLeliana, TRUE);
Rubber_SetHome(oLeliana, oWPL);
Rubber_JumpHome(oLeliana);
SetFollowerState(oLeliana, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_MORRIGAN_RECRUITED))
{
WR_SetObjectActive(oMorrigan, TRUE);
SetFollowerState(oMorrigan, FOLLOWER_STATE_AVAILABLE);
}
if (WR_GetPlotFlag(PLT_GEN00PT_PARTY, GEN_LOGHAIN_RECRUITED))
{
WR_SetObjectActive(oLoghain, TRUE);
SetFollowerState(oLoghain, FOLLOWER_STATE_AVAILABLE);
}
if(GetFollowerState(oFollower) != FOLLOWER_STATE_ACTIVE)
{
SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);
SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE);
AddCommand(oFollower, cMove);
WR_SetObjectActive(oFollower, TRUE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_PARTY, FALSE, FALSE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_CAMP, TRUE, FALSE);
}
SetFollowerState(oFollower, FOLLOWER_STATE_AVAILABLE);
AddCommand(oFollower, cMove);
WR_SetObjectActive(oFollower, TRUE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_PARTY, FALSE, FALSE);
WR_SetPlotFlag(PLT_GEN00PT_PARTY_XXX, CREATURENAME_IN_CAMP, TRUE, FALSE);
}
Simple Approval Script
#include "approval_h"
void main()
{
object oFollower = GetObjectByTag("INSERT CREATURE TAG HERE");
AdjustFollowerApproval(oFollower, 5, TRUE); /*change the 7 to whatever you want to increase approval by. change to negative number to decrease approval*/
}
