Endless Adventures Companion Hire Include

From Dragon Age Toolset Wiki
Jump to: navigation, search

Endless Adventures Main Page

Endless Adventures EAC Tutorials

This page holds the code for the common "ea_companion_h" script used for EAC modules. This script is included in the base module, so modders don't need to include it in their addins. Note that making any changes to the script and including it in an addin could break other addin modules.

#include "sys_chargen_h"
#include "wrappers_h"
#include "utility_h"
#include "sys_rewards_h"
#include "approval_h"
#include "sys_autolevelup_h"
 
/*  Jye Nicolson 5-Jan-2010
This function set duplicates the full functionality chain of UT_HireFollower, with the following exceptions:
 
-  Followers can gain XP
-  Autolevel status can be set (default off)
-  Followers can be set to any starting state (default Available) and will still be properly initalised and added to the party pool
-  Autolevel tables for non-core followers can be explicitly set.
-  Class and Specialisation can be chosen via script
-  Followers without specialisations are granted a spec point by default.
 
It should only ever be called once each for characters you intend to be full followers.
Much of the protective code handling summoned creatures etc. in player_core is not present here.
 
*/
 
// This just cleans up the main function a little
 
int GetCustomFollowerTargetLevel(object oFollower, object oHero, int nPackage, int nMinLevel = 0) {
            int nPlayerLevel = GetLevel(oHero);
            int nTargetLevel = 0;
 
            if((nPlayerLevel >= 13) || (nPlayerLevel == 1) || (!_UT_GetIsPlotFollower(oFollower))) {
               nTargetLevel = nPlayerLevel;
            } else {
               nTargetLevel = nPlayerLevel + 1;
            }
 
            if (nMinLevel == 0) {  //If nMinLevel is not specified, checks package 2DA for a value
              nMinLevel = GetM2DAInt(TABLE_PACKAGES, "MinLevel", nPackage);
             }
            if(nMinLevel > 0 && nMinLevel > nTargetLevel) {
               nTargetLevel = nMinLevel;
            }
            return nTargetLevel;
}
 
/* InitCustomFollowerSpec:
This function tries to set the forced Specialisation.  If there is none, it checks the package for one.
If there isn't either of those, it grants a free spec point if bFreeSpecPoint is true.
*/
void InitCustomFollowerSpec(object oFollower, int nPackage, int nForceSpec, int bFreeSpecPoint) {
    // Find specialization, and optionally add a spec point if none is found.
        if (nForceSpec == 0) {
        int nSpecAbility = GetM2DAInt(TABLE_PACKAGES, "switch1_class", nPackage); // followers can have only 1 advanced class
         if(nSpecAbility > 0)
         {
          AddAbility(oFollower, nSpecAbility);
         } else {
             if (bFreeSpecPoint) {
                 SetCreatureProperty(oFollower, 38, 1.00);
             }
         }
        } else {
             AddAbility(oFollower, nForceSpec);
        }
}
 
/* hireCustomFollower()  (See doco at top of page)
 
I strongly suggest you reorder the parameters if you're adding many followers with advanced options.
 
Feel free to leave them alone if you only want to set class, plot, spec or don't mind long declarations.
 
Note nForceClass is currently compulsory due to flakiness with GetCreatureCoreClass()
*/
 
