Streamlining Quests

Got it. It’s GetFirstFactionMember() and GetNextFactionMember(); they have a “PC Only” parameter. Add a “, FALSE” to them, like this:

    // Start looking through the faction members.
    object oTarget = GetFirstFactionMember(oPC, FALSE);
        // Check the next faction member.
        oTarget = GetNextFactionMember(oPC, FALSE);
1 Like

@TheBarbarian - Saving the .mod now. I’ll let you know how it works. I’ll also login a second toon to see if it cycles to other PCs

Thank you!

1 Like


Although it doesn’t report what it’s taken from the henchman, the effect is outstanding.

Is there something I can place there to report what it’s taken from the hench?

1 Like

Yay!! :smiley:

Sure. RedeemBountyItemType looks like a likely candidate:

// Destroys all items tagged sTag possessed by oHasItem, and gives oGetsReward
// the XP and gold rewards times the amount of items found.
void RedeemBountyItemType(string sTag, int nGoldReward, int nXPReward, object oHasItem, object oGetsReward)
    object oItem = GetItemPossessedBy(oHasItem, sTag);
    int nBounty = DestroyItemsInInventory(oHasItem, sTag, 9999);
    GiveGoldToCreature(oGetsReward, nGoldReward * nBounty);
    GiveXPToCreature(oGetsReward, nXPReward * nBounty);

    SendMessageToPC(oGetsReward, IntToString(nBounty)+" '"+GetName(oItem)+"' on "+GetName(oHasItem)+" redeemed for "+IntToString(nGoldReward)+" each.");

Or you could turn RedeemBountyItemType into an int rather than having it be the void it currently is, and add all found items from all bounty item types together in RedeemAllBountyItems, if you just want a single “Redeemed n bounty items on (character)” message.

1 Like

It throws an error.


Is it because I haven’t defined what (oItem) is anywhere in this script?

I’d added a line for declaring and defining oItem at the top, first line in RedeemBountyItemType (that new one just now). Did you put that one in?

When one reads what someone has provided, instead of just looking for what one thinks is new, one sees that one is provided with more information than what one had expected…

My bad. I just copied the SendMessage line. Compiled great when Copy/Pasted with precision :slight_smile:

1 Like

! Add a check to make sure that you don’t get spammed with lots and lots of “0 ‘(Thing)’ on Bob redeemed for x gold.” messages:

if (nBounty)
    SendMessageToPC(etc etc...

“Of course… They’ll eat the egg plants”.

I am required to go do manual labor. So I am afk for some time.

Thank you very much for your input. This thing works awesome now :slight_smile:

1 Like

Ok… Is there any way I can have this script stop or pause the turn in based on the selection by the PC? Or to only turn in those items the PC wants? i.e. there are 25 types of items, and he may not want to turn in all 25.

Currently there are multiple scripts handling each item, and that’s what this script was intended to fix. But our player base may be discomfited by options being removed (see below)

Sure. It’d just require some more restructuring - and, an additional script per item.

Set up a new script per bounty item, which stores the tag and the rewards on the PC as local string and ints. This goes in the Actions Taken script of the ‘Collect on Kobold ears’ dialogue option.

void main()
    object oPC = GetPCSpeaker();
    SetLocalString(oPC, "BOUNTY_ITEM_TAG", "KoboldEar");
    SetLocalInt(oPC, "BOUNTY_GOLD_REWARD", 50);
    SetLocalInt(oPC, "BOUNTY_XP_REWARD",   50);

Then, in Actions Taken of the NPC’s immediate response, put a slightly modified version of the bounty redemption script we’ve put together to use RedeemBountyItemType directly, skipping over RedeemAllBountyItems, and use the stored local variables to get the tag and gold/xp reward amounts we just set.

void main()
    object oPC = GetPCSpeaker();
    string sTag     = GetLocalString(oPC, "BOUNTY_ITEM_TAG");
    int nGoldReward = GetLocalInt(oPC, "BOUNTY_GOLD_REWARD");
    int nXPReward   = GetLocalInt(oPC, "BOUNTY_XP_REWARD");

    DeleteLocalString(oPC, "BOUNTY_ITEM_TAG");
    DeleteLocalInt(oPC, "BOUNTY_GOLD_REWARD");
    DeleteLocalInt(oPC, "BOUNTY_XP_REWARD");

    // Redeem bounty items on the PC speaker.
    RedeemBountyItemType(sTag, nGoldReward, nXPReward, oPC, oPC);

    // Start looking through the faction members.
    object oTarget = GetFirstFactionMember(oPC, FALSE);
    // As long as a valid faction member continues to be found...
    while (oTarget != OBJECT_INVALID)
        // Only target faction members who are henchmen whose master is the PC speaker.
        if (GetAssociateType(oTarget) == ASSOCIATE_TYPE_HENCHMAN && GetMaster(oTarget) == oPC)
            // Redeem bounty items on the henchman.
            RedeemBountyItemType(sTag, nGoldReward, nXPReward, oTarget, oPC);

        // Check the next faction member.
        oTarget = GetNextFactionMember(oPC, FALSE);

Will this store all the items to be turned in until the end of the conversation, and then “redeem” them all at once? Or does it store the first item and very quickly redeem it, then do the same for the second, etc?

I may just have to console the players. :slight_smile:

Also, I’m not seeing the DestroyObject… Where would I put that?

It’d immediately redeem the individual item type when the player clicks the dialogue option to redeem that item type, much the same as the original situation was. :thinking: Just with a single catch-all “reward-redemption” script, rather than one per item type.

The destroying would still happen in the RedeemBountyItemType function, which calls DestroyItemsInInventory. I just posted only void main since that’s the only one that’d need to change. Although RedeemAllBountyItems would no longer be necessary, since it’s not being used anymore, so you could delete it entirely.

So tell me if this sounds like what I do:

Create 25 item scripts “bnty_(loc)_(shortname)”…

Conversations option 1. Kobold Ears

  • Appears When - “1st query script you made for me”
  • Action Taken - “bnty_(loc)_(shortname)”
    … Does the RedeemBounty get executed on the “(Owner)Very good then.” Actions Taken?

Partially, yes. The original conditional script wouldn’t be useful here anymore, because that one tried to look for the presence of any bounty item. If you want to maintain the old functionality entirely, and have the lines for redeeming the item types show up only if the PC or one of their associates is currently in possesssion of an item of that type, you will need a “Text Appears When…” script for each item type again.

To the latter - yes, exactly. :smiley: One script (per item type) to check whether the dialogue node to redeem the bounty item type should show up for the player at all. One script (per item type) to store the variables for that bounty item type on the player. One (catch-all) script to redeem the bounty item type, using the variables stored on the player.

Ok. I’m gonna pause this one :slight_smile:

I don’t want to do 50+ scripts (unless it becomes absolutely necessary). If it does, I’ll come back to this and remake and recompile this script.

I’ll let you know which way it goes.

Thanks so much for the work you’ve put in.

1 Like

Anytime. :slight_smile: Shout if anything else comes up.

1 Like

Just throwing my 2cp. There were a lot of comments in this thread, so Ive only read a few at the top and bottom. Hence I dont know if variables were discussed. I tend to use variables set on objects and creatures and a persistence token on the PC to handle all generic quest scripts. I have bounties in my PW too, here are my generic conversation scripts. Of course, you can just then adapt them for all other instances. I hadnt considered henchman checking yet, so I figure this as repayment for helping me avoid having to redo all my generic check scripts (though Im thinking I probably wont have henchmen):

On conversation conditional (makes the option to turn in appear if the character has the bounty item in their inventory. Here is where you would insert code related to checking henchmen too).

// generic HAS ITEM? conversation conditional
//set a string variable named REQUIRED on the owner of the conversation
//with the value of the tag of item required for the line to be visible in the dialogue
/* Script generated by
Lilac Soul’s NWN Script Generator, v. 2.3
For download info, please visit: */
int StartingConditional()
object oPC = GetPCSpeaker();
string sReqird = GetLocalString(OBJECT_SELF, “REQUIRED”);
if (GetItemPossessedBy(oPC, sReqird) == OBJECT_INVALID) return FALSE;
return TRUE;

Yeah, its lilac soul. I can do scripts by scratch, but its a timesaver. And here is the partner generic script:

// ta_bountynub
// conversation action script for counting up newbie bounties
//based on —>
// CheckFactionForItems include
// —from NW Lexicon, adapted
( Created By: Arlas Gilhith (
Created On: 29.07.2003 )
//adapted for Atlantis mod 2018
//this is used for the newbie bounty quests, such as goblin, kobold, orc ears and et cetera
script outline:
//the owner of the conversation will have variables set on them
//bountyitem (string) resref of bounty item
//bountyID (string) string ID of token variable (for persistance) ie goblinbnty, koboldbnty, orcbnty
//these will become int vars stored on the fate token
//Loops through their inventories
//GetFirstItemInInventory and GetNextItemInInventory
//destroys item, adds to the count, places int variable on player fate token
//if enough bounties are tallied on fate token, player can buy a bounty license
//and go after major bounty targets
//gives gold to PC if an int called bounty is set on NPC conv owner
void main()
object oPC = GetPCSpeaker();
object oItem;
int nBounty = GetLocalInt(OBJECT_SELF, “bounty”);
string sItem = GetLocalString(OBJECT_SELF, “bountyitem”);
string sBnty = GetLocalString(OBJECT_SELF, “bountyID”);
object oFate = GetObjectByTag(“ta_fatetoken”);
// check inventory for item
oItem = GetFirstItemInInventory(oPC);
while (GetIsObjectValid(oItem))
if (GetTag(oItem) == sItem)
GiveGoldToCreature(oPC, nBounty);
int nBnty = (GetLocalInt(oFate, sBnty) + 1);
SetLocalInt(oFate, sBnty, nBnty);
oItem = GetNextItemInInventory(oPC);

Right now, they are simple scripts that just check the PC alone, as I am focusing mainly on getting the base areas made with minor playtest functionality. Hope this helps?

EDIT: read more of the thread. Dunno if this helps much re: turn in of diff bounties. Where your script consolidates all turn-in, mine requires a diff NPC/line of conversation for each bounty.

Also, as my mod is still skeletal - I havent been able to test the functionality of the bounty system in regards to the player earning a licence to hunt bounties. Basically, the license will allow them to spawn monsters and NPCs like named fugitives and outlaws that normally one cant find.

@Dreadlord_Anwyn - Over the course of this thread, my script priorities had changed (based on DM/Admin and player input). Also, had I formatted per Forum Regs (VaulForReg w/Ch 3, para 3, sub para 3), you would see my initial “has” and “redeem” scripts in my initial post. @Tarot_Redhand fixed me on that one though :slight_smile:

  • Priority one was checking hench inventory. @TheBarbarian (with some pretty handy stuff by @pscythe) fixed that one fairly early on. The rest became cake

  • Priority two was script consolidation/minimization. We were working with 100+ generic bounty scripts.

  • Priority three was item selectability. This didn’t become a priority until late in the thread, and based on further player input it may an acceptable loss. If I could accomplish different NPC lines without each requiring a seperate “HasItem” script, I would totally do this. Heck, the conversations are setup like this right now anyway. I’m just tired of having to manage 2893 custom scripts, some of which I don’t even know the purpose of.

So, as you can see, the price of rice in the preponderance of Chinese provinces has… What does that have to do with NWN?