Compatible Companion Mod Creation/Gifts And Approval

From Dragon Age Toolset Wiki
Jump to: navigation, search

The Gifts And Approval step explains how modify your custom companion's approval through gift giving and scripted events.

Valeria Gift Handling

When a gift item (Base Item Type set to gift) is given to a companion, the event EVENT_TYPE_MODULE_HANDLE_GIFT fires and is processed by core game scripts. So the easy way to handle this, is modify most notably sp_module_item_acq and the approval scripts.

As it turns out, ANY item set to gift item, will lead to this script firing and changing the companion's approval. The script has a list of companions and corresponding indices to each one, so it knows how to handle them(the original game ones), and the function that gives you the companion index or tag (like Approval_GetFollowerObject in approval_h) DOES NOT have a default value to return. That's fine of course, so people go in and can add their companion to all those scripts. We don't want to do that.

The unfortunate part for us, is that even if you give Valeria any gift, her approval will not be handled appropriately, since her tag is nowhere in those scripts. Moreover, if you give someone else a gift that should be unique for your companion, the gift will be lost forever since your companion is not in the checks from the core game scripts.

One way around this, that works fine if ONLY ONE mod does it (as I have), is everytime a gift is handed to a companion (from the original game or from a companion mod) we capture all possibilities as seen below in the code in Event handling and associated scripts.

So I will first illustrate how to do it for only one mod, and then we'll work on changing it so everyone can do it, aye?

NOTE: I have changed and restructured my current scripts in my mod from these basic ones you see below (to perfect things like approval rating showing on the inventory GUI for Valeria, use different approval names than the core game ones etc, but these below should get you started. If you master these scripts you can also do it yourself after.)

What we need

When a gift is given to a companion and their approval goes up, a "plot" skill (like increased attributes or extra talents) must be given to the companion and the approval status should change. If approval drops below a certain level, the appropriate skills must be removed from the companion and so forth. Valeria appears in non of the corresponding game scripts so we have to take care of all of that. We'll build our own functions.

Moreover, the gifts are lost without any effect on the companion. Which means any gifts that should not be allowed to be given to Valeria, must be returned back in the inventory, or Valeria gifts, not allowed to be given to other companions, must also be returned to the inventory. It is a pain in the a...

Note to self: ask Bioware to build a StringToResource() conversion function, ack.

Let's start. In 'includes' add the following function definitions:

...
//these are the plot ability id's from ABI_BASE
const int valeria_nAbility1war=90200;
const int valeria_nAbility2war=90201;
const int valeria_nAbility3war=90202;
const int valeria_nAbility4war=90218;
const int valeria_nAbility1thief=90209;
const int valeria_nAbility2thief=90210;
const int valeria_nAbility3thief=90211;
const int valeria_nAbility4thief=90221;
const int valeria_nAbility1mage=90215;
const int valeria_nAbility2mage=90216;
const int valeria_nAbility3mage=90217;
const int valeria_nAbility4mage=90223;
const int valeria_nAbility_warshow=90224;
const int valeria_nAbility_thiefshow=90227;
const int valeria_nAbility_mageshow=90229;
...
void valeria_approval();
void give_valeria_skill(object oval,int level);
void handle_valeria_gift(object oFollower,object oItem,int nApprovalChange);
resource get_gift_resource(string sGiftTag);
resource get_valeria_gift_resource(string sGiftTag);
...

Handling the event EVENT_TYPE_MODULE_HANDLE_GIFT

We capture here all possibilities in gift handling, based on the behavior of the core game scripts.

