Aller au contenu

Photo

How do you add multiple items with a single script?


  • Veuillez vous connecter pour répondre
22 réponses à ce sujet

#1
AdamTaylor

AdamTaylor
  • Members
  • 461 messages
So, I tried using weriKK's blog to make a couple of custom items.

Making the items was no problem.
But how do I script it to give me both items at once?
Or do you have to have an individual script for every item?

#2
Talian Kross

Talian Kross
  • Members
  • 239 messages
Strictly speaking, the script you are running (based on his/her tutorial) is 100% independent of the item you created. Think of it as a heartbeat script for your module (AddIn) as a whole. With that in mind so it's a little more clear to you what's going on, adding 2, 3, or numerous items is no different than adding just one.

In other words, just keep adding additional items just like you did the first one (as shown in his/her tutorial), i.e., for every item you want to add, do a...

(pseudo code)
if( CountItemsByTag( ... )  < 1 )
{
    UT_AddItemToInventory( ... )
}

Incidentally, his/her use of local variables to prevent repeated execution is 1.) redundant and unnecessary (the CountItemsByTag() prevents adding the item more than once), and 2.) incorrect as local variables need to be defined in a 2DA file if they are to be persistent, and he/she makes no mention of that. As written, it will just prevent execution within the current session, but once you reload a game, it gets executed again. So with that in mind, you can skip that part of the tutorial code.

NOTE: He/She probably knows that by now if you consider he/she wrote that tutorial practically the day the toolset was released.  He/she just hasn't bothered to update it I presume. :)

Modifié par Talian Kross, 16 novembre 2009 - 07:49 .


#3
Phaenan

Phaenan
  • Members
  • 315 messages
Also, if you wish to create several stackable items such as a pile of potions, you can simply create one single item then change the stack size. Something like this :
oPotion = CreateItemOnObject(R"resname", GetHero(), 1);
SetItemStackSize(oPotion, GetMaxItemStackSize(oPotion));
 // will fill the stack

Modifié par Phaenan, 16 novembre 2009 - 08:45 .


#4
hwlreckles

hwlreckles
  • Members
  • 44 messages
I'm not quite sure what you're asking because all you do is add another item right below the first.



if ( nHas == 0 ){

UT_AddItemToInventory(R"wep_mel_gs1_marius.uti");

UT_AddItemToInventory(R"wep_mel_ls1_marius.uti");





Just go down line adding more, if you want to have duplicates of an item then,



UT_AddItemToInventory(R"gen_im_qck_book_talentm.uti",10);

#5
weriKK

weriKK
  • Members
  • 106 messages

Talian Kross wrote...

NOTE: He/She probably knows that by now if you consider he/she wrote that tutorial practically the day the toolset was released.  He/she just hasn't bothered to update it I presume. :)


He knows :) I am trying to update it since a couple of days now just well.. it seems fate works against me :)

But it is coming. I've learned a lot since then, it should be a much more precise and easier to follow guide once it is done.

Just to make sure this post contains some useful information too, if you read through the comments of my guide or the discussion boards of the related project, there are many people with many good ideas helping others to solve issues and make things like this happen, which is really awesome.

Modifié par weriKK, 16 novembre 2009 - 10:51 .


#6
Talian Kross

Talian Kross
  • Members
  • 239 messages

