Usable campaign items tutorial

From Dragon Age Toolset Wiki
Jump to: navigation, search

This is how to make a usable item (such as a sword or a helmet) that is also vital to the plot.

The problem with regular Plot items is that they're really just tokens that can't be used for anything.

Item Template

Set the item variable ITEM_SEND_ACQUIRED_EVENT to 1.

Module Script

The item variable we just set will trigger a module event when the player acquires the item.

At minimum, we probably want to stop the player destroying the item, so the module event script will include

         case EVENT_TYPE_CAMPAIGN_ITEM_ACQUIRED:
         {
            object oAcquirer     = GetEventCreator(ev);
            object oItem         = GetEventObject(ev, 0);
            string sItem         = GetTag(oItem);
 
            // Make item indestructible
 
            SetItemIndestructible(oItem, TRUE);
 
            // Set plot flags if required (sItem tells us which item has been acquired)
 
            break;
         }

Merchants

We probably don't want to allow the player to sell campaign items.

NOTE: The solution adopted here assumes that event handling is not possible while a merchant is open. It has recently been reported that ToggleGamePause(FALSE) enables event handling, so there might be an easier way.

Here, a custom version of the "open store" plot script is used to store the campaign items in a temporary placeable.

Returning the items to the player is delayed until the next AI update, which happens after the store closes (there's no explicit event for this).

          case COC_GENERAL_OPEN_STORE:
            {
              object    oPlayer = GetHero();
              object    oStore  = GetObjectByTag("store_" + GetTag(oConversationOwner));
              object    oBin;
              object [] oItemTable;
              object    oItem;
              int       nItemCount;
              int       nGetItemsOption = GET_ITEMS_OPTION_BACKPACK;
              int       i               = -1;
 
              if (!IsObjectValid(oStore))
                {
                  Log_Trace(LOG_CHANNEL_SYSTEMS, GetCurrentScriptName(), "INVALID STORE OBJECT");
                  break;
                }
 
              // Hide campaign items (so they can't be sold).
 
              oBin = CreateObject(OBJECT_TYPE_PLACEABLE, R"cocip_bin.utp", GetLocation(GetHero()));  // Almost any placeable template will do
              SetTag(oBin, "cocip_campaign_items");
 
              oItemTable = GetItemsInInventory(oPlayer, nGetItemsOption);
              nItemCount = GetArraySize(oItemTable);
 
              while (++i < nItemCount)
                {
                  oItem = oItemTable[i];
 
                  if (GetLocalInt(oItem, ITEM_SEND_ACQUIRED_EVENT))                        
                    MoveItem(oPlayer, oBin, oItem);
                }
 
              // Schedule an event to return campaign items to the player at the next AI update
 
              DelayEvent(0.0, oPlayer, Event(EVENT_TYPE_INVALID), "coc_restore_campaign_items");
 
              // Open store
 
              ScaleStoreItems(oStore);
              OpenStore(oStore);
              break;
            }

The delayed script coc_restore_campaign_items looks like this:

// Restore campaign items to the player
//
// Campaign items were removed from inventory while the player was trading with a merchant.
// Now they are returned.
//
// Proleric 08-Dec-2010
//
 
#include "log_h"
#include "utility_h"
#include "wrappers_h"
#include "plot_h"
 
void main()
{
  object    oPlayer = GetHero();
  object    oBin    = GetObjectByTag("cocip_campaign_items");
  object [] oItemTable;
  object    oItem;
  int       nItemCount;
  int       nGetItemsOption = GET_ITEMS_OPTION_BACKPACK;
  int       i               = -1;
 
  if (IsObjectValid(oBin))
    {
      oItemTable = GetItemsInInventory(oBin, nGetItemsOption);
      nItemCount = GetArraySize(oItemTable);
 
      while (++i < nItemCount)
        {
          oItem = oItemTable[i];
          MoveItem(oBin, oPlayer, oItem);
        }
 
      WR_DestroyObject(oBin);
    }
}

Lost Items

If your campaign allows items to be lost by other means (such as a camp storage chest), you may want to set the ITEM_SEND_LOST_EVENT variable on the item. This can be intercepted in the EVENT_TYPE_CAMPAIGN_ITEM_LOST module event to control what happens.

Dismissed Followers

If your campaign allows the player to dismiss followers without being able to get them back easily, you might want to check if the follower being fired has a campaign item equipped. Either notify the player, or move it to the shared inventory space automatically.