Difference between revisions of "Playing custom Player Character"

From Dragon Age Toolset Wiki
Jump to: navigation, search
(Characters)
(Characters)
Line 11: Line 11:
 
Create 3 creatures
 
Create 3 creatures
  
* lpt_000c_ariana (tag "lpt_000c_ariana") - This is our main character. Set her class, gender and morph.
+
* lpt_000c_ariana (tag "lpt_000c_ariana") - This is our main character. Set her class, gender, VO and morph.
* lpt_000c_default_char (tag "lpt_000c_default_char") - this character who will mimic Jaden, so change only it's head morph and gender. The rest must be default.
+
* lpt_000c_default_char (tag "lpt_000c_default_char") - this character who will mimic Jaden, so change only it's head morph, VO and gender. The rest must be default.
* lpt_000c_roquefort (tag "party_roquefort") - this is the follower. Set up his gender, class, inventory and head.
+
* lpt_000c_roquefort (tag "party_roquefort") - this is the follower. Set up his gender, class, VO, inventory and head.
 +
 
 +
 
 +
Note: If you change morph of your PC you should change both files
  
 
== Plot file ==
 
== Plot file ==

Revision as of 04:50, 15 July 2014

Author: dr. dummie

This tutorial:

  • Allows you to play custom character.
  • Start your module with cutscene.
  • Allows you to create character 10 lvl and set it's characteristics as you want.


Characters

Create 3 creatures

  • lpt_000c_ariana (tag "lpt_000c_ariana") - This is our main character. Set her class, gender, VO and morph.
  • lpt_000c_default_char (tag "lpt_000c_default_char") - this character who will mimic Jaden, so change only it's head morph, VO and gender. The rest must be default.
  • lpt_000c_roquefort (tag "party_roquefort") - this is the follower. Set up his gender, class, VO, inventory and head.


Note: If you change morph of your PC you should change both files

Plot file

You need to create plot file of your module. This must be called "lpt_module_plot". Don't forget to create cutscene named "lpt_module_intro".

There is only one Main Flag must be called MODULE_START_CUTSCENE with default settings.

Module script

This is script of your module

//::///////////////////////////////////////////////
//:: Module Template
//:: Copyright (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Module events
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On:
//:://////////////////////////////////////////////
 
#include "log_h"
#include "utility_h"
#include "wrappers_h"
#include "events_h"
 
#include "sys_chargen_h"
#include "sys_rewards_h"
 
const int FORCE_AUTOLEVEL = 0;  //to turn autolevel off
 
void main()
{
    event ev = GetCurrentEvent();
    int nEventType = GetEventType(ev);
    string sDebug;
    object oPC = GetHero();
    object oParty = GetParty(oPC);
    int nEventHandled = FALSE;
 
    switch(nEventType)
    {
        ////////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: The module starts. This can happen only once for a single
        //       game instance.
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_MODULE_START:
        {
 
            //normally we would go trough chargen
            //PreloadCharGen();
            //StartCharGen(GetHero());
 
            //but since we have fixed hero
            object oHero = GetHero();
 
            // skip character generation and set some defaults
            Chargen_InitializeCharacter(oHero);
            Chargen_SelectGender(oHero, GENDER_FEMALE);
            Chargen_SelectRace(oHero, RACE_HUMAN);
            Chargen_SelectCoreClass(oHero,CLASS_ROGUE);
            Chargen_SelectBackground(oHero, BACKGROUND_NOBLE);
 
            //give hero a name
            SetName(oHero, "Ariana");
 
            //manually give the player some equipment
            //EquipItem(oHero, UT_AddItemToInventory(R"gen_im_arm_cht_lgt_new.uti"));
 
            //or create your fixed character as template and then transfer everything on player.
            LoadItemsFromTemplate(oHero, "lpt_000c_ariana.utc", TRUE);
 
            //NOTE!
            //to get player appereance as you like, you must create blank char with desired facemorph
            //then after export copy that char to "default_player.utc" in your module override directory
            //so now this will be default char instead JADEN
 
            // lets go level 10 and set autolevel to off
            RewardXP(oHero, RW_GetXPNeededForLevel(10), FALSE, FALSE);
            SetAutoLevelUp(oHero, FORCE_AUTOLEVEL);
 
            PrintToLog("------> MODULE START - Ariana created");
 
            break;
        }
        ////////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: The module loads from a save game. This event can fire more than
        //       once for a single module or game instance.
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_MODULE_LOAD:
        {
            break;
        }
    ////////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: A player enters the module
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_ENTER:
        {
            object oCreature = GetEventCreator(ev);
 
            break;
        }
    ////////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: the player clicks on a destination in the world map
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_WORLD_MAP_USED:
        {
            int nFrom = GetEventInteger(ev, 0); // travel start location
            int nTo = GetEventInteger(ev, 1); // travel target location
            break;
        }
    }
    if (!nEventHandled)
    {
        HandleEvent(ev, RESOURCE_SCRIPT_MODULE_CORE);
    }
}

