Aller au contenu

Photo

Get Random Follower from Pool


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

#1
Karma

Karma
  • Members
  • 391 messages

I know there is a scripting function that allows us to randomly select a member of the party (I assume this means a member of the active party), but I would like to select a random follower from the party pool. More particularly, I'd like to select the random follower from a pool of ID numbers from an M2DA (the row IDs will probably not be consecutive integers from 0 to whatever). I can think of a couple ways to do it, but neither seems very efficient. Is there a "best practice" method of doing this?

 

EDIT: More specific question... Does GetM2DAString() et al use the actual row number or does it use the ID number from the first column?



#2
Sunjammer

Sunjammer
  • Members
  • 925 messages
GetM2DAString uses the ID number but GetM2DARowIdFromRowIndex will give the ID.

So normally the approach is to get the total number of rows in the M2DA; for each row (i.e. 0 to nRows - 1) get the actual ID for the entry using GetM2DARowIdFromRowIndex; then use the ID with the other M2DA functions as required. However as you only want one at random you can forego the loop and just pass the number of rows into Random and the look up the number it returns to give you at ID.

#3
Karma

Karma
  • Members
  • 391 messages

So let's say that the follower who was randomly selected isn't available. How do I loop it back around and select a different and available follower? It doesn't necessarily have to be another random selection (since, unless I'm mistaken, the random function can't omit numbers); at that point, it could be the next available follower.



#4
Sunjammer

Sunjammer
  • Members
  • 925 messages