Add this to Event handling section:

        case EVENT_TYPE_MODULE_HANDLE_GIFT:
        {
//from my experiments, it is possible to have this script be fired
//before the core game script does(which mean the constant 
//nApprovalChange has not been changed from the core game scripts.
//that introduces extra difficulties
//it happens for instance when you first load the game, and give 
//Valeria a gift or say Alistair. This will bug their approval rating
//what you see below, is the solution to all those possibilities
//after tons of trial and error
//companion object
            object oFollower = GetEventObject(ev, 0);
//gift object
            object oItem = GetEventObject(ev, 1);
//this is the default(for that gift)approval change value from the game
            int nApprovalChange = GetEventInteger(ev, 0);  
//tag of the gift
            string sGiftTag = GetTag(oItem);
//if the follower recieving the gift is not Valeria but we chose to
//give them a Valeria gift, they should refuse it, and throw it back
//in the inventory, I use 6 unique gifts for her in my mod
            if(GetTag(oFollower)!="valeria_npc")
            {
             if(sGiftTag=="valeria_gift1"  ||sGiftTag=="valeria_gift2" ||sGiftTag=="valeria_gift3"  ||sGiftTag=="valeria_gift4" ||sGiftTag=="valeria_gift5"  ||sGiftTag=="valeria_gift6")
             {
//we adjust the follower approval to what it was
//this will cause the following wierd behavior, say Alistair 
//is 3 points away from a plot skill upgrade, giving him the gift 
//would give him the plot, and then remove it, so the message will
//show up. No way around this I'm afraid.
                AdjustFollowerApproval(oFollower,-nApprovalChange,TRUE);
//return valeria only gifts, StringToResource function needed first
//here. It gets a LOT worse. there's a function about this, see below.
                resource res=get_valeria_gift_resource(sGiftTag);
                UT_AddItemToInventory(res, 1,GetHero(),"",TRUE);
                PlaySoundSet(oFollower, SS_GIFT_NEGATIVE);
             }
            }
//if the gift is given to Valeria
            if(GetTag(oFollower) == "valeria_npc")
            {
//if she was not the character we were controlling
//while opening the inventory gui, that character WILL have their 
//approval changed. So bring it back to what it was.
                if(GetTag(GetMainControlled())!= "valeria_npc")
                {
                    AdjustFollowerApproval(GetMainControlled(),-nApprovalChange,TRUE);
                }
                handle_valeria_gift(oFollower,oItem,nApprovalChange);
            }
            break;
        }

Valeria custom gift/approval scripts

Add these functions in the 'functions' section.

Gift function: get_valeria_gift_resource

resource get_valeria_gift_resource(string sGiftTag)
{
    resource res;
        if (sGiftTag == "valeria_gift1")
            res=R"valeria_gift1.uti";
        if (sGiftTag == "valeria_gift2")
            res=R"valeria_gift2.uti";
        if (sGiftTag == "valeria_gift3")
            res=R"valeria_gift3.uti";
        if (sGiftTag == "valeria_gift4")
            res=R"valeria_gift4.uti";
        if (sGiftTag == "valeria_gift5")
            res=R"valeria_gift5.uti";
        if (sGiftTag == "valeria_gift6")
            res=R"valeria_gift6.uti";
    return res;
}

Gift function: get_gift_resource (oh yes, all game gifts)

We have to do this only for the gifts not being returned automatically by game scripts, like Alistair's Mother locket, Morrigan's Grimoire etc.

