Is there an easy way of preventing a PC from taking an item from a container if they already have an identical one in their inventory? Stopping them from picking one up off the floor is easy, but containers have me stumped. If not I'll just have to make it so they immediately drop the item, but that just seems a bit messy.
Thanks in advance.
TR
Help preventing a PC from taking an item from a container needed
Débuté par
Tarot Redhand
, févr. 21 2011 10:43
#1
Posté 21 février 2011 - 10:43
#2
Posté 21 février 2011 - 11:58
have you tryied setting the item cursed flag OnOpen of the chest?
#3
Posté 21 février 2011 - 05:15
Why not simply create the item in the chest only if they don't already have it?
#4
Posté 21 février 2011 - 07:15
exploitablekalbaern wrote...
Why not simply create the item in the chest only if they don't already have it?
#5
Posté 21 février 2011 - 07:49
I really need more information on what is tring to be done here.
Is this going to be for every item in the chest ?
Or just a single item that you can only have one of?
if it is the single item just take care of it through TBS the same way you are most likely taking care of it when picked up from the ground. Just put it back in the chest instead of dropping it. There is a GetModuleItemAcquiredFrom function in the module event after all.
Is this going to be for every item in the chest ?
Or just a single item that you can only have one of?
if it is the single item just take care of it through TBS the same way you are most likely taking care of it when picked up from the ground. Just put it back in the chest instead of dropping it. There is a GetModuleItemAcquiredFrom function in the module event after all.
#6
Posté 21 février 2011 - 08:27
ShaDoOoW wrote...
exploitablekalbaern wrote...
Why not simply create the item in the chest only if they don't already have it?
If it's a one time ever issue, you can make it non exploitable by storing a variable on an item in the PC's inventory that is undroppable. Then check the item for the variable before creating it. If it's a do once per reset thing, store it as a local variable on the PC.
#7
Posté 21 février 2011 - 08:34
exploitable because one player could open the chest and another player come by and take the item while the chest is still open. Assuming it is a multiplayer game.
#8
Posté 21 février 2011 - 10:27
Thanks for all the responses. As I've never actually written for multiplayer, I don't know if the feeble solution that I came up with is exploitable. After I wrote my request Ithought I better see if there was some work-around that I could come up with just in case there is no way of stopping a player from aquiring more than 1 of a particular item, So I thought what if instead of trying to stop them getting it, I immediately put it back? If nwn is fast enough it might give the illusion, if not the reality, of only being to take 1 item at any one time. So I put the following code in the X2_ITEM_EVENT_ACQUIRE part of my tag based script for it.
oPC = GetModuleItemAcquiredBy();
oItem = GetModuleItemAcquired();
if(oItem != OBJECT_INVALID)
{
if(GetNumItems(oPC, GetTag(oItem)) > 1)
{
oContainer = GetModuleItemAcquiredFrom();
if(oContainer != OBJECT_INVALID)
{
oNewMap = CreateItemOnObject("mapofrohan", oContainer);
DestroyObject(oItem);
}
}
}
And it does indeed give that illusion. So thanks for the input. One question, is this code exploitable?
TR
oPC = GetModuleItemAcquiredBy();
oItem = GetModuleItemAcquired();
if(oItem != OBJECT_INVALID)
{
if(GetNumItems(oPC, GetTag(oItem)) > 1)
{
oContainer = GetModuleItemAcquiredFrom();
if(oContainer != OBJECT_INVALID)
{
oNewMap = CreateItemOnObject("mapofrohan", oContainer);
DestroyObject(oItem);
}
}
}
And it does indeed give that illusion. So thanks for the input. One question, is this code exploitable?
TR
Modifié par Tarot Redhand, 21 février 2011 - 10:28 .
#9
Posté 22 février 2011 - 12:07
I dont see any exploit.
I do think I would do it more like this though.
object oPC = GetModuleItemAcquiredBy();
object oItem = GetModuleItemAcquired();
if(oItem != OBJECT_INVALID)
{
if(GetNumItems(oPC, GetTag(oItem)) > 1)
{
object oContainer = GetModuleItemAcquiredFrom();
if(GetHasInventory(oContainer))
{
CopyItem(oItem, oContainer,TRUE);
DestroyObject(oItem);
}
}
}
I do think I would do it more like this though.
object oPC = GetModuleItemAcquiredBy();
object oItem = GetModuleItemAcquired();
if(oItem != OBJECT_INVALID)
{
if(GetNumItems(oPC, GetTag(oItem)) > 1)
{
object oContainer = GetModuleItemAcquiredFrom();
if(GetHasInventory(oContainer))
{
CopyItem(oItem, oContainer,TRUE);
DestroyObject(oItem);
}
}
}
#10
Posté 22 février 2011 - 01:07
I did - if(oContainer != OBJECT_INVALID) - because the item can be aquired off the ground and GetModuleItemAcquiredFrom returns OBJECT_INVALID if the place the item is aquired from is not a container. Never occurred to me to use CopyItem - must make a note for future reference 'cos don't need the resref. Thanks for that one.
TR
TR
#11
Posté 22 février 2011 - 01:28
Yes, I am just not sure what happens when the event fires from the item being created into the inventory of the chest. At that point the event fires again, Does the function the return the item being aquired form the module a Valid object or OBJECT_INVALID ?? I just thought it safer to limit it a bit more without having to do the research.
Keep in mind that If they buy the item from a store they will lose the item and there gold.
Keep in mind that If they buy the item from a store they will lose the item and there gold.
#12
Posté 22 février 2011 - 10:49
GetLastDisturbed() returns the object that last disturbed OBJECT_SELF. GetInventoryDisturbType() returns one of the INVENTORY_DISTURB_TYPE_* constants to determine what occured. GetInventoryDisturbItem() returns the item that was either added or removed to the inventory of OBJECT_SELF.
Would these functions not be more useful?
Allows you to determine if your individual placeables inventory, had an item taken away, by whom, and then you can script specifically for whether or not the action should occur.
eg -
if item was not allowed to be taken by item taker, then give item back to chest.
#13
Posté 22 février 2011 - 11:11
Yes, OnDisturbed is probably the only way of doing something like this in multiplayer.
If thats SP however, it would be maybe better, if you would set the item in placeable's OnOpen to cursed so no "if take then destroy" workaround is needed at all
btw: LightFoot8 thanks for that undroppable(cursed) suggestion, I didn't know about this, it allowed me to remake my view only items, so I dont have to mess with my module events.
If thats SP however, it would be maybe better, if you would set the item in placeable's OnOpen to cursed so no "if take then destroy" workaround is needed at all
btw: LightFoot8 thanks for that undroppable(cursed) suggestion, I didn't know about this, it allowed me to remake my view only items, so I dont have to mess with my module events.
Modifié par ShaDoOoW, 22 février 2011 - 11:12 .
#14
Posté 22 février 2011 - 02:00
I think you going to need to do a few tweeks to get this to work.
First the mod on acquire Item script be the place to do what your looking for? If player has X in inventory, then another instance of X can not be picked up.
Second, create a Database value when the PC gets the item the first time, so
Third, have the container check for the database value to see if it will spawn the item.
As far as another player opening the chest, and another PC then gets the item, well the first part takes care of that.
good luck.
First the mod on acquire Item script be the place to do what your looking for? If player has X in inventory, then another instance of X can not be picked up.
Second, create a Database value when the PC gets the item the first time, so
Third, have the container check for the database value to see if it will spawn the item.
As far as another player opening the chest, and another PC then gets the item, well the first part takes care of that.
good luck.
#15
Posté 22 février 2011 - 11:42
Thanks guys. Having read what shova wrote I think I better clear one thing up. There can be many instances of this item in the game but no one player can own more than one copy of it. So if player a opens a chest and player a already has a copy of this item but player b who does not have a copy comes along and takes the item in the chest, it doesn't really matter.
TR
TR
#16
Posté 23 février 2011 - 01:08
And this item does not stack?
#17
Posté 23 février 2011 - 01:20
This should work for an item that does not stack:
[nwscript]
#include "nw_i0_plot"
const string ONE_ONLY_TAG = "";//put the tag of the one/per item here
const string DENY = "You may only possess one of that item.";
void main()
{
object oContainer = OBJECT_SELF;
object oPC = GetLastDisturbed();
int nType = GetInventoryDisturbType();
object oItem = GetInventoryDisturbItem();
string sTag = GetTag(oItem);
int nNum; string sRes;
if(sTag != ONE_ONLY_TAG)return;
if(nType != INVENTORY_DISTURB_TYPE_REMOVED)return;
nNum = GetNumItems(oPC, ONE_ONLY_TAG);
if(nNum > 1)
{
sRes = GetResRef(oItem);
CreateItemOnObject(sRes, oContainer);
DestroyObject(oItem, 0.1);
SendMessageToPC(oPC, DENY);
}
}[/nwscript]
[nwscript]
#include "nw_i0_plot"
const string ONE_ONLY_TAG = "";//put the tag of the one/per item here
const string DENY = "You may only possess one of that item.";
void main()
{
object oContainer = OBJECT_SELF;
object oPC = GetLastDisturbed();
int nType = GetInventoryDisturbType();
object oItem = GetInventoryDisturbItem();
string sTag = GetTag(oItem);
int nNum; string sRes;
if(sTag != ONE_ONLY_TAG)return;
if(nType != INVENTORY_DISTURB_TYPE_REMOVED)return;
nNum = GetNumItems(oPC, ONE_ONLY_TAG);
if(nNum > 1)
{
sRes = GetResRef(oItem);
CreateItemOnObject(sRes, oContainer);
DestroyObject(oItem, 0.1);
SendMessageToPC(oPC, DENY);
}
}[/nwscript]
#18
Posté 23 février 2011 - 01:21
#include "nw_i0_plot"
const string ONE_ONLY_TAG = "";//put the tag of the one/per item here
const string DENY = "You may only possess one of that item.";
void main()
{
object oContainer = OBJECT_SELF;
object oPC = GetLastDisturbed();
int nType = GetInventoryDisturbType();
object oItem = GetInventoryDisturbItem();
string sTag = GetTag(oItem);
int nNum; string sRes;
if(sTag != ONE_ONLY_TAG)return;
if(nType != INVENTORY_DISTURB_TYPE_REMOVED)return;
nNum = GetNumItems(oPC, ONE_ONLY_TAG);
if(nNum > 1)
{
sRes = GetResRef(oItem);
CreateItemOnObject(sRes, oContainer);
DestroyObject(oItem, 0.1);
SendMessageToPC(oPC, DENY);
}
}
const string ONE_ONLY_TAG = "";//put the tag of the one/per item here
const string DENY = "You may only possess one of that item.";
void main()
{
object oContainer = OBJECT_SELF;
object oPC = GetLastDisturbed();
int nType = GetInventoryDisturbType();
object oItem = GetInventoryDisturbItem();
string sTag = GetTag(oItem);
int nNum; string sRes;
if(sTag != ONE_ONLY_TAG)return;
if(nType != INVENTORY_DISTURB_TYPE_REMOVED)return;
nNum = GetNumItems(oPC, ONE_ONLY_TAG);
if(nNum > 1)
{
sRes = GetResRef(oItem);
CreateItemOnObject(sRes, oContainer);
DestroyObject(oItem, 0.1);
SendMessageToPC(oPC, DENY);
}
}
Modifié par Baragg, 23 février 2011 - 01:21 .
#19
Posté 23 février 2011 - 04:25
Please Note that He wants the PC to only have one item of this kind. The above solution is perfect for use on just a chest. However since most of the code posted are just script fragments, I am pretty sure he is also adding code for picking the item up from the ground. Hence the need to use TBS.
#20
Posté 24 février 2011 - 04:47
Sorry bout the double posting.
#21
Posté 26 février 2011 - 11:21
Thank you to everyone for thier help. If anyone is interested to see what I was working on, I have now uploaded the project to the vault and the link is in my sig under Micro Maps.
TR
TR





Retour en haut