void EA_HireFollower(object oFollower, int nForceClass, int nForceSpec = 0,
int nALTable = 0, int nAutolevel = 0, int bFreeSpecPoint = TRUE, int nTargetLevel = 0, int nMinLevel = 0)
{object oHero = GetHero();
 int nInitialState = FOLLOWER_STATE_AVAILABLE;
 
        /* #################  BEGIN BASIC FOLLOWER JOIN BLOCK   ###################
        This loosely replicates WR_SetFollowerState.
        */
        if (nForceClass == 0) {
            nForceClass = GetCreatureCoreClass(oFollower);           //This is not working.  Hence nForceClass mandatory.
        }
 
        SetGroupId(oFollower, GetGroupId(oHero));      //Puts the follower in the pc's Group.
        SetEventScript(oFollower, RESOURCE_SCRIPT_PLAYER_CORE);  //This makes them act like a player.
        SetFollowerState(oFollower, nInitialState);  //This sets whether they are available, in the active party etc.
 
        /* #################  END BASIC FOLLOWER JOIN BLOCK ##################### */
 
        /* #################  BEGIN PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION #################
         This replicates the EVENT_TYPE_PARTY_MEMBER_HIRED handler from player_core, stripped down for simplicity and allowing our custom options.
        */
        Chargen_EnableTacticsPresets(oFollower);    //I assume this is important.
 
        SetLocalInt(oFollower, FOLLOWER_SCALED, 1);  //This should prevent the follower being rescaled by player_core or what have you
 
        int nPackage = GetPackage(oFollower);  //Gets the package, which will be used to find a number of 2DA IDs.
        int nPackageClass = GetM2DAInt(TABLE_PACKAGES, "StartingClass", nPackage);  //I don't think this is used, even by player_core
 
        // set behavior according to package
        int nBehavior = GetM2DAInt(TABLE_PACKAGES, "FollowerBehavior", nPackage);
 
        if(nBehavior >= 0) {
            SetAIBehavior(oFollower, nBehavior);
        }
 
        Chargen_InitializeCharacter(oFollower);      //We initialise the follower and choose race/class.
        Chargen_SelectRace(oFollower,GetCreatureRacialType(oFollower));
        Chargen_SelectCoreClass(oFollower,nForceClass);
 
         if (nTargetLevel == 0) {   //This block picks a target level if not specified
 
              nTargetLevel = GetCustomFollowerTargetLevel(oFollower, oHero, nPackage, nMinLevel);
         }
 
         int nXp = RW_GetXPNeededForLevel(Max(nTargetLevel, 1));      //Here is where the XP is calculated and rewarded
         RewardXP(oFollower, nXp, FALSE, FALSE);
 
         // -------------------------------------------------------------
         // 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)
         // -------------------------------------------------------------
         int nIndex = Approval_GetFollowerIndex(oFollower);
         Approval_AddFollowerBonusAbility(nIndex, 0);
 
          //Handle Specialisation
          InitCustomFollowerSpec(oFollower, nPackage, nForceSpec, bFreeSpecPoint);
 
         // -------------------------------------------------------------
         // This spends all available attribute and stat points on the
         // creature according to the levelup table.  (JN:  this replicates AL_DoAutoLevelUp but with our choice of table)
         // -------------------------------------------------------------
 
         if (nALTable == 0) {
            nALTable = 1002;
            if (nForceClass = CLASS_WIZARD)
            nALTable = 1003;
            if (nForceClass = CLASS_ROGUE)
            nALTable = 1004;
         }
 
         AL_SpendAttributePoints(oFollower, nALTable, FALSE);
         AL_SpendSkillPoints(oFollower, nALTable, TRUE);
         AL_SpendSpecializationPoints(oFollower, nALTable);
         AL_SpendTalentSpellPoints(oFollower, nALTable, TRUE);
 
        // -------------------------------------------------------------------------
        // Update various UIs
        // -------------------------------------------------------------------------
        Chargen_SetNumTactics(oFollower);
        SetCanLevelUp(oFollower,Chargen_HasPointsToSpend(oFollower));
 
         /* #################  END PLAYER_CORE EVENT_TYPE_PARTY_MEMBER_HIRED EMULATION ################# */
 
           SetAutoLevelUp(oFollower, nAutolevel);         //This is the autolevel flag on the character sheet.
 
           SetCreatureProperty(oFollower, PROPERTY_ATTRIBUTE_REGENERATION_HEALTH_COMBAT,  10.0f);
           SetCreatureProperty(oFollower, PROPERTY_ATTRIBUTE_REGENERATION_STAMINA_COMBAT, 10.0f);
           SetCreatureProperty(oFollower, PROPERTY_ATTRIBUTE_REGENERATION_HEALTH,30.0f, PROPERTY_VALUE_BASE);
           SetCreatureProperty(oFollower, PROPERTY_ATTRIBUTE_REGENERATION_STAMINA, 30.0f, PROPERTY_VALUE_BASE);
        // Invoke picker if requested.
             SetPartyPickerGUIStatus(2);
             ShowPartyPickerGUI();
 
}