resource get_gift_resource(string sGiftTag)
{
    resource res;
//alistair
//    if (sGiftTag == GEN_IM_GIFT_ALISTAIR_AMULET)
//    if (sGiftTag == GEN_IM_GIFT_DUNCAN_SHIELD)
    if (sGiftTag == "gen_im_gift_runston")
        res=R"gen_im_gift_runston.uti";
    if (sGiftTag == "gen_im_gift_runston2")
        res=R"gen_im_gift_runston2.uti";
    if (sGiftTag == "gen_im_gift_stat")
        res=R"gen_im_gift_stat.uti";
    if (sGiftTag == "gen_im_gift_stat2")
        res=R"gen_im_gift_stat2.uti";
    if (sGiftTag == "gen_im_gift_stat3")
        res=R"gen_im_gift_stat3.uti";
    if (sGiftTag == "gen_im_gift_stat4")
        res=R"gen_im_gift_stat4.uti";
//leliana
//    if (sGiftTag == "gen_im_gift_nugg")
//    if (sGiftTag == "gen_im_gift_flower_andraste")
    if (sGiftTag == "gen_im_gift_chantam")
        res=R"gen_im_gift_chantam.uti";
    if (sGiftTag == "gen_im_gift_hlysymb")
        res=R"gen_im_gift_hlysymb.uti";
    if (sGiftTag == "gen_im_gift_hlysymb2")
        res=R"gen_im_gift_hlysymb2.uti";
    if (sGiftTag == "gen_im_gift_hlysymb3")
        res=R"gen_im_gift_hlysymb3.uti";
    if (sGiftTag == "gen_im_gift_hlysymb4")
        res=R"gen_im_gift_hlysymb4.uti";
    if (sGiftTag == "gen_im_gift_hlysymb5")
        res=R"gen_im_gift_hlysymb5.uti";
    if (sGiftTag == "gen_im_gift_shoe")
        res=R"gen_im_gift_shoe.uti";
//loghain 13
    if (sGiftTag == "gen_im_gift_map")
        res=R"gen_im_gift_map.uti";
    if (sGiftTag == "gen_im_gift_map2")
        res=R"gen_im_gift_map2.uti";
    if (sGiftTag == "gen_im_gift_map3")
        res=R"gen_im_gift_map3.uti";
    if (sGiftTag == "gen_im_gift_map4")
        res=R"gen_im_gift_map4.uti";
    if (sGiftTag == "gen_im_gift_map5")
        res=R"gen_im_gift_map5.uti";
//morigan  18
//    if (sGiftTag == "gen_im_gift_grimoire")
//    if (sGiftTag == "gen_im_gift_flmgrimoire")
//    if (sGiftTag == "gen_im_gift_mirror")
    if (sGiftTag == "gen_im_gift_brooch")
        res=R"gen_im_gift_brooch.uti";
    if (sGiftTag == "gen_im_gift_locket")
        res=R"gen_im_gift_locket.uti";
    if (sGiftTag == "gen_im_gift_ncklace")
        res=R"gen_im_gift_ncklace.uti";
    if (sGiftTag == "gen_im_gift_ncklace2")
        res=R"gen_im_gift_ncklace2.uti";
    if (sGiftTag == "gen_im_gift_ncklace3")
        res=R"gen_im_gift_ncklace3.uti";
    if (sGiftTag == "gen_im_gift_ncklace4")
        res=R"gen_im_gift_ncklace4.uti";
    if (sGiftTag == "gen_im_gift_ncklace5")
        res=R"gen_im_gift_ncklace5.uti";
//oghern 25
    if (sGiftTag == "gen_im_gift_ale")
        res=R"gen_im_gift_ale.uti";
    if (sGiftTag == "gen_im_gift_fanbot")
        res=R"gen_im_gift_fanbot.uti";
    if (sGiftTag == "gen_im_gift_fanbot2")
        res=R"gen_im_gift_fanbot2.uti";
    if (sGiftTag == "gen_im_gift_fanbot3")
        res=R"gen_im_gift_fanbot3.uti";
    if (sGiftTag == "gen_im_gift_fanbot4")
        res=R"gen_im_gift_fanbot4.uti";
    if (sGiftTag == "gen_im_gift_fanbot5")
        res=R"gen_im_gift_fanbot5.uti";
    if (sGiftTag == "gen_im_gift_pitcher")
        res=R"gen_im_gift_pitcher.uti";
//stern 32
//    if (sGiftTag == "gen_im_gift_sword_sten")
    if (sGiftTag == "gen_im_gift_mdpnt1")
        res=R"gen_im_gift_mdpnt1.uti";
    if (sGiftTag == "gen_im_gift_mdpnt2")
        res=R"gen_im_gift_mdpnt2.uti";
    if (sGiftTag == "gen_im_gift_smlpnt1")
        res=R"gen_im_gift_smlpnt1.uti";
    if (sGiftTag == "gen_im_gift_smlpnt2")
        res=R"gen_im_gift_smlpnt2.uti";
    if (sGiftTag == "gen_im_gift_totem")
        res=R"gen_im_gift_totem.uti";
//wynne 37
    if (sGiftTag == "gen_im_gift_book")
        res=R"gen_im_gift_book.uti";
    if (sGiftTag == "gen_im_gift_book2")
        res=R"gen_im_gift_book2.uti";
    if (sGiftTag == "gen_im_gift_book4")
        res=R"gen_im_gift_book4.uti";
    if (sGiftTag == "gen_im_gift_book5")
        res=R"gen_im_gift_book5.uti";
    if (sGiftTag == "gen_im_gift_tatbook")
        res=R"gen_im_gift_tatbook.uti";
    if (sGiftTag == "gen_im_gift_fanscrl")
        res=R"gen_im_gift_fanscrl.uti";
    if (sGiftTag == "gen_im_gift_wine")
        res=R"gen_im_gift_wine.uti";
//zevran 44
//    if (sGiftTag == GEN_IM_GIFT_DALISH_GLOVES)
//    if (sGiftTag == GEN_IM_GIFT_ANTIVAN_BOOTS)
    if (sGiftTag == "gen_im_gift_mgold")
        res=R"gen_im_gift_mgold.uti";
    if (sGiftTag == "gen_im_gift_msilver")
        res=R"gen_im_gift_msilver.uti";
    if (sGiftTag == "gen_im_gift_sgold")
        res=R"gen_im_gift_sgold.uti";
    if (sGiftTag == "gen_im_gift_ssilver")
        res=R"gen_im_gift_ssilver.uti";
//other 48
    if (sGiftTag == "gen_im_gift_armband")
        res=R"gen_im_gift_armband.uti";
    if (sGiftTag == "gen_im_gift_bracer")
        res=R"gen_im_gift_bracer.uti";
    if (sGiftTag == "gen_im_gift_brclet")
        res=R"gen_im_gift_brclet.uti";
    if (sGiftTag == "gen_im_gift_brclet2")
        res=R"gen_im_gift_brclet2.uti";
    if (sGiftTag == "gen_im_gift_cake")
        res=R"gen_im_gift_cake.uti";
    if (sGiftTag == "gen_im_gift_dppant")
        res=R"gen_im_gift_dppant.uti";
    if (sGiftTag == "gen_im_gift_earring")
        res=R"gen_im_gift_earring.uti";
    if (sGiftTag == "gen_im_gift_earring2")
        res=R"gen_im_gift_earring2.uti";
    if (sGiftTag == "gen_im_gift_hdband")
        res=R"gen_im_gift_hdband.uti";
    if (sGiftTag == "gen_im_gift_paintsky")
        res=R"gen_im_gift_paintsky.uti";
    if (sGiftTag == "gen_im_gift_ring")
        res=R"gen_im_gift_ring.uti";
    if (sGiftTag == "gen_im_gift_ring2")
        res=R"gen_im_gift_ring2.uti";
    if (sGiftTag == "gen_im_gift_ring3")
        res=R"gen_im_gift_ring3.uti";
    if (sGiftTag == "gen_im_gift_ring4")
        res=R"gen_im_gift_ring4.uti";
    if (sGiftTag == "gen_im_gift_ring5")
        res=R"gen_im_gift_ring5.uti";
    if (sGiftTag == "gen_im_gift_tiara")
        res=R"gen_im_gift_tiara.uti";
    if (sGiftTag == "gen_im_gift_trbneck")
        res=R"gen_im_gift_trbneck.uti";
    if (sGiftTag == "gen_im_gift_tyarn")
        res=R"gen_im_gift_tyarn.uti";
//dog 66
    if (sGiftTag == "gen_im_gift_dogbone")
        res=R"gen_im_gift_dogbone.uti";
    if (sGiftTag == "gen_im_gift_dogbone2")
        res=R"gen_im_gift_dogbone2.uti";
    if (sGiftTag == "gen_im_gift_dogbone3")
        res=R"gen_im_gift_dogbone3.uti";
    if (sGiftTag == "gen_im_gift_dogbone4")
        res=R"gen_im_gift_dogbone4.uti";
    if (sGiftTag == "gen_im_gift_dogbone5")
        res=R"gen_im_gift_dogbone5.uti";
        //71 without the special ones
    return res;
}