if ( nHas == 0 ){
UT_AddItemToInventory(R"wep_mel_gs1_marius.uti");
UT_AddItemToInventory(R"wep_mel_ls1_marius.uti");

That would produce duplicates. nHas may equal 0 for your "wep_mel_gs1_marius.uti" greatsword, but then you would also get the longsword whether you had one already or not. <_<

#7
weriKK

weriKK
  • Members
  • 106 messages
Just so we have a working example here, in case some people learn easier looking at one, you can add multiple different items like this:

object oCharacter = GetHero();

        // 1) Add an item
        int nHas0 = CountItemsByTag(oCharacter, "wep_mel_gs1_marius");
        if ( nHas0 == 0 )
        {
                UT_AddItemToInventory(R"wep_mel_gs1_marius.uti");
        }
        // End of 1)
        
        // 2) Add two of this other item
        int nHas1 = CountItemsByTag(oCharacter, "wep_mel_ls1_marius");
        if ( nHas1 == 0 )
        {
                UT_AddItemToInventory(R"wep_mel_ls1_marius.uti", 2)
        }
        // End of 2)
        
        // 3) Add another item ...
        int nHas2 = ....

And so on and so forth

Modifié par weriKK, 17 novembre 2009 - 12:03 .


#8
Talian Kross

Talian Kross
  • Members
  • 239 messages
Or better yet, make it a  function. :P

/*--------------------*/

void MyAddItem( object p_oCreature, string p_tagItem, resource p_resItem, int p_nCount = 1 );

void main()
{
    // (snip)
    
    MyAddItem( oCharacter, "wep_mel_gs1_marius", R"wep_mel_gs1_marius.uti" );
    MyAddItem( oCharacter, "wep_mel_ls1_marius", R"wep_mel_ls1_marius.uti" );
    
    // (snip)
}

void MyAddItem( object p_oCreature, string p_tagItem, resource p_resItem, int p_nCount = 1 )
{
    //  paranoia check
    if( !IsObjectValid( p_oCreature ) )
        return;

    int nHas = CountItemsByTag( p_oCreature, p_tagItem );
    if( nHas == 0 )
    {
         UT_AddItemToInventory( p_resItem, p_nCount );
    }
}

/*--------------------*/

(Stupid forum software and its inability to format code blocks correctly.)

Modifié par Talian Kross, 17 novembre 2009 - 12:50 .


#9
hwlreckles

hwlreckles
  • Members
  • 44 messages
I should have just posted my entire script. What I posted works for my script.



//// ---------- Script Starts Here ----------



#include "utility_h"

#include "wrappers_h"

#include "events_h"



void main()

{



event ev = GetCurrentEvent();

int nEventType = GetEventType(ev);



object oPC = GetHero();



int nDoOnce = GetLocalInt(OBJECT_SELF, "MARIUS_GS1_GIVEN");



if ( nDoOnce != 1 )

{

switch(nEventType)

{



case EVENT_TYPE_MODULE_LOAD:

{



int nHas = CountItemsByTag(oPC, "wep_mel_gs1_marius");



// If no greatsword then add all this stuff

if ( nHas == 0 ){

UT_AddItemToInventory(R"wep_mel_gs1_marius.uti");

UT_AddItemToInventory(R"wep_mel_ls1_marius.uti");

UT_AddItemToInventory(R"wep_mel_ls2_marius.uti",10);

UT_AddItemToInventory(R"arm_chest_spell_marius.uti");

UT_AddItemToInventory(R"wep_spell_staff_marius.uti");

UT_AddItemToInventory(R"wep_spell_staff2_marius.uti");

UT_AddItemToInventory(R"wep_rng_bow_marius.uti");

UT_AddItemToInventory(R"arm_chest_mass1_marius.uti");

UT_AddItemToInventory(R"arm_helm_mass1_marius.uti");

UT_AddItemToInventory(R"arm_feet_mass1_marius.uti");

UT_AddItemToInventory(R"arm_hands_mass1_marius.uti");

UT_AddItemToInventory(R"acc_ring_spell_marius.uti");

UT_AddItemToInventory(R"acc_ring_spell_marius.uti");

UT_AddItemToInventory(R"gen_im_qck_book_talentm.uti",10);

UT_AddItemToInventory(R"gen_im_qck_book_talentw.uti");

UT_AddItemToInventory(R"gen_im_qck_book_attribute2.uti",10);

UT_AddItemToInventory(R"wep_mel_shield1_marius.uti");

UT_AddItemToInventory(R"wep_mel_shield2_marius.uti");

UT_AddItemToInventory(R"wep_spell_ls_marius.uti");

UT_AddItemToInventory(R"wep_shield_mage_marius.uti");

UT_AddItemToInventory(R"acc_ring_mel_marius.uti");

UT_AddItemToInventory(R"arm_spell_boots_marius.uti");

UT_AddItemToInventory(R"arm_spell_chest_marius.uti");

UT_AddItemToInventory(R"arm_spell_gloves_marius.uti");

UT_AddItemToInventory(R"arm_spell_helm_marius.uti");

UT_AddItemToInventory(R"gen_im_qck_book_skill.uti",5);

}

break;

}

}



SetLocalInt(OBJECT_SELF,"MARIUS_GS1_GIVEN", 1);

}



}

// ---------- Script Ends Here ----------





It simply checks to see if the greatsword is in my inventory. If not then it adds all that ****. So if I want the script to be ran again and get more of the items all I have to is destroy the greatsword or pass it to a party member and swap tem out. Then I quicksave and quick load and boom all the items in my inventory again.

#10
weriKK

weriKK
  • Members
  • 106 messages
I like this, let's keep iterating for greater success!

/*--------------------*/

#include "wrappers_h"
#include "utility_h"

void MyAddItem( resource p_resItem, int p_nCount = 1 );

void main()
{
    MyAddItem( R"wep_mel_gs1_marius.uti" );
    MyAddItem( R"wep_mel_ls1_marius.uti", 2 );
}

void MyAddItem( resource p_resItem, int p_nCount = 1 )
{
    //  paranoia check            
    object oCreature = GetMainControlled();
    if( !IsObjectValid( oCreature ) )
        return;

    if( !CountItemsByTag( oCreature, ResourceToTag(p_resItem) ) )
    {
         UT_AddItemToInventory( p_resItem, p_nCount );
    }
}

/*--------------------*/

Modifié par weriKK, 17 novembre 2009 - 01:26 .


#11
AND04

AND04
  • Members
  • 154 messages

weriKK wrote...

I like this, let's keep iterating for greater success!


hmm i would do it like this - its even safer ;)
+ we can check if we added something

