Aller au contenu

Photo

Help preventing a PC from taking an item from a container needed


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

#1
Tarot Redhand

Tarot Redhand
  • Members
  • 2 684 messages
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

#2
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
have you tryied setting the item cursed flag OnOpen of the chest?

#3
kalbaern

kalbaern
  • Members
  • 824 messages
Why not simply create the item in the chest only if they don't already have it?

#4
Shadooow

Shadooow
  • Members
  • 4 470 messages

kalbaern wrote...

Why not simply create the item in the chest only if they don't already have it?

exploitable

#5
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
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.

#6
kalbaern

kalbaern
  • Members
  • 824 messages

ShaDoOoW wrote...

kalbaern wrote...

Why not simply create the item in the chest only if they don't already have it?

exploitable


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
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
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
Tarot Redhand

Tarot Redhand
  • Members
  • 2 684 messages
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

Modifié par Tarot Redhand, 21 février 2011 - 10:28 .


#9
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
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);
      }
    }
  }

#10
Tarot Redhand

Tarot Redhand
  • Members
  • 2 684 messages
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


#11
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
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.

#12
Baaleos

Baaleos
  • Members
  • 1 330 messages
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
Shadooow

Shadooow
  • Members
  • 4 470 messages
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.

Modifié par ShaDoOoW, 22 février 2011 - 11:12 .


#14
SHOVA

SHOVA
  • Members
  • 522 messages
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.


#15
Tarot Redhand

Tarot Redhand
  • Members
  • 2 684 messages
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

#16
Baragg

Baragg
  • Members
  • 271 messages
And this item does not stack?

#17
Baragg

Baragg
  • Members
  • 271 messages
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]

#18
Baragg

Baragg
  • Members
  • 271 messages
#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);
}


}

Modifié par Baragg, 23 février 2011 - 01:21 .


#19
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
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
Baragg

Baragg
  • Members
  • 271 messages
Sorry bout the double posting.

#21
Tarot Redhand

Tarot Redhand
  • Members
  • 2 684 messages
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