A conversion function StringToResource starting to sound like a good idea right about now hehe.

Approval function: valeria_approval

You can change these bounds for the plot skills to anything you wish. I have them at 65,75,85 and 95.

void valeria_approval()
{
    object oPC=GetHero();
    object oFollower=UT_GetNearestObjectByTag(oPC, "valeria_npc");
// what you see here is something that needs to be done, in order you 
//don't get bugs and lose Valeria's true approval rating
//give your PC an item before valeria joins, and use a local variable 
//there to hold the true approval rating. i use the thief writ you get 
//when you first release her by talking to Jaltair(guildmaster)
    object [] thiefwrit=GetItemsInInventory(oPC,GET_ITEMS_OPTION_BACKPACK,0,"valeria_thief_contract");
    object thiefwrit1=thiefwrit[0];
    int nApproval=GetFollowerApproval(oFollower);
    SetLocalInt(thiefwrit1,ITEM_COUNTER_1,nApproval);
    int trueapproval=GetLocalInt(thiefwrit1,ITEM_COUNTER_1);
// up to to here
    if(trueapproval<65)
    {
        give_valeria_skill(oFollower,0);
    }
    if(trueapproval>=65 && trueapproval<75)
    {
//        SetFollowerApprovalDescription
        give_valeria_skill(oFollower,1);
    }
    if(trueapproval>=75 && trueapproval<85)
    {
        give_valeria_skill(oFollower,2);
    }
    if(trueapproval>=85 && trueapproval<95)
    {
        give_valeria_skill(oFollower,3);
    }
//I only change the description if over 95 to friendly because the 
//game won't do it, when we load the game (see below), we have to redo this...
    if(trueapproval>=95)
    {
        int nStringRef = GetM2DAInt(TABLE_APPROVAL_NORMAL_RANGES, "StringRef", APP_RANGE_FRIENDLY);
        SetFollowerApprovalDescription(oFollower, nStringRef);
        give_valeria_skill(oFollower,4);
    }
}

