Aller au contenu

Photo

Any scripting method for transferring all inventory items to a remote container?


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

#1
Furnaceden

Furnaceden
  • Members
  • 3 messages
Hello,

I am new to this forum and I apologize if this topic has been addressed already, but I performed a reasonably diligent search and could not find anything.

Is there a way to transfer all of the player-character's inventory to a container in another area? For example, if I wanted to create a module with a segment where the player is taken prisoner and all belongings confiscated, and the character has to escape and make it back to a point without the aid of those belongings. Of course, the prisoner's confiscated stuff would be safely and "conveniently" locked away in a container by the guards (nobody wants to lose all their precious enchanted stuff for good, after all).

Is there a script or method to accomplish this? Even, say, a way of turning the current character-state into a "corpse-container" elsewhere -- form of an armoire, maybe -- and regenerating a duplicate with all personal stats but without items? That would be a horribly convoluted method but I'm just spit-balling here.

#2
henesua

henesua
  • Members
  • 3 867 messages
 I have a function for doing that which I call MoveInventory.

I beleive others have pointed out problems with how I implemented this, but I haven't encountered anything. I hope some of those that know what they are doing chime in and explain how to improve my function.

While it owuld be best to go to pastebin to see my function (see link above), I am also posting it here:

int MoveInventory(object oSource, object oTarget)
{
object oItem, oCopy; int nCount;

// move gold
if(GetObjectType(oSource)==OBJECT_TYPE_CREATURE)
{
int nGold = GetGold(oSource);
if(nGold)
{
AssignCommand(oTarget, TakeGoldFromCreature(nGold, oSource));
++nCount;
}
}

// copy containers
oItem = GetFirstItemInInventory(oSource);
while(GetIsObjectValid(oItem))
{
if(GetHasInventory(oItem)&&!GetLocalInt(oItem,"COPIED"))
{
nCount++;
// create a copy of the container
oCopy = CreateItemOnObject(GetResRef(oItem), oTarget, 1, GetTag(oItem));
SetLocalInt(oItem, "COPIED", TRUE); // mark the original as copied
SetName(oCopy, GetName(oItem));
SetDescription(oCopy, GetDescription(oItem));
SetIdentified(oCopy, GetIdentified(oItem));
// copy contents of container
nCount += MoveInventory(oItem, oCopy);
DestroyObject(oItem, 0.1);
}

oItem = GetNextItemInInventory(oSource);
}
// copy items
oItem = GetFirstItemInInventory(oSource);
while(GetIsObjectValid(oItem))
{
if(!GetHasInventory(oItem)&&!GetLocalInt(oItem,"COPIED"))
{
nCount++;
CopyItem(oItem, oTarget, TRUE);
SetLocalInt(oItem, "COPIED", TRUE);
DestroyObject(oItem, 0.1);
}

oItem = GetNextItemInInventory(oSource);
}

return nCount;
}

Modifié par henesua, 21 février 2014 - 01:04 .


#3
WhiZard

WhiZard
  • Members
  • 1 204 messages
Here's how your script works:
Inventory items are arranged in order from last disturbed to first disturbed with the contents of containers immediately following the container item.

So you would first transfer all gold,
Then you would copy container 1.
Then you would check container 1 for gold.
Then you would check container 1 for containers.
Then you would copy the inventory of container 1 to its new container.
You would then be at the end of the inventory of container 1 so the next object for examining containers is just after container 1 and its contents, so you would then proceed to container 2.
Repeat container 1 loop for the remaining containers.
Next you copy all items not in a container.

Inefficient but it works. One thing that would save a lot of script time is not to check containers for containers.

#4
Proleric

Proleric
  • Members
  • 2 354 messages