/*--------------------*/

#include "wrappers_h"
#include "utility_h"

int MyAddItem( resource p_resItem, int p_nCount = 1 );

void main()
{
    MyAddItem( R"wep_mel_gs1_marius.uti" );
    MyAddItem( R"wep_mel_ls1_marius.uti", 2 );
}

int MyAddItem( resource p_resItem, int p_nCount = 1 )
{
    //  paranoia check
    object[] oChar = GetPartyPoolList();
    int nSize = GetArraySize(oChar);
    int i;
    object oCurrent;
    int nHasItem= 0;

      for(i = 0; i < nSize; i++)
       {
           oCurrent = oChar[i];
           if( IsObjectValid( oCurrent ) )
           nHasItem += CountItemsByTag(oCurrent, ResourceToTag(p_resItem));
       }

        if ( nHasItem == 0 )
       {           
           UT_AddItemToInventory( p_resItem, p_nCount );
           return TRUE;
       }  
       else 
       return FALSE;
}

/*--------------------*/

Modifié par AND04, 17 novembre 2009 - 01:44 .


#12
weriKK

weriKK
  • Members
  • 106 messages
Hm, I thought the party inventory is shared, do we really need to check it for every party member?
Now if we were checking for equipped items too, that's another story.

/*--------------------*/

#include "wrappers_h"
#include "utility_h"

int MyAddItem( resource p_resItem, int p_nCount = 1 );

void main()
{
    MyAddItem( R"wep_mel_gs1_marius.uti" );
    MyAddItem( R"wep_mel_ls1_marius.uti", 2 );
}