Approval function: give_valeria_skill

This one gives/takes the right plot skill, depending on current approval rating. I have to take care of all 4 possible class cases for Valeria. You'd probably need only one set of these.

void give_valeria_skill(object oval,int level)
{
   int doit=0;
   if(WR_GetPlotFlag(PLT_VALERIA_NPC_HIRE,ISROGUEWARRIOR))
   {
    doit=1;
   }
//warrior
   if(doit || WR_GetPlotFlag(PLT_VALERIA_NPC_HIRE,ISWARRIOR))
   {
    if(level==0)
    {
     RemoveAbility(oval, valeria_nAbility_warshow);
        RemoveAbility(oval, valeria_nAbility1war);
        RemoveAbility(oval, valeria_nAbility2war);
        RemoveAbility(oval, valeria_nAbility3war);
        RemoveAbility(oval, valeria_nAbility4war);
     return;
    }
    AddAbility(oval, valeria_nAbility_warshow);
    if(!HasAbility(oval, valeria_nAbility1war) && level==1)
    {
        AddAbility(oval, valeria_nAbility1war, TRUE);
        RemoveAbility(oval, valeria_nAbility2war);
        RemoveAbility(oval, valeria_nAbility3war);
        RemoveAbility(oval, valeria_nAbility4war);
    }
    if(!HasAbility(oval, valeria_nAbility2war) && level==2)
    {
        AddAbility(oval, valeria_nAbility1war);
        AddAbility(oval, valeria_nAbility2war, TRUE);
        RemoveAbility(oval, valeria_nAbility3war);
        RemoveAbility(oval, valeria_nAbility4war);
    }
    if(!HasAbility(oval, valeria_nAbility3war) && level==3)
    {
        AddAbility(oval, valeria_nAbility1war);
        AddAbility(oval, valeria_nAbility2war);
        AddAbility(oval, valeria_nAbility3war, TRUE);
        RemoveAbility(oval, valeria_nAbility4war);
    }
    if(!HasAbility(oval, valeria_nAbility4war) && level==4)
    {
        AddAbility(oval, valeria_nAbility1war);
        AddAbility(oval, valeria_nAbility2war);
        AddAbility(oval, valeria_nAbility3war);
        AddAbility(oval, valeria_nAbility4war, TRUE);
    }
   }
 
//rogue
   if(doit || WR_GetPlotFlag(PLT_VALERIA_NPC_HIRE,ISROGUE)==TRUE)
   {
    if(level==0)
    {
     RemoveAbility(oval, valeria_nAbility_thiefshow);
        RemoveAbility(oval, valeria_nAbility1thief);
        RemoveAbility(oval, valeria_nAbility2thief);
        RemoveAbility(oval, valeria_nAbility3thief);
        RemoveAbility(oval, valeria_nAbility4thief);
     return;
    }
    AddAbility(oval, valeria_nAbility_thiefshow);
    if(!HasAbility(oval, valeria_nAbility1thief) && level==1)
    {
        AddAbility(oval, valeria_nAbility1thief, TRUE);
        RemoveAbility(oval, valeria_nAbility2thief);
        RemoveAbility(oval, valeria_nAbility3thief);
        RemoveAbility(oval, valeria_nAbility4thief);
    }
    if(!HasAbility(oval, valeria_nAbility2thief) && level==2)
    {
        AddAbility(oval, valeria_nAbility1thief);
        AddAbility(oval, valeria_nAbility2thief, TRUE);
        RemoveAbility(oval, valeria_nAbility3thief);
        RemoveAbility(oval, valeria_nAbility4thief);
    }
    if(!HasAbility(oval, valeria_nAbility3thief) && level==3)
    {
        AddAbility(oval, valeria_nAbility1thief);
        AddAbility(oval, valeria_nAbility2thief);
        AddAbility(oval, valeria_nAbility3thief, TRUE);
        RemoveAbility(oval, valeria_nAbility4thief);
    }
    if(!HasAbility(oval, valeria_nAbility4thief) && level==4)
    {
        AddAbility(oval, valeria_nAbility1thief);
        AddAbility(oval, valeria_nAbility2thief);
        AddAbility(oval, valeria_nAbility3thief);
        AddAbility(oval, valeria_nAbility4thief, TRUE);
    }
   }
 
//mage
   if(WR_GetPlotFlag(PLT_VALERIA_NPC_HIRE,ISMAGE)==TRUE)
   {
    if(level==0)
    {
     RemoveAbility(oval, valeria_nAbility_mageshow);
        RemoveAbility(oval, valeria_nAbility1mage);
        RemoveAbility(oval, valeria_nAbility2mage);
        RemoveAbility(oval, valeria_nAbility3mage);
        RemoveAbility(oval, valeria_nAbility4mage);
     return;
    }
    AddAbility(oval, valeria_nAbility_mageshow);
    if(!HasAbility(oval, valeria_nAbility1mage) && level==1)
    {
        AddAbility(oval, valeria_nAbility1mage, TRUE);
        RemoveAbility(oval, valeria_nAbility2mage);
        RemoveAbility(oval, valeria_nAbility3mage);
        RemoveAbility(oval, valeria_nAbility4mage);
    }
    if(!HasAbility(oval, valeria_nAbility2mage) && level==2)
    {
        AddAbility(oval, valeria_nAbility1mage);
        AddAbility(oval, valeria_nAbility2mage, TRUE);
        RemoveAbility(oval, valeria_nAbility3mage);
        RemoveAbility(oval, valeria_nAbility4mage);
    }
    if(!HasAbility(oval, valeria_nAbility3mage) && level==3)
    {
        AddAbility(oval, valeria_nAbility1mage);
        AddAbility(oval, valeria_nAbility2mage);
        AddAbility(oval, valeria_nAbility3mage, TRUE);
        RemoveAbility(oval, valeria_nAbility4mage);
    }
    if(!HasAbility(oval, valeria_nAbility4mage) && level==4)
    {
        AddAbility(oval, valeria_nAbility1mage);
        AddAbility(oval, valeria_nAbility2mage);
        AddAbility(oval, valeria_nAbility3mage);
        AddAbility(oval, valeria_nAbility4mage, TRUE);
    }
   }
}

