How do you make a PC drop a random item on death?
Drop random item from inventory
Débuté par
mwplayer
, juin 24 2011 02:05
#1
Posté 24 juin 2011 - 02:05
#2
Posté 24 juin 2011 - 03:40
Unless there's a NWNX function for it, the only way is to copy the object to the players location, or near their location, then delete the object from the PCs inventory after. That simulates dropping it, without the need for the PC to be able to run an Action.
#3
Posté 24 juin 2011 - 03:45
Yeah that's what I was planning to do. GetLocalLocation and copy the item there while deleting the item. But I don't know what do with GetNextItemObject while randomizing which item to drop.
Modifié par mwplayer, 24 juin 2011 - 03:46 .
#4
Posté 24 juin 2011 - 06:24
It's a matter of deciding if you want to drop an item based on certain criteria, or a completely random item, I suppose.
To get a fully random item you have to loop through all the inventory items to get a count, then pick a random number based on that count, then go through the inventory again in order to get the item.
If you have it based on certain criteria, you would instead loop through only the once, comparing the item to your stored one to see if it's a better fit. Neither is overly complicated to write, only a dozen lines or so, but you would need to know which method you preferred first.
I'll write up some example scripts in the morning if nobody else has, the random one would be pretty similar to the treasure generation ones that were posted last week-end.
To get a fully random item you have to loop through all the inventory items to get a count, then pick a random number based on that count, then go through the inventory again in order to get the item.
If you have it based on certain criteria, you would instead loop through only the once, comparing the item to your stored one to see if it's a better fit. Neither is overly complicated to write, only a dozen lines or so, but you would need to know which method you preferred first.
I'll write up some example scripts in the morning if nobody else has, the random one would be pretty similar to the treasure generation ones that were posted last week-end.
#5
Posté 24 juin 2011 - 04:13
Here's a modified version of the loot generation script I'd posted in the other thread, set up to be usable with the vanilla NWN scripts, as an example. This is set to run in the OnPlayerDeath event.
#include "x0_i0_position""
void main()
{
object oPC = GetLastPlayerDied();
int nCount;
object oItem;
if (!nCount)
{
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) )
{
nCount ++;
oItem = GetNextItemInInventory (oPC);
}
}
int nItem = Random (nCount) + 1;
int nContinue = TRUE;
int nCounter = 1;
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) && nContinue)
{
if (nCounter == nItem)
{
CopyObject (oItem, GetRandomLocation (GetArea(oPC), oPC, 1.0) );
DestroyObject (oItem, 0.1);
nContinue = FALSE;
}
nCounter ++;
oItem = GetNextItemInInventory (oPC);
}
}
I have it set to drop in a random nearby (1.0 m) location so the item doesn't end up under the PCs body.
The drawback to a truly random method, is that it doesn't care if the item is plot, the size of it, or what not. I've seen a few servers that go with dropping what the PC has in their hands at that moment on death, which while annoying at least is consistent in what the players can expect to have drop.
#include "x0_i0_position""
void main()
{
object oPC = GetLastPlayerDied();
int nCount;
object oItem;
if (!nCount)
{
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) )
{
nCount ++;
oItem = GetNextItemInInventory (oPC);
}
}
int nItem = Random (nCount) + 1;
int nContinue = TRUE;
int nCounter = 1;
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) && nContinue)
{
if (nCounter == nItem)
{
CopyObject (oItem, GetRandomLocation (GetArea(oPC), oPC, 1.0) );
DestroyObject (oItem, 0.1);
nContinue = FALSE;
}
nCounter ++;
oItem = GetNextItemInInventory (oPC);
}
}
I have it set to drop in a random nearby (1.0 m) location so the item doesn't end up under the PCs body.
The drawback to a truly random method, is that it doesn't care if the item is plot, the size of it, or what not. I've seen a few servers that go with dropping what the PC has in their hands at that moment on death, which while annoying at least is consistent in what the players can expect to have drop.
#6
Posté 24 juin 2011 - 10:09
Well I don't want the item to drop if GetItemCursedFlag/GetPlotFlag is TRUE.
This is how your modified script looks. There's probably a much better way to do it cuz I'm not a great scripter, lol.
#include "x0_i0_position"
void main()
{
object oPC = GetLastPlayerDied();
int nCount;
object oItem;
if (!nCount)
{
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem))
{
nCount ++;
oItem = GetNextItemInInventory (oPC);
}
}
int nItem = Random (nCount) + 1;
int nContinue = TRUE;
int nCounter = 1;
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) && nContinue)
{
if (GetItemCursedFlag(oItem) == TRUE)
{
oItem = GetNextItemInInventory(oPC);
}
else if (GetPlotFlag(oItem) == TRUE)
{
oItem = GetNextItemInInventory(oPC);
}
else if (nCounter == nItem)
{
{
CopyObject (oItem, GetRandomLocation (GetArea(oPC), oPC, 2.0));
DestroyObject (oItem, 0.1);
nContinue = FALSE;
}
nCounter ++;
oItem = GetNextItemInInventory (oPC);
}
}
}
This is how your modified script looks. There's probably a much better way to do it cuz I'm not a great scripter, lol.
#include "x0_i0_position"
void main()
{
object oPC = GetLastPlayerDied();
int nCount;
object oItem;
if (!nCount)
{
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem))
{
nCount ++;
oItem = GetNextItemInInventory (oPC);
}
}
int nItem = Random (nCount) + 1;
int nContinue = TRUE;
int nCounter = 1;
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) && nContinue)
{
if (GetItemCursedFlag(oItem) == TRUE)
{
oItem = GetNextItemInInventory(oPC);
}
else if (GetPlotFlag(oItem) == TRUE)
{
oItem = GetNextItemInInventory(oPC);
}
else if (nCounter == nItem)
{
{
CopyObject (oItem, GetRandomLocation (GetArea(oPC), oPC, 2.0));
DestroyObject (oItem, 0.1);
nContinue = FALSE;
}
nCounter ++;
oItem = GetNextItemInInventory (oPC);
}
}
}
Modifié par mwplayer, 24 juin 2011 - 10:18 .
#7
Posté 25 juin 2011 - 12:38
What you would have to do, is incriment nRandom instead of getting the next item. That way, it selects the next item in the inventory instead. That would also require the initial counting loop only counts non-plot/non cursed items as well.
#8
Posté 25 juin 2011 - 10:15
I don't see the integer nRandom in the script anywhere...
Sorry, am I missing something?
Sorry, am I missing something?
#9
Posté 25 juin 2011 - 11:03
That was my mistake, I should have said "nItem" instead of "nRandom". I didn't double check what int I'd used for storing the random number under.
Modified, the script would look something like this:
#include "x0_i0_position""
void main()
{
object oPC = GetLastPlayerDied();
int nCount;
object oItem;
if (!nCount)
{
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) )
{
if (!GetPlotFlag (oItem) && !GetItemCursedFlag (oItem))
{
nCount ++;
}
oItem = GetNextItemInInventory (oPC);
}
}
int nItem = Random (nCount) + 1;
int nContinue = TRUE;
int nCounter = 1;
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) && nContinue)
{
if (GetPlotFlag (oItem) || GetItemCursedFlag (oItem))
{
nItem ++;
}
else if (nCounter == nItem)
{
CopyObject (oItem, GetRandomLocation (GetArea(oPC), oPC, 1.0) );
DestroyObject (oItem, 0.1);
nContinue = FALSE;
}
nCounter ++;
oItem = GetNextItemInInventory (oPC);
}
}
That should ignore all plot and cursed items in the count, as well as "skipping" them when it goes to drop the item, by incrimenting the item to drop by one.
Modified, the script would look something like this:
#include "x0_i0_position""
void main()
{
object oPC = GetLastPlayerDied();
int nCount;
object oItem;
if (!nCount)
{
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) )
{
if (!GetPlotFlag (oItem) && !GetItemCursedFlag (oItem))
{
nCount ++;
}
oItem = GetNextItemInInventory (oPC);
}
}
int nItem = Random (nCount) + 1;
int nContinue = TRUE;
int nCounter = 1;
oItem = GetFirstItemInInventory (oPC);
while (GetIsObjectValid (oItem) && nContinue)
{
if (GetPlotFlag (oItem) || GetItemCursedFlag (oItem))
{
nItem ++;
}
else if (nCounter == nItem)
{
CopyObject (oItem, GetRandomLocation (GetArea(oPC), oPC, 1.0) );
DestroyObject (oItem, 0.1);
nContinue = FALSE;
}
nCounter ++;
oItem = GetNextItemInInventory (oPC);
}
}
That should ignore all plot and cursed items in the count, as well as "skipping" them when it goes to drop the item, by incrimenting the item to drop by one.





Retour en haut