int MyAddItem( resource p_resItem, int p_nCount = 1 )
{
    //  paranoia check
    object[] oChar = GetPartyPoolList();
    int      nSize = GetArraySize(oChar);
    string   strItemTag = ResourceToTag(p_resItem);
    object   oItem = GetObjectByTag(strItemTag);
    int i;
    int j;
    object oCurrent;
    int nHasItem= 0;

      for(i = 0; i < nSize; i++)
       {
           oCurrent = oChar[i];
           if ( IsObjectValid( oCurrent ) )
           {
                // If item is in the shared inventory
                nHasItem += CountItemsByTag(oCurrent, ResourceToTag(p_resItem));

                if ( !nHasItem )
                {
                    // If item is not in the shared inventory
                    // maybe it is equipped
                    for ( j = 524288; j > 0; j>>=1 )
                    {
                        if ( GetTag(GetItemInEquipSlot(j, oCurrent)) == strItemTag )
                            nHasItem += 1;
                    }
                }
           }
       }

       if ( nHasItem == 0 )
       {          
           UT_AddItemToInventory( p_resItem, p_nCount );
           return TRUE;
       } 
       else
       return FALSE;
}

/*--------------------*/

Modifié par weriKK, 17 novembre 2009 - 03:15 .


#13
AND04

AND04
  • Members
  • 154 messages

weriKK wrote...

Hm, I thought the party inventory is shared, do we really need to check it for every party member?
Now if we were checking for equipped items too, that's another story.


The Count Items by tag includes equipped items (and yes i usually check for equiped ones too)

but true we could do a general inventory check on GetHero() and if we didn't find the item then check the others

Modifié par AND04, 17 novembre 2009 - 03:32 .


#14
weriKK

weriKK
  • Members
  • 106 messages
Well there you go, I had no idea of that. In that case, my version is kind of an overkill:)

Edit2: but wait a minute, if the inventory is shared and CountItemsByTag() checks the equipped items too, calling it for every party member will count the items from the inventory multiple times? Not that it matters in this context but hey-ho! :PP

Modifié par weriKK, 17 novembre 2009 - 03:39 .


#15
AND04

AND04
  • Members
  • 154 messages

weriKK wrote...

Well there you go, I had no idea of that. In that case, my version is kind of an overkill:)


it is shared - i was checking the equiped items of all other party(pool) members - but i could have aborted if its allready in the shared one - btw the curent script doesn't check for the item count we give the function but just if it exists

edit: well i am off to bed now - 4 am and geting a lil tired ;)

Modifié par AND04, 17 novembre 2009 - 03:38 .


#16
weriKK

weriKK
  • Members
  • 106 messages

AND04 wrote...
btw the curent script doesn't check for the item count we give the function but just if it exists;)


Damn, you are right! It might be a good time to refactor that item counter part too.

Hm, actually it is late indeed.

#17
Talian Kross

Talian Kross
  • Members
  • 239 messages

AND04 wrote...

but true we could do a general inventory check on GetHero() and if we didn't find the item then check the others


And to the others stumbing in on this thread and perhaps getting wide-eyed at the growing and growing complexity of such a seemly simplistic task,  let us not forget that weriKK's original blog entry tutorial was (and is) based only giving the player an item, so checking the hero's inventory is all that is required.

(I only throw this out there because from a distance, it could appear that we are beating up on poor weriKK and his original implementation.  I'm still amazed that not only did he figure out the basics almost instantly, but he managed to do a write up about it as well--all within hours of the toolset's release!  Outstanding stuff, that.)


#18
weriKK

weriKK
  • Members
  • 106 messages
Yeah, we are going off topic insanely fast here, it's just kind of fun to thinker about this, can't help it :/



That guide has many flaws looking back at it now, considering how many people have read it I should really update it and I think I will do it tomorrow, even though procrastination is my middle name.

#19
AND04

AND04
  • Members
  • 154 messages

weriKK wrote...

AND04 wrote...
btw the curent script doesn't check for the item count we give the function but just if it exists;)


Damn, you are right! It might be a good time to refactor that item counter part too.

Hm, actually it is late indeed.


+ maybe add a parameter that tells us what and if we want to check at all:


const int MYADDITEM_CHECK_ALL = 0; // check the Hero and all followers
const int MYADDITEM_CHECK_HERO = 1; // check just the hero
const int MYADDITEM_CHECK_NONE = 2; // no check just add the item(s)