Two ways I can see of doing this:

  1. Select one at random each time and use a while (or do ... while) loop to keep searching until you have the ID of an available companion. You can use tag, resource or actual object of an available companion as your loop. Of course if none are available you risk and infinite loop so you might need a second condition to break out after a number of attempts.
  2. Use a for loop to iterate through all the companions and store their ID in a temporary array, then select an array index random and retrieve that ID (it's guaranteed to be available). If there aren't any available companions then your array will be empty.

EDIT: I've updated the GetM2DARowIdFromRowIndex page with an example.



#5
Karma

Karma
  • Members
  • 391 messages

My understanding of arrays is limited, so this is what I came up with. It compiles, which is weird, because it shouldn't. I'm sure something needs to be fixed, but am I at least on the right track for what you suggested in #2?

 

 


    object [] arPool = GetPartyPoolList();
    int nSize = GetArraySize(arPool);
    int [] arAvailablePool;
    int i;
    object oCurrent;

    for(i = 0; i < nSize; i++)
    {
        oCurrent = arPool[i];

        if(!IsHero(oCurrent) && !IsSummoned(oCurrent) && !IsFollowerVanilla(oCurrent) && GetFollowerState(oCurrent, FOLLOWER_STATE_AVAILABLE))
        {                                   
            arAvailablePool [i] = GetM2DARowIdFromRowIndex(CCC_TABLE_CAPTURED, i);
        }
    }

    int nRandom = Random(GetArraySize(arAvailablePool));
    nFollowerID = arAvailablePool[nRandom];

    string sFollowerTag = GetM2DAString(CCC_TABLE_CAPTURED, CCC_COL_FOLLOWER_TAG, nFollowerID);
    string sPlot = GetM2DAString(CCC_TABLE_CAPTURED, CCC_COL_PARTY_PLOT, nFollowerID);
    int nFlag = GetM2DAInt(CCC_TABLE_CAPTURED, CCC_COL_IN_PARTY_FLAG, nFollowerID);    

    WR_SetFollowerState(GetObjectByTag(sFollowerTag), FOLLOWER_STATE_ACTIVE);
    WR_SetPlotFlag(sPlot, nFlag, TRUE);


#6
Sunjammer

Sunjammer
  • Members
  • 925 messages

I don't think you can use an object's position in the party pool in that way as it won't relate to your CCC_TABLE_CAPTURED M2DA. I would expect objects to appear in the PartyPool in the order (or the reverse order) they join your party whereas your M2DA is probably in a specific order. So while this may work for you it may not be reliable for others. As I recall BioWare have a look up functions to map the companion to an ID and back again.

 

I think what you want to do is tackle the problem the other way round. Assuming your CCC_TABLE_CAPTURED M2DA has all the relevant companions in it (even if spread over multiple fragments) then you should be able to do something like this:

    int nAvailable, nFollowerId, nRow;
    int[] nAvailableFollowerIds;
    object oFollower; 
    object[] oAvailableFollowers;
    string sFollowerTag;
    
    // get the size of the "captured" array
    int nRows = GetM2DARows(CCC_TABLE_CAPTURED);
    
    // loop through each entry in the "captured" array and build a list of available captives
    // NOTE: depending what the table contains the IsHero, IsSummond and IsFollowerVanilla checks
    // are probably not required so have been omited in this example. They should be added back as
    // necessary.
    for(nRow = 0; nRow < nRows; nRow++)
    {
        // convert the row number into an ID
        nFollowerId = GetM2DARowIdFromRowIndex(CCC_TABLE_CAPTURED, nRow);
        
        // get the companion's tag
        sFollowerTag = GetM2DAString(CCC_TABLE_CAPTURED, CCC_COL_FOLLOWER_TAG, nFollowerId);
        
        // companions, once joined, should be in the party or the char_stage so we can Get it by
        // its tag
        oFollower = GetObjectByTag(sFollowerTag); 
        
        // determine if the follower is a suitable candidate and, if so add them and their ID to
        // arrays: note we only need the ID but storing the object saves us retrieving it again
        if(GetFollowerState(oFollower) == FOLLOWER_STATE_AVAILABLE)
        {  
            nAvailableFollowerIds[nAvailable] = nFollowerId;
            oAvailableFollowers[nAvailable] = oFollower;
            nAvailable++;
        }
    }
    
    // select a companion at random
    // NOTE: by incrementing nAvailable after adding elements to both arrays it is equivalent to the 
    // size of the array so we can just use it as the basis for our random index
    int nRandom = Random(nAvailable);
               
    // retrieve the information stored in the "available" arrays
    oFollower = oAvailableFollowers[nRandom];
    nFollowerId = nAvailableFollowerIds[nRandom]; 
  
    // retireve the "in party" plot flag information from the M2DA
    string sPlot = GetM2DAString(CCC_TABLE_CAPTURED, CCC_COL_PARTY_PLOT, nFollowerId);
    int nFlag = GetM2DAInt(CCC_TABLE_CAPTURED, CCC_COL_IN_PARTY_FLAG, nFollowerId);    

    // activate the companion and add them to the party
    WR_SetFollowerState(oFollower, FOLLOWER_STATE_ACTIVE);
    WR_SetPlotFlag(sPlot, nFlag, TRUE);


#7
Karma

Karma
  • Members
  • 391 messages

Thanks. I'll give it a try this weekend.

 

EDIT: I made some small modifications to the script, and it appears to be working at least for my followers. I still need to test it to see if it works with multiple m2da fragments.

One more question though... In the wiki example you provided for GetM2DARowIdFromRowIndex(), you noted, "Random function gives a number between 0 and nRows - 1 however as the first row is invalid and the last row is a lyrium potion we actually want a number between 1 adn nRows," and you accommodated this by adding a "+1" to the Random() line. Is that necessary to do in this case assuming valid m2da rows start at 0? I'm assuming not, but I wanted to confirm.


  • luna1124 aime ceci

#8
Sunjammer

Sunjammer
  • Members
  • 925 messages
If you a random row from anywhere in the m2da then you are correct you can just use Random(nRows). It doesn't matter what the IDs start at. For example if you have 10 rows in an m2da with IDs 101 to 110 their indices will still be 0 to 9.

In my example I don't want the first row (because it is invalid) unfortunately there is a bug in my code as it should be Random(nRows - 1) + 1. Using the previous example of 10 rows my original code would have give an index between 1 and 10 but index 10 doesn't exist!

Off to fix it now ..
  • luna1124 aime ceci