A few issues:

  • Removing equipped items (if we're in jail, having a sword might be frowned on).

  • Removing the creature skin will break the 1.69 horse system

  • Containers have a stack limit of 50,000 gold

Here's my script. There's an option to remove the clothing/armour, too, in case you want to equip a prison uniform or whatever.

I've never bothered much with containers, so I'm not sure whether special processing is required for them. EDIT : It is - see next post for fix.

Modifié par Proleric1, 21 février 2014 - 03:11 .


#5
Proleric

Proleric
  • Members
  • 2 354 messages
I've added a line to my script which handles container items with contents.

I find that container items cannot contain gold or nested containers, so the result is simple, but comprehensive, I think.

Modifié par Proleric1, 21 février 2014 - 03:08 .


#6
WhiZard

WhiZard
  • Members
  • 1 204 messages
Proleric1, your script doesn't accomplish one thing that henesua's script accomplishes, that is keeping the inventory contents in the same container. I am not sure why you are bringing up point 2 (removal of creature skin) as henesua doesn't do an inventory removal in his function. Due to the fact that the function calls itself, I think henesua would do an inventory strip outside this function if it were called for.

#7
meaglyn

meaglyn
  • Members
  • 809 messages

WhiZard wrote...

Inefficient but it works. One thing that would save a lot of script time is not to check containers for containers.


Its not that inefficient in the grand scheme of things. Containers don't have containers so that always fails,and the recursion stops. A few extra instructions maybe, but a bit of elegance. Assuming the variables used in the iterators are on the object being iterated you could remove the recursion and add another loop there to copy over all the items in each container inline. You still need to mark them.

(Edit again: Nevermind - I didn't notice the two loops. That could be made into one without much trouble I think...)

Plus, I expect stripping all the PC gear is not that common.

One thing that Hen's does is keep the contents of PC containers in the container. This seems like a nice feature.

(Edit : What Whizard said..)

@Proleric: Agree with most of what yours does, stripping equipped things etc. But your fixed version empties all the containers that get moved. Also you could just stop the inventory loop before the carmor slot. Then you don't need to hardcode the resref of the skin, which is configurable (at least in Krit's updated skin code).

One issue with the containers part of Henesua's is variables on the container. I have a bunch of auto sorting containers PCs can use which have settings on them. Need code in there to copy that state over to the newly created container.

Good discussion - made me see a few issues with what I have currently, which I'm off to fix...

Modifié par meaglyn, 21 février 2014 - 04:52 .


#8
WhiZard

WhiZard
  • Members
  • 1 204 messages
I have cleaned up Henesua's script to work more efficiently (although it no longer factors in gold).  Gold and equipped item sweeps can be done on the side.

int MoveInventory(object oSource, object oTarget)
{
// This function can cause problems if misused
if(oTarget == oSource)  return -1;
int nCount, nCount2; object oCopy, oBlank;
object oItem = GetFirstItemInInventory(oSource);
while(GetIsObjectValid(oItem))
   {
   nCount++;
   oCopy = CreateItemOnObject(GetResRef(oItem), oTarget, 1, GetTag(oItem));
  SetName(oCopy, GetName(oItem));
  SetDescription(oCopy, GetDescription(oItem));
  SetIdentified(oCopy, GetIdentified(oItem));
  if(GetHasInventory(oItem))
    {
    nCount2 = MoveInventory(oItem, oCopy);
    nCount += nCount2;
    while(nCount2--) oBlank = GetNextItemInInventory(oSource);
    }
  DestroyObject(oItem);
  oItem = GetNextItemInInventory(oSource);
  }
return nCount;
}

Modifié par WhiZard, 21 février 2014 - 05:05 .


#9
meaglyn

meaglyn
  • Members
  • 809 messages
Hhm, you're doing it all with CreateItemOnObject. That means no variables... I think you may have gone one step too far in the name of efficiency :)

I like the oBlank usage instead of marking the items, although it does rely on implementation details of the lower levels. I may borrow that ...

#10
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages

meaglyn wrote...

Hhm, you're doing it all with CreateItemOnObject. That means no variables... I think you may have gone one step too far in the name of efficiency :)


Ironically, CopyItem (with or without variables) would also be far more efficient than Create. :P

Funky

#11
Proleric

Proleric
  • Members
  • 2 354 messages

WhiZard wrote...

Proleric1, your script doesn't accomplish one thing that henesua's script accomplishes, that is keeping the inventory contents in the same container.

Interesting. Have you tested this? My finding is that containers can't be nested, nor can they contain gold, but perhaps I've missed something.

WhiZard wrote...
I am not sure why you are bringing up point 2 (removal of creature skin) as henesua doesn't do an inventory removal in his function. ...

The most important difference between Henesua's script and mine is that I remove equipped items, which is normally a requirement for jail scenarios etc. That implies the additional requirement to retain the horse skin.

Incidentally, I'm using CopyItem, which is faster and preserves variables, as FunkySwerve says.

meaglyn wrote...

@Proleric: ...you could just stop the inventory loop before the carmor slot. Then you don't need to hardcode the resref of the skin, which is configurable (at least in Krit's updated skin code).

True, the literal is just sloppy. Since the engine isn't going to change now, I guess we could use the "inside information" that the creature slot has a higher number than the others, though purists might argue with that, too.

meaglyn wrote...
One issue with the containers part of Henesua's is variables on the container.

Yes, I wondered if anyone ever did that.

Good discussion.

Modifié par Proleric1, 21 février 2014 - 06:24 .


#12
meaglyn

meaglyn
  • Members
  • 809 messages

Proleric1 wrote...

True, the literal is just sloppy. Since the engine isn't going to change now, I guess we could use the "inside information" that the creature slot has a higher number than the others, though purists might argue with that, too.


I put this just inside my for loop:

if (i == INVENTORY_SLOT_CARMOUR)
                        continue;

Then I'm not relying on the relative numerical values at all.