Area scipt

This is script of your starting area

//::///////////////////////////////////////////////
//:: Area Core
//:: Copyright (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Handles global area events
*/
//:://////////////////////////////////////////////
//:: Created By: Yaron
//:: Created On: July 17th, 2006
//:://////////////////////////////////////////////
 
#include "log_h"
#include "utility_h"
#include "wrappers_h"
#include "events_h"
#include "2da_constants_h"
 
#include "lpt_utility_h"
 
#include "plt_lpt_module_plot"
 
void main()
{
    event ev = GetCurrentEvent();
    int nEventType = GetEventType(ev);
    string sDebug;
    object oPC = GetHero();
    object oParty = GetParty(oPC);
    int nEventHandled = FALSE;
 
    switch(nEventType)
    {
        ///////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: it is for playing things like cutscenes and movies when
        // you enter an area, things that do not involve AI or actual game play
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_AREALOAD_SPECIAL:
        {
 
            PrintToLog("-----> START AREA - AREALOAD SPECIAL.");
 
            //moved cutscene and hiring code to postloadexit cause some
            //stuff didnt worked here
 
            //EDIT: It seems that works with this approach! left other info for
            //      learn and debug purposes.
 
            //we run cutscene in this event cause in areaload special we could not
            //hire follower with desired behavior (gain xp and skills can be set)..
            //since cutscene and hiring are to be done only once we keep them together.
            //here it works.. why? i dont know..
            if (WR_GetPlotFlag(PLT_LPT_MODULE_PLOT, MODULE_START_CUTSCENE) == FALSE)
            {
                //roquefort is added to start area and has tag "roquefort"
                object oFollower = GetObjectByTag("party_roquefort");
 
                //this caused follower to not gain xp, it is bug in game script
                //UT_HireFollower(oFollower); //we're not using this
 
                //instead hiring follower with UT_hirefollower, set plot flag and
                //start script which will hire Roquefort..
                //this is used if you want to set plot flag to "know" that roquefort is hired
                //like in some dialogues etc where you can check for conditions..
                //WR_SetPlotFlag(PLT_LOP_MODULE_PLOT, ROQUEFORT_HIRED, TRUE, TRUE);
 
                //eventually we can try this to avoid plots at all!
                //but i guess it would not work as it should without setting
                //bResetFollower to true..
                lop_UT_HireFollower(oFollower, FALSE, 0, TRUE, CLASS_WARRIOR);
 
                // Start cutscene, also set plot flag that cutscene was played.
                PrintToLog("-----> START AREA - Load Cutscene.");
                CS_LoadCutscene(R"lpt_module_intro.cut", PLT_LPT_MODULE_PLOT, MODULE_START_CUTSCENE);
                PlayCutscene();
             }
 
            break;
        }
        ///////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: for things you want to happen while the load screen is still up,
        // things like moving creatures around
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_AREALOAD_PRELOADEXIT:
        {
            break;
        }
        ////////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: fires at the same time that the load screen is going away,
        // and can be used for things that you want to make sure the player sees.
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_AREALOAD_POSTLOADEXIT:
        {
            break;
        }
        ////////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: A creature enters the area
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_ENTER:
        {
            object oCreature = GetEventCreator(ev);
 
            break;
        }
        ////////////////////////////////////////////////////////////////////////
        // Sent by: The engine
        // When: A creature exits the area
        ////////////////////////////////////////////////////////////////////////
        case EVENT_TYPE_EXIT:
        {
            object oCreature = GetEventCreator(ev);
 
            break;
        }
    }
    if (!nEventHandled)
    {
        HandleEvent(ev, RESOURCE_SCRIPT_AREA_CORE);
    }
}