const int MYADDITEM_ADD_TILLCOUNT= 0; // if we just want to restock an item to the given value
const int MYADDITEM_ADD_EXACTCOUNT = 1; // if we want to give the player excactly the count - usually no checks are nessecary then

*--------------------*/

#include "wrappers_h"
#include "utility_h"

int MyAddItem( resource p_resItem, int p_nCount = 1, int p_nCheck = 0, int p_nAdd = 0);



i believe you get where i am going - we best put that then in a seperate file and "#include" it in our module.

Modifié par AND04, 17 novembre 2009 - 02:22 .


#20
weriKK

weriKK
  • Members
  • 106 messages
How about something like this:

/*--------------------*/

#include "wrappers_h"
#include "utility_h"

const int CHECK_ALL  = 0;
const int CHECK_HERO = 1;
const int ADD_RESTOCK  = 0;
const int ADD_FORCEADD = 1;

int MyAddItem( resource p_resItem, int p_nCount = 1, int p_nMode = ADD_RESTOCK, int p_nFilter = CHECK_ALL );
int CountItems( string p_strItemTag, int p_nCountFilter = CHECK_ALL );

void main()
{  
   MyAddItem( R"gen_im_wep_mel_mac_drk.uti" );
   MyAddItem( R"gen_im_wep_mel_mac_drk.uti", 2 );
}

int MyAddItem( resource p_resItem, int p_nCount = 1, int p_nMode = ADD_RESTOCK, int p_nFilter = CHECK_ALL )
{
    // Argument checks
    if ( p_nCount <= 0 )
        return 0;
        
    if ( p_nMode < ADD_RESTOCK || p_nMode > ADD_FORCEADD )
        p_nMode = ADD_RESTOCK;
        
    if ( p_nFilter < CHECK_ALL || p_nFilter > CHECK_HERO )
        p_nFilter = CHECK_HERO;        
        
    if ( p_nMode == ADD_RESTOCK )
    {
        int nHasItems = CountItems( ResourceToTag( p_resItem ), p_nFilter );
        int nAddItems = p_nCount-nHasItems;

        if ( nAddItems > 0 )
        { 
            UT_AddItemToInventory( p_resItem, nAddItems, GetHero() );
            return nAddItems;
        }
        else
            return 0;
    }
    else if ( p_nMode == ADD_FORCEADD )
    {
        UT_AddItemToInventory( p_resItem, p_nCount, GetHero() );
        return p_nCount;        
    }
    
    return 0;
}

int CountItems( string p_strItemTag, int p_nCountFilter = CHECK_ALL )
{
    // Argument check
    if ( p_nCountFilter > CHECK_HERO || p_nCountFilter < CHECK_ALL ) 
        p_nCountFilter = CHECK_ALL;
        

    object[] oChar = GetPartyPoolList();
    int      nSize = GetArraySize( oChar );
    int      nItemCount;
    object   oCurrent;
    int i;
    int j;

    nItemCount = CountItemsByTag( GetHero(), p_strItemTag ); 
    
    if ( p_nCountFilter == CHECK_HERO )
        return nItemCount;

    for( i = 0; i < nSize; i++ )
         if ( IsObjectValid( oChar[i] ) )
            for ( j = 0; j < 20; j++ )
                if ( GetTag( GetItemInEquipSlot( j, oChar[i] ) ) == p_strItemTag )
                    nItemCount += 1;
                    
    return nItemCount;
}

/*--------------------*/


#21
AND04

AND04
  • Members
  • 154 messages
looks nice - though i would add some prefix to our const variables - seeing as this should become some kind of "standard-add function" and we should avoid names that could allready be used by somehting else (unless we don't want to go the #include "MyAddItem" way)

#22
weriKK

weriKK
  • Members
  • 106 messages
And so http://social.bioware.com/group/694/ was born :)

#23
quantumraider

quantumraider
  • Members
  • 37 messages
I'm not a coder but following the thought processes of coders I do find interesting :P



Plus I may be able to use some of the scripts at some point :)