User:Satans karma
Noob-Friendly Follower Tutorial:
Contents
Assumptions:
1) You know how to create a new module. If not, read through the module tutorial first.
2) You know how to create a basic dialogue. If not, read through the conversation tutorial first.
3) You know how to make a creature. If not, read through the creature tutorial first.
4) You know how to add waypoints to an area. If not, read through the area tutorial first.
5) You know how to create a plot. If not, read through the plot tutorial first.
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).
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*/
}