One more scipt

This one must be called lpt_utility_h

                      //:://////////////////////////////////////////////
/*
    "Lady of pain"
     -> Utility include script
 
     This file contains utility functions
*/
//:://////////////////////////////////////////////
//:: Created By: Kivito
//:: Created On: 19.10.2013
//:://////////////////////////////////////////////
 
#include "sys_chargen_h"
#include "sys_rewards_h"
 
#include "plt_tut_friendly_aoe"
 
//clears creature stats (from wiki)
void lop_ClearCharStats(object oFollower);
 
//resets all creature points to defaults
//it should be called ONLY AFTER follower is hired,
//also you can change core class for follower
void lop_ReHireChar(object oFollower, int nCoreClass = 1);
 
//custom hire follower with parameters, if bResetFollower is true,
//then all followers points are reset to defaults, also if nCoreClass is specified
//it is possible to change i.e. warrior to mage
void lop_UT_HireFollower(object oFollower, int bPreventLevelUp = FALSE, int nForceAutolevel = 0, int bResetFollower = FALSE, int nResetTo = 1);
 
void lop_ClearCharStats(object oChar)
{
    // Initialize all creature properties to default value
 
    SetCreatureProperty(oChar,PROPERTY_SIMPLE_LEVEL,1.0f,PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_SIMPLE_EXPERIENCE,0.0f,PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_STRENGTH,      CHARGEN_BASE_ATTRIBUTE_VALUE, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_DEXTERITY,     CHARGEN_BASE_ATTRIBUTE_VALUE, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_CONSTITUTION,  CHARGEN_BASE_ATTRIBUTE_VALUE, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_WILLPOWER,     CHARGEN_BASE_ATTRIBUTE_VALUE, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_INTELLIGENCE,  CHARGEN_BASE_ATTRIBUTE_VALUE, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_MAGIC,         CHARGEN_BASE_ATTRIBUTE_VALUE, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_ATTACK_SPEED_MODIFIER,     1.0f);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_DAMAGE_SCALE,       1.0f);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_RESISTANCE_MENTAL,         0.0f);
    SetCreatureProperty(oChar,PROPERTY_ATTRIBUTE_RESISTANCE_PHYSICAL,       0.0f);
    SetCreatureProperty(oChar,51,       1.0f);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_REGENERATION_HEALTH_COMBAT,  REGENERATION_HEALTH_COMBAT_DEFAULT);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_REGENERATION_STAMINA_COMBAT, REGENERATION_STAMINA_COMBAT_DEFAULT);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_REGENERATION_HEALTH,REGENERATION_HEALTH_EXPLORE_DEFAULT, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_REGENERATION_STAMINA, REGENERATION_STAMINA_EXPLORE_DEFAULT, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_MISSILE_SHIELD,0.0);
    SetCreatureProperty(oChar, 38,0.0);
    SetCreatureProperty(oChar, PROPERTY_DEPLETABLE_HEALTH ,          1.0f, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar, PROPERTY_DEPLETABLE_MANA_STAMINA ,    0.0f, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_DEFENSE ,          0.0f, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_ATTACK,            0.0f, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_DAMAGE_BONUS,      0.0f, PROPERTY_VALUE_BASE);
    SetCreatureProperty(oChar, PROPERTY_ATTRIBUTE_FLANKING_ANGLE,  60.0f, PROPERTY_VALUE_BASE);
}
 
 
 