#13
henesua

henesua
  • Members
  • 3 867 messages
I forget why i did not copy objects with inventory. That said I appreciate all the comments, folks. When I have time I'll take a look at this function again.

I hope the OP is getting what they need. If not, speak up.

#14
meaglyn

meaglyn
  • Members
  • 809 messages

henesua wrote...
I forget why i did not copy objects with inventory.


I think it just doesn't work, at least if there is anything in it.

#15
WhiZard

WhiZard
  • Members
  • 1 204 messages

FunkySwerve wrote...

meaglyn wrote...

Hhm, you're doing it all with CreateItemOnObject. That means no variables... I think you may have gone one step too far in the name of efficiency :)


Ironically, CopyItem (with or without variables) would also be far more efficient than Create. :P

Funky


Easy enough to adjust for...


int MoveInventory(object oSource, object oTarget)
{
// This function can cause problems if misused
if(oTarget == oSource)  return -1;
int nCount, nCount2; object oCopy, oBlank;
object oItem = GetFirstItemInInventory(oSource);
while(GetIsObjectValid(oItem))
   {
   nCount++;
   if(GetHasInventory(oItem))
     {
     oCopy = CreateItemOnObject(GetResRef(oItem), oTarget, 1, GetTag(oItem));
     SetName(oCopy, GetName(oItem));
     SetDescription(oCopy, GetDescription(oItem));
     SetIdentified(oCopy, GetIdentified(oItem));
     nCount2 = MoveInventory(oItem, oCopy);
     nCount += nCount2;
     while(nCount2--) oBlank = GetNextItemInInventory(oSource);
     }
  else CopyItem(oItem, oTarget, TRUE);
  DestroyObject(oItem);
  oItem = GetNextItemInInventory(oSource);
  }
return nCount;
}

#16
Furnaceden

Furnaceden
  • Members
  • 3 messages
Hello all,

Thanks for the very useful (and timely) posts. I am studying all this with great interest. Will be testing some of this out shortly.

For a prison situation, issues of losing some gold due to container limitations, would be less important than the necessity of removing equipped items. The loss of gold could be explained in the realm of logic, whereas a prisoner being jailed with a "Halberd of Acidic Destruction +4" or a "Wizard's Staff of Fireballs" -- not so much.

I assume Bags of Holding pose no special problems for this. They (and their contents) move in and out of containers easily enough.

Modifié par Furnaceden, 21 février 2014 - 08:50 .


#17
henesua

henesua
  • Members
  • 3 867 messages
Furnaceden, I'm glad to have been part of the help.

As far as how to solve your problem goes, I recommend that you create a special script for handling the jailing of the PC. The confiscation of belongings portion of this script could call two functions:

Function 1: would unequip everything on the PC
Function 2: would move everything in the PCs inventory to where ever you want it kept. Function 2 is the one we've been working on.

Alternatively instead of using those two functions, you could probably use Proleric1's function. I believe it does everything you have asked for in the confiscation department.

#18
meaglyn

meaglyn
  • Members
  • 809 messages
My testing is showing that CopyItem() does not copy modified descriptions. It does copy the name and variables correctly. So you do need to do that SetDescription(oCopy, GetDescription(oItem)) even in the CopyItem path.

#19
henesua

henesua
  • Members
  • 3 867 messages
nice catch, meaglyn.

#20
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
Crafting. I think CopyItem handles this already, but it's handy for Creates, in a situation where you have to go that way.

Funky

Modifié par FunkySwerve, 22 février 2014 - 03:32 .


#21
WhiZard

WhiZard
  • Members
  • 1 204 messages

meaglyn wrote...

henesua wrote...
I forget why i did not copy objects with inventory.


I think it just doesn't work, at least if there is anything in it.


CopyItem does nothing for an object with inventory.  CopyObject copies the container and all its inventory, however I have heard of problems with identifiers on the container being placed on the inventory items, I don't remember if it was tags, resrefs, or something else; but the outcome was hardly desirable for trying to keep things intact.

#22
meaglyn

meaglyn
  • Members
  • 809 messages

WhiZard wrote...

CopyItem does nothing for an object with inventory.  CopyObject copies the container and all its inventory, however I have heard of problems with identifiers on the container being placed on the inventory items, I don't remember if it was tags, resrefs, or something else; but the outcome was hardly desirable for trying to keep things intact.


For one thing CopyObject does not copy variables so if you use variables on your items (which I do) you lose all of that using CopyObject.

#23
Furnaceden

Furnaceden
  • Members
  • 3 messages
Thanks again, everyone.

I will be piecing things together and testing it all out. Also, thanks for the heads-up about copying modified descriptions. That is of course an important factor.

I'm still watching this thread so if any other advice comes to mind, please post. I will update with any useful findings in the not-too-distant future after I take this for a test run.