Dragon Age: Origins

Stores open through dialog options which set a plot flag called "open store" in gen00pt_generic_actions, triggering the store interface to open.  That plot script refers to a function "ScaleStoreItems" in core_h.nss.  
Rather than edit core_h directly, requiring all scripts dependent on it to also be recompiled, I've created a new include file that only contains an edited version of ScaleStoreItems, and then changed gen00pt_generic_actions (and a few other store-opening plot scripts) to use my new function instead. 

~~original ScaleStoreItems function, unedited (except to remove logging)~~ 
~~my notes & edits
~~

void ScaleStoreItems(object oStore, int bReset = FALSE)
{
    // check for duplicate specialization books
    int nSpecialization;
    object [] oItems = GetItemsInInventory(oStore, GET_ITEMS_OPTION_ALL);
    int nSize = GetArraySize(oItems);
    int nCount = 0;
    string acvId;
    for (nCount = 0; nCount < nSize; nCount++)
    {
        nSpecialization = GetLocalInt(oItems[nCount], ITEM_SPECIALIZATION_FLAG);
        if (nSpecialization > 0)
        {
            acvId = GetM2DAString(TABLE_ACHIEVEMENTS, "AchievementID", nSpecialization);
            if (GetHasAchievement(acvId) == TRUE)
            {
                DestroyObject(oItems[nCount]);
            }
        }
    }

    // Remove backpack items from store if party's inventory size is already maximized.
    if (GetMaxInventorySize() >= 125)
    {
        RemoveItemsByTag(oStore, "gen_im_misc_backpack");
    }

    // Only scale the merchant the first time opened.
   REMOVED this check.  It doesn't seem to work anyway. (possibly due to a patch, but I can't find where)
    if (GetLocalInt(oStore, "MERCHANT_IS_SCALED") && !bReset)
    {
        return; 
    }

    SetLocalInt(oStore, "MERCHANT_IS_SCALED", 1);

    int nStoreBase = GetLocalInt(oStore, "MERCHANT_LEVEL_OVERRIDE");
   No stores actually seem to use this variable.  It appears to set a store to a specific, non-scaling level.

    int nStoreLevel;

    if (nStoreLevel > 0)
   possibly a mistake?  nStoreLevel has been initialized, but not set, so should always return INVALID (-1)
   CHANGED to if (nStoreBase > 0), but again, no stores actually seem to use nStoreBase.
    {
        nStoreLevel = nStoreBase;
    } else
    {
        nStoreLevel = GetLevel(GetHero());
        stores use player level as baseline
    }

    int nStoreLevelModifier = GetLocalInt(oStore, "MERCHANT_LEVEL_MODIFIER");
   a rare few are flagged to use player level + 1 or 2 as baseline instead

    // modify and enforce range
    nStoreLevel += nStoreLevelModifier;
    nStoreLevel = Max(nStoreLevel, 1);
    nStoreLevel = Min(nStoreLevel, 45);
    making sure stores don't get too high- or low-level
   
    int nItemType;
    int nMaterialProgression;
    int nRandomLevel;
    int nColumn;
    int nMaterial;

    float fHighChance = GetLocalFloat(oStore, "MERCHANT_HIGH_CHANCE");
    A few stores have this.  It varies a bit, but always seems to be <25% chance.
    int nHighModifier = 3;
    basically a guaranteed way to set a store's items 1 tier above player (formula below)
   
    nCount = 0;
    for (nCount = 0; nCount < nSize; nCount++)
    {
        // if appropriate type (armor, shield, melee weapon, ranged weapon)
        nItemType = GetItemType(oItems[nCount]);
        
        if ((nItemType == ITEM_TYPE_ARMOUR) || (nItemType == ITEM_TYPE_SHIELD) || (nItemType == ITEM_TYPE_WEAPON_MELEE) || (nItemType == ITEM_TYPE_WEAPON_RANGED))
       ADDED staves to this list. (called 'wands' as an ITEM_TYPE_)
      (coincidentally, the same oversight also occurs in the plot rewards system, but since very few staves are given as quest rewards, AND I'd only be able to fix the base game, I'm not bothering)

        {
            // if not unique
            if (GetItemUnique(oItems[nCount]) == FALSE)
           "unique"-flagged items are not supposed to scale.  IDK why, so I didn't change it.
            {
                // get material progression
                nMaterialProgression = GetItemMaterialProgression(oItems[nCount]);
               annoyingly, there is a "GetItemMaterialProgression" function but no "SetItemMaterialProgression".  -_-
                if (nMaterialProgression > 0)
                {
                    // find randomized level
                    nRandomLevel = nStoreLevel + Random(7) - 3;
                   REMOVED this.  Baseline store level is now the same as player level + MERCHANT_LEVEL_MODIFIER
                    
                    if (RandomFloat() < fHighChance)
                   giving certain stores an extra chance to have items 1 tier higher
                    {
                        nRandomLevel += nHighModifier;
                        SetLocalInt(oItems[nCount], "ITEM_RUNE_ENABLED", 1);
                       MOVED this outside the if{} so all stores enable runes.
                   materials start getting runes at tier 3 (around player level 7)

                    }

                    nRandomLevel = Max(1, nRandomLevel);
                    nRandomLevel = Min(45, nRandomLevel);
                   another check to make sure the store isn't too high- or low-level

                    // find material column
                   Item scaling is determined by that item's material progression; this is for checking that GDA table.
                    nColumn = ((nRandomLevel - 1) / 3) + 1;

                   Store items scale up 1 tier roughly every 3 player levels. (always rounds DOWN)
                Stores with MERCHANT_LEVEL_MODIFIER will have items the next tier up if the player is near that 3-level threshold.
                Stores with a successful MERCHANT_HIGH_CHANCE roll will always be next tier up.
                It's possible for some stores to have both, so items may be up to 2 tiers higher than the player.


                    nColumn = Max(1, nColumn);
                    nColumn = Min(15, nColumn);
                    making sure the tier falls somewhere in the material progression table (TS_materials.gda)
                 (there aren't actually 15 material tiers; after a certain #, they're all the maximum for that progression)


                    // get material
                    nMaterial = GetM2DAInt(TABLE_MATERIAL, "Material" + ToString(nColumn), nMaterialProgression);
                    getting the new material from the table
                    
                    // set material
                    SetItemMaterialType(oItems[nCount], nMaterial);
                   actually changing the item material.
                ADDED a check to make sure items only scale up, since it's common for a merchant to carry items that are by default above the player's level

                }  
            }
        }
    }
  }

Article information

Added on

Edited on

Written by

Shanamah

0 comments