void lop_ReHireChar(object oFollower, int nCoreClass = 1)
{
    object me = oFollower;
    object oPC = GetHero();
 
    //lets get some info from original follower
 
    //this returns invalid class(0)!! probably cause when hiring a follower
    //game performes some AI update in "areaload special" event
    int nClass = GetCreatureCoreClass(me);
    int nCurrentClass = GetCreatureCurrentClass(me);
 
    int nRace = GetCreatureRacialType(me);
    int nGender = GetCreatureGender(me);
 
    //it seems we dont need this
    //lop_ClearCharStats(me);
 
    //cause this went well
    Chargen_InitializeCharacter(me);
 
    //select race, otherwise skills tree wont show
    //Chargen_SelectRace(me,RACE_HUMAN);
    Chargen_SelectRace(me, nRace); //we passing race from original char
 
    //no use for this since we passing core class from function
    //int nClass_s = CLASS_WARRIOR;
 
    Chargen_SelectGender(me, nGender); //we passing gender from original char
 
    //remove the defaults - leftover(s) from wiki, could be useful for some other approaches
    //CharGen_ClearAbilityList(me,1);//remove talents
    //CharGen_ClearAbilityList(me,2);//remove spells
    //CharGen_ClearAbilityList(me,3);//remove skills
 
    //apply attributes, abilities and stats for the core class
    //SetCreatureProperty(me,PROPERTY_SIMPLE_CURRENT_CLASS, n1-3.0,PROPERTY_VALUE_BASE);
 
    //we passed core class for our follower, in theory here we could change it
    //to be what we want (i.e. from warrior to mage)
    Chargen_SelectCoreClass(me, nCoreClass);
 
    //add ability - just to test it
    //_AddAbility(me, ABILITY_TALENT_POWERFUL);
 
    PrintToLog("-----> lop_ReHireFollower: Race: " + IntToString(nRace) +
        ", Current Core Class: " + IntToString(nClass) + ", Wanted Core Class: " + IntToString(nCoreClass) +
        ", Gender: " + IntToString(nGender) + ", Current (sub) Class: " + IntToString(nCurrentClass));
 
    //tactics
    Chargen_SetNumTactics(me);
    Chargen_EnableTacticsPresets(me);
 
    //level needed for scaling
    int nPackage = GetPackage(me);
    int nTargetLevel;
 
    int nPlayerLevel = GetLevel(oPC);
    if(nPlayerLevel >= 13 || nPlayerLevel == 1 )
       nTargetLevel = nPlayerLevel;
    else
       nTargetLevel = nPlayerLevel + 1;
 
    int nMinLevel = GetM2DAInt(TABLE_PACKAGES, "MinLevel", nPackage);
 
    if(nMinLevel > 0 && nMinLevel > nTargetLevel)
       nTargetLevel = nMinLevel;
 
    //xp until hero level
    int nXp = RW_GetXPNeededForLevel(Max(nTargetLevel, 1));
    RewardXP(me, nXp, FALSE, FALSE);
 
    //add specialization
    float count=1.0;
    if(GetLevel(oPC)>=7)
    {
        SetCreatureProperty(me, 38, count);  // 38 is the spec point ID
        count=count+1.0;
    }
    if(GetLevel(oPC)>=14)
        SetCreatureProperty(me, 38, count);  // 38 is the spec point ID
 
    //make available in party picker - don't know if its needed here for this case usage
    //SetFollowerState(me, FOLLOWER_STATE_ACTIVE);
    //SetFollowerState(me, FOLLOWER_STATE_AVAILABLE);
 
    //dont fire player_core scaling
    SetLocalInt(me, FOLLOWER_SCALED, 1);
    SetLocalInt(me, AI_FLAG_STATIONARY, 0);
    SetLocalInt(me, AMBIENT_SYSTEM_STATE, 0);
    SetLocalInt(me, CREATURE_REWARD_FLAGS, 0);
 
    //change script to player and send hire event
    SetEventScript(me, RESOURCE_SCRIPT_PLAYER_CORE);
    InitHeartbeat(me, CONFIG_CONSTANT_HEARTBEAT_RATE);
    SendPartyMemberHiredEvent(me, FALSE);
    SetFollowerApprovalEnabled(me,TRUE);
 
    //open up party picker to allow npc to join in the active party - not needed in this usage
    //SetPartyPickerGUIStatus(2);
    //ShowPartyPickerGUI();
 
    SetFollowerState(me, FOLLOWER_STATE_ACTIVE);  //put him in party
 
    PrintToLog("-----> Custom Hire follower: " + GetTag(me) +
        ", Hero lvl: " + IntToString(nPlayerLevel) + ", Follower level: " + IntToString(nTargetLevel));
}
 
 
 