Gift Handling function: handle_valeria_gift

void handle_valeria_gift(object oFollower,object oItem,int nApprovalChange)
{
    string sGiftTag = GetTag(oItem);
    int nSoundSet;
    int nApproval=GetFollowerApproval(oFollower);
//again read the true approval, see the valeria_approval script
    object [] thiefwrit=GetItemsInInventory(GetHero(),GET_ITEMS_OPTION_BACKPACK,0,"valeria_thief_contract");
    object thiefwrit1=thiefwrit[0];
    int trueapproval=GetLocalInt(thiefwrit1,ITEM_COUNTER_1);
//this checks to see if the current approval is not the true, which 
//means the core game scripts have changed her approval, so bring it
//back to what it was. also if approval is 100 take care for a really 
//nusty nusty nusty bug.
    if(nApproval!=trueapproval)
    {
        if(nApproval==100)
            nApprovalChange=100-trueapproval;
        if(GetMainControlled()==oFollower)
            AdjustFollowerApproval(oFollower,-nApprovalChange,TRUE);
    }
 
// accept only certain gifts, if it's not right return it
    if  (sGiftTag!="valeria_gift1" && sGiftTag!="valeria_gift2"  && sGiftTag!="valeria_gift3" &&  sGiftTag!="valeria_gift4" && sGiftTag!="valeria_gift5"  && sGiftTag!="valeria_gift6")
    {
        resource res=get_gift_resource(sGiftTag);
        UT_AddItemToInventory(res, 1,GetHero(),"",TRUE);
        PlaySoundSet(oFollower, SS_THREATEN);
        return;
    }
    nApproval=GetFollowerApproval(oFollower);
//depending on the gift type, add random approval
//fruit, vegetable
    if (sGiftTag=="valeria_gift1" || sGiftTag=="valeria_gift2")
    {
        nApprovalChange=1+Random(4);
    }
//uncle Ertin's contract, Medal of Messira
    if (sGiftTag=="valeria_gift3" || sGiftTag=="valeria_gift4")
    {
        nApprovalChange=5+Random(5);
    }
//portrait of her family, her sister's locket
    if (sGiftTag=="valeria_gift5" || sGiftTag=="valeria_gift6")
    {
        nApprovalChange=10+Random(5);
    }
//play appropriate soundset response
    if(nApprovalChange<=0)nSoundSet=SS_NO;
    else if(nApprovalChange>0 && nApprovalChange<=4) nSoundSet=SS_YES;
    else if(nApprovalChange>4 && nApprovalChange<=9) nSoundSet=SS_THANK_YOU;
    else nSoundSet=SS_CHEER;
 
    nApproval+=nApprovalChange;
    if(nApproval<-100)nApproval=-100;
    if(nApproval>100)nApproval=100;
    nApprovalChange=nApproval-trueapproval;
    AdjustFollowerApproval(oFollower,nApprovalChange,TRUE);
    PlaySoundSet(oFollower,nSoundSet);
    WR_DestroyObject(oItem);
    SetLocalInt(thiefwrit1,ITEM_COUNTER_1,GetFollowerApproval(oFollower));
 
//if approval is 100 return everything
    if(GetFollowerApproval(oFollower)==100 && trueapproval==100)
    {
        resource res=get_valeria_gift_resource(sGiftTag);
        UT_AddItemToInventory(res, 1,GetHero(),"",TRUE);
        PlaySoundSet(oFollower, SS_THREATEN);
    }
//give extra skill, if her approval is high or take it away
    trueapproval=GetLocalInt(thiefwrit1,ITEM_COUNTER_1);
    if(trueapproval<65)
    {
        give_valeria_skill(oFollower,0);
    }
    if(trueapproval>=65 && trueapproval<75)
    {
        give_valeria_skill(oFollower,1);
    }
    if(trueapproval>=75 && trueapproval<85)
    {
        give_valeria_skill(oFollower,2);
    }
    if(trueapproval>=85 && trueapproval<95)
    {
        give_valeria_skill(oFollower,3);
    }
    if(trueapproval>=95)
    {
        int nStringRef = GetM2DAInt(TABLE_APPROVAL_NORMAL_RANGES, "StringRef", APP_RANGE_FRIENDLY);
        SetFollowerApprovalDescription(oFollower, nStringRef);
        give_valeria_skill(oFollower,4);
    }
}

