@pscythe I can see the value of not checking creatures needlessly, especially on a busier server. I’ll amend what @TheBarbarian gave me in the interest of having it prepared for the next guy that takes over, in hopes that Amon re-grows. Thank you.
what exactly you want to achieve?
you can increase max stack in baseitems.2da if you think 99 is too little
there is a method how to spawn stack of more than 99 while still having 99 as max but it is quite complicated so first tell me what you want to do exactly with that
I am sure you already know this…
In both functions where you got nHasBountyItem = TRUE
inside a loop, it can be rewritten to return TRUE
to break out off the loop early instead of just looping on needlessly when you already have the result.
If DestroyItemsInInventory() does what it looks like it does, which is “destroy all items with a particular tag and award gold and return the number of items it found”, then you’d want to put the condition check script into the “Text Appears When…” tab of the dialogue node, and the bounty redemption into the “Actions Taken” one. The Actions Taken script would stand on it’s own, and look something like this:
#include "pcinclude"
// 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)
{
int nBounty = DestroyItemsInInventory(oHasItem, sTag, 9999);
GiveGoldToCreature(oGetsReward, nGoldReward * nBounty);
GiveXPToCreature(oGetsReward, nXPReward * nBounty);
}
// Redeems bounty items. Lists tags and XP/Gold rewards of redeemable
// bounty items; add new bounty items here.
void RedeemAllBountyItems(object oHasItem, object oGetsReward);
void RedeemAllBountyItems(object oHasItem, object oGetsReward)
{
RedeemBountyItemType("KoboldEar", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("OrcEar", 75, 75, oHasItem, oGetsReward);
}
void main()
{
object oPC = GetPCSpeaker();
// Redeem bounty items on the PC speaker.
RedeemAllBountyItems(oPC, oPC);
// Start looking through the faction members.
object oTarget = GetFirstFactionMember(oPC);
// 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.
RedeemAllBountyItems(oTarget, oPC);
}
// Check the next faction member.
oTarget = GetNextFactionMember(oPC);
}
}
But you could probably leave the conditional script out entirely, and let the “[Redeem bounty items]” option be always available, just using this one script under Actions Taken. Trying to redeem bounty items without being in possession of any should just not do anything whatsoever (0*50), assuming there are no problems with the DestroyItemsInInventory function. It’d skip the effort of cycling through the faction members and the items in the associate inventories.
I think so, but I get all my testing done in singleplayer mode for lack of easily-accessible guinea pigs, so don’t take my word for it. :x Either one of the GetAssociateType and the GetIsPC checks should exclude other PCs, though, skipping over faction members who have the henchman associate type or are PCs themselves.
Without NWNX, for sure. I don’t know what can be done with NWNX, unfortunately. I’ve seen someone say they saw edits I’d normally expect to be 2da-dependent on a PW without having had to download anything once, but I can’t judge whether they were right, or how it was done if they were. Normally, yes - if a file is edited, the edited file needs to be distributed to the players somehow if it’s supposed to have an effect for them.
@pscythe
Assume that I just sat down and started tinkering one day, and have no idea what I’m doing. Pointing stuff like this out is always worthwhile and welcome.
you should try PRC Lite then ;), though you should know what is normally not possible before you try it because everything in it uses vanilla GUI so it looks like its from Bioware
anyway changing stacksize doesn’t require to distribute that change to players - all you need is to put it into override folder on server (if module is not using any haks with this 2da in them) or put it into top-hak.
@Shadooow
Does this go for all 2da-based changes on PWs? What about models, scripts, textures? Can stuff just be plonked into the override folder on the server?
Offtopic-reduction!
i tried to once but i got tangled up in the installation and then i gave up and felt bad about being *too stupid to install something* x_x and then i felt bad about giving up because *that's not how to get things done at all* but then i got distracted by other things and ever since then i just kind of avoid the whole nwnx sector like it's on fire and emanating an uncomfortable heat it is a source of ongoing regret for me if you teach me how to use this stuff i will in turn teach others x_x
Backtracking to check - it was Roaringthing who asked about making alterations to classes.2da, to make rangers unable to cast spells, but without mandating a hak. That help request might still be open.
no not all, something requires players to have same 2da or at least same value in 2da and something doesn’t
I have this info in my head but I am not exactly keen on writing some exhaustive list for various reasons… sorry.
Just try to change it in override, if it won’t work for players then they need that 2da too.
@TheBarbarian @Sknymick I’m still building/writing, so not tested anything extensively, however when I tried the 2da changes to Classes and Spells etc I did have to have the 2da on my client to get them to work (I think ;p) - I’m building on Windows and play on OS X, so have two separately folders, which functions like another player basically.
I’ve kept my world vanilla, with no hak paks, so would be a real shame to make anyone have to download / install something to try / play - I suppose that is the benefit of NWNX. For example Arelith server is basically a different game with all the class and feat changes etc and there is no extra content required, so I can only assume this is all NWNX based.
@Shadooow - increasing stack size - would like to have larger arrow stack sizes and “Gem” stack sizes to reduce used inventory space.
- If I change my moduel with PRC Lite (without NWNX) is the client required to install it to play? To simply use some functionality?
- I’ll ask the rest of my questions on my other post. I don’t want to cross into this one too much (and you’re very helpful/prolific on the board)
@pscythe - I did not, in fact, already know. I can decode a script as I’m reading it, just as a novice reader can understand most of The Wheel of Time. But I am no Robert Jordan.
@TheBarbarian - Even more thanks to you. I had consolidated all my Action Taken turn in scripts and had more than 300 lines of code… This will reduce that by half. I’ll consolidate my list into the code and paste it in a new reply.
@Roaringthing - You sir are more ambitious than I. I harvested an old favorite PW off the Vault, and we’re just trying to keep it modern/interesting. Ours was built by Craig Sutter (DM Ren) in the Vanilla NWN of 2001/2002. So some of the script is klunky. It was built to run on 2 crappy old Linux laptops with RAM in the 250-500 mb range. So mine is not doing a lot of the things it could (or as Shadooow helped me fix in another thread, things it SHOULD), but it’s amazing for what it was.
@TheBarbarian - Below is a consolidated script fromwhat you gave me today with my list of ResRefs:
// 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)
{
int nBounty = DestroyItemsInInventory(oHasItem, sTag, 9999);
GiveGoldToCreature(oGetsReward, nGoldReward * nBounty);
GiveXPToCreature(oGetsReward, nXPReward * nBounty);
}
// Redeems bounty items. Lists tags and XP/Gold rewards of redeemable
// bounty items; add new bounty items here.
void RedeemAllBountyItems(object oHasItem, object oGetsReward);
void RedeemAllBountyItems(object oHasItem, object oGetsReward)
{
RedeemBountyItemType("ArustethHead", 75, 75, oHasItem, oGetsReward);
RedeemBountyItemType("BeholderEyeStalk", 75, 75, oHasItem, oGetsReward);
RedeemBountyItemType("BisonMeat", 40, 40, oHasItem, oGetsReward);
RedeemBountyItemType("BisonSkin", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("BisonTongue", 60, 60, oHasItem, oGetsReward);
RedeemBountyItemType("BoarSkin", 25, 25, oHasItem, oGetsReward);
RedeemBountyItemType("1Shortbow", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("CarasinHobgoblinEar", 75, 75, oHasItem, oGetsReward);
RedeemBountyItemType("1Crossbow", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("tr_forrestboarskin", 25, 25, oHasItem, oGetsReward);
RedeemBountyItemType("FireGiantHead", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("FriaknarOrcEar", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("FrostGiantHead", 150, 150, oHasItem, oGetsReward);
RedeemBountyItemType("GatorSkin", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("GlacierBearSkin", 250, 250, oHasItem, oGetsReward);
RedeemBountyItemType("GlacierBearSkin2", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("GoblinEar", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("HrendyrHide", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("KoboldEar", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("Sharpzombiebone", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("SpiderHeart", 60, 60, oHasItem, oGetsReward);
RedeemBountyItemType("SpineGiantHand", 200, 200, oHasItem, oGetsReward);
RedeemBountyItemType("ViperSkin", 150, 150, oHasItem, oGetsReward);
RedeemBountyItemType("Toweraxe", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("WildlingScalp", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("WorgsTail", 50, 50, oHasItem, oGetsReward);
}
void main()
{
object oPC = GetPCSpeaker();
// Redeem bounty items on the PC speaker.
RedeemAllBountyItems(oPC, oPC);
// Start looking through the faction members.
object oTarget = GetFirstFactionMember(oPC);
// 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.
RedeemAllBountyItems(oTarget, oPC);
}
// Check the next faction member.
oTarget = GetNextFactionMember(oPC);
}
}
VERY much obliged to you for your assistance here.
De nada. Test it, though! I write crap sometimes.
Sidenote: ResRefs and tags are different things; see under the “General” tab when you open the item properties panel for the blueprint. Either can be used to identify something, but the ResRef is unique to the blueprint, while many different items can have the same tag.
Lined up the spaces.
// Redeems bounty items. Lists tags and XP/Gold rewards of redeemable
// bounty items; add new bounty items here.
void RedeemAllBountyItems(object oHasItem, object oGetsReward);
void RedeemAllBountyItems(object oHasItem, object oGetsReward)
{
RedeemBountyItemType("ArustethHead", 75, 75, oHasItem, oGetsReward);
RedeemBountyItemType("BeholderEyeStalk", 75, 75, oHasItem, oGetsReward);
RedeemBountyItemType("BisonMeat", 40, 40, oHasItem, oGetsReward);
RedeemBountyItemType("BisonSkin", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("BisonTongue", 60, 60, oHasItem, oGetsReward);
RedeemBountyItemType("BoarSkin", 25, 25, oHasItem, oGetsReward);
RedeemBountyItemType("1Shortbow", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("CarasinHobgoblinEar", 75, 75, oHasItem, oGetsReward);
RedeemBountyItemType("1Crossbow", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("tr_forrestboarskin", 25, 25, oHasItem, oGetsReward);
RedeemBountyItemType("FireGiantHead", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("FriaknarOrcEar", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("FrostGiantHead", 150, 150, oHasItem, oGetsReward);
RedeemBountyItemType("GatorSkin", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("GlacierBearSkin", 250, 250, oHasItem, oGetsReward);
RedeemBountyItemType("GlacierBearSkin2", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("GoblinEar", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("HrendyrHide", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("KoboldEar", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("Sharpzombiebone", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("SpiderHeart", 60, 60, oHasItem, oGetsReward);
RedeemBountyItemType("SpineGiantHand", 200, 200, oHasItem, oGetsReward);
RedeemBountyItemType("ViperSkin", 150, 150, oHasItem, oGetsReward);
RedeemBountyItemType("Toweraxe", 100, 100, oHasItem, oGetsReward);
RedeemBountyItemType("WildlingScalp", 50, 50, oHasItem, oGetsReward);
RedeemBountyItemType("WorgsTail", 50, 50, oHasItem, oGetsReward);
}
Ok,
I fired it up single player, Debug, and hired me a Henchman. Gave myself some items and went to the fella with the script.
He took all the PCs items perfectly. Left the Hench’s where they were. Am I missing a #include “x0_i0_henchman”? Do I need to establish a master for it to recognize that he’s a henchman? I have no idea…
Ok then you should modify baseitems.2da and put that modified file into your top hak on server.
Include files exist to make functions available to use in other scripts. For instance, if you put the functions RedeemBountyItemType() and RedeemAllBountyItems() into a separate script file, without a void main in it, and saved it, you could then #include that script at the top of another, and call the functions from there.
Hold up, I’mma set up a test scenario and come debug.
Also, tip: To find out where something’s going wrong, place debug messages. For instance, you can put a SendMessageToPC(oPC, “Checking “+GetName(oTarget)+”.”); into the faction member cycling:
// As long as a valid faction member continues to be found...
while (oTarget != OBJECT_INVALID)
{
SendMessageToPC(oPC, "Checking "+GetName(oTarget)+".");
// Only target faction members who are henchmen whose master is the PC speaker.
if (GetAssociateType(oTarget) == ASSOCIATE_TYPE_HENCHMAN && GetMaster(oTarget) == oPC)
{
SendMessageToPC(oPC, "This object is a qualifying henchman.");
// Redeem bounty items on the henchman.
RedeemAllBountyItems(oTarget, oPC);
}
// Check the next faction member.
oTarget = GetNextFactionMember(oPC);
}
Once you run that, you know whether it’s failing to find the henchman as a faction member, or whether it’s the GetAssociateType/GetMaster check that’s the problem.
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);
@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!
SUCCESS!!
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?
Yay!!
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.
It throws an error.
bounty_exch.nss(11): ERROR: VARIABLE DEFINED WITHOUT TYPE
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?