void lop_UT_HireFollower(object oFollower, int bPreventLevelUp = FALSE, int nForceAutolevel = 0, int bResetFollower = FALSE, int nResetTo = 1)
{
    object oPC = GetPartyLeader();
 
    PrintToLog("-----> lop_UT_HireFollower: Hiring: " + GetTag(oFollower) +
        ", Party leader: " + GetTag(oPC) + ", Autolevel: " + IntToString(nForceAutolevel) +
        ", Reset follower: " + IntToString(bResetFollower));
 
    //cannot be used for plot followers
    if(_UT_GetIsPlotFollower(oFollower))
    {
        PrintToLog("-----> lop_UT_HireFollower: Follower IS plot follower, exiting.");
        return;
    }
 
    //calling this code caused follower to be hired and to gain xp
    SetAutoLevelUp(oFollower, nForceAutolevel);       //0 - off, 1 - autolevel, 2 - force autolevel
    SetGroupId(oFollower, GetGroupId(oPC));           //not sure if needed cause player_core resets it
    SetLocalInt(oFollower, CREATURE_REWARD_FLAGS, 0); //to gain xp
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE, TRUE, 0, bPreventLevelUp);
 
    //Show the AOE flag when the PC is a mage and aquires a follower or the follower hired is a mage
    if(GetLocalInt(GetModule(), TUTORIAL_ENABLED) && (GetCreatureCoreClass(oPC) == CLASS_WIZARD || GetCreatureCoreClass(oFollower) == CLASS_WIZARD))
    {
        WR_SetPlotFlag(PLT_TUT_FRIENDLY_AOE, TUT_FRIENDLY_AOE_1, TRUE);
    }
 
    if (bResetFollower)
    {
        PrintToLog("-----> lop_UT_HireFollower: Resetting follower.");
        //calling this will re-initialize follower
        lop_ReHireChar(oFollower, nResetTo);
    }
 
}
 
//activates group of triggers by tag
void yad_ActivateTrigger(string sTriggerTag, int bActivate = TRUE)
{
    object [] arActivate = GetNearestObjectByTag(GetMainControlled(), sTriggerTag, OBJECT_TYPE_TRIGGER, 15);
    int nSize = GetArraySize(arActivate);
 
    object oActivate;
    int nIndex;
 
    for (nIndex = 0; nIndex < nSize; ++nIndex)
    {
        oActivate = arActivate[nIndex];
        WR_SetObjectActive(oActivate, bActivate);
        DisplayFloatyMessage(oActivate, "Hello trigger!", FLOATY_MESSAGE,16777215,10.0);
    }
}