Handling the Event EVENT_TYPE_MODULE_LOAD

Add this in 'Event handling':

        case EVENT_TYPE_MODULE_LOAD:
        {
            object [] thiefwrit=GetItemsInInventory(oPC,GET_ITEMS_OPTION_BACKPACK,0,"valeria_thief_contract");
            object thiefwrit1=thiefwrit[0];
//get the true approval, and set the description appropriately
//has to be done, since the core game scripts do not have valeria in
//them to do it automatically
            int trueapproval=GetLocalInt(thiefwrit1,ITEM_COUNTER_1);
            if(trueapproval>=95)
            {
                int nStringRef = GetM2DAInt(TABLE_APPROVAL_NORMAL_RANGES, "StringRef", APP_RANGE_FRIENDLY);
                SetFollowerApprovalDescription(oVal, nStringRef);
            }
        }

Changing Valeria's approval in other parts of the game

In many places of the game you might want to drop or increase approval. Example: When you destroy the thief guild, Valeria is so pleased that her approval skyrockets. In a script you could have something like this:

    object ofollow = UT_GetNearestObjectByTag(oPC,"valeria_npc");
    AdjustFollowerApproval(ofollow,35,TRUE);
    valeria_approval();
//which means all approval functions, constants etc have be included 
//as a say valeria_approval_functions_h file to those scripts. Just 
//combine the appropriate functions that I've shown you here to create 
//that file.

Another way to do this (it's what the game uses of course), is through the approval plots. That allows you to change approval in dialogs as well. But then again, the game has full control of the approval scripts.

So I haven't done it, I always change her approval through scripts run from dialogs instead. I think you can easily add that though.

The potential problem and solutions

The aforementioned approach will have to be modified, so we can all use it. I have not thought about it hard.

Imagine if two mods do this, while the core game script runs only once. We would reduce say, Alistair's approval twice as much, as the approval value of the gift.

This occurs when we capture the event EVENT_TYPE_MODULE_HANDLE_GIFT:

        case EVENT_TYPE_MODULE_HANDLE_GIFT:
        {
            object oFollower = GetEventObject(ev, 0);
            object oItem = GetEventObject(ev, 1);
            int nApprovalChange = GetEventInteger(ev, 0);  
            string sGiftTag = GetTag(oItem);
            if(GetTag(oFollower)!="valeria_npc")//<--HERE
            {
                if(sGiftTag=="valeria_gift1"  || sGiftTag=="valeria_gift2" 
                || sGiftTag=="valeria_gift3"  || sGiftTag=="valeria_gift4"
                || sGiftTag=="valeria_gift5"  || sGiftTag=="valeria_gift6")
                {
                    AdjustFollowerApproval(oFollower,-nApprovalChange,TRUE);
                    resource res=get_valeria_gift_resource(sGiftTag);
                    UT_AddItemToInventory(res, 1,GetHero(),"",TRUE);
                    PlaySoundSet(oFollower, SS_GIFT_NEGATIVE);
                }
            }
...
            break;
        }

A possible solution is the following but I have not implemented it. Have about 7-8 variables, as many as the original game npcs, and keep track of EVERYONE's approval. That way you can check to see if their approval has NOT changed from what its true value was before the gift handling event fired. If 1) Alistair's approval changed it means the core script run and we need to bring his approval to what it was. 2) his approval did not change it means either: a)the core script hasn't run yet or b) another mod run with the approach above and took his approval back.

There's an easy way to find out if another mod is present (2b), so you probably don't need all that. If you check the inventory for the item, if it is still there, it means another mod already returned it. I'll see if I can implement this at some point and update the wiki appropriately.


I'm sure if we think hard enough we can solve this easily and possibly in a more efficient way. I'll assume for now I'm done with the wiki and take a rest.

Joining The Party Compatible Companion Mod Creation Icon wiki arrow right disabled.png