Any scripting method for transferring all inventory items to a remote container?
#1
Posté 20 février 2014 - 10:57
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
Posté 21 février 2014 - 01:04
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
Posté 21 février 2014 - 04:51
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
Posté 21 février 2014 - 08:46
- 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 .
#6
Posté 21 février 2014 - 04:23
#7
Posté 21 février 2014 - 04:43
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
Posté 21 février 2014 - 05:00
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
Posté 21 février 2014 - 05:17
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
Posté 21 février 2014 - 06:10
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.
Funky
#11
Posté 21 février 2014 - 06:21
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...
Proleric1, your script doesn't accomplish one thing that henesua's script accomplishes, that is keeping the inventory contents in the same container.
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.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. ...
Incidentally, I'm using CopyItem, which is faster and preserves variables, as FunkySwerve says.
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...
@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).
Yes, I wondered if anyone ever did that.meaglyn wrote...
One issue with the containers part of Henesua's is variables on the container.
Good discussion.
Modifié par Proleric1, 21 février 2014 - 06:24 .
#12
Posté 21 février 2014 - 06:29
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
Posté 21 février 2014 - 07:27
I hope the OP is getting what they need. If not, speak up.
#14
Posté 21 février 2014 - 07:43
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
Posté 21 février 2014 - 08:38
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.
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
Posté 21 février 2014 - 08:45
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
Posté 21 février 2014 - 09:18
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
Posté 22 février 2014 - 01:39
#19
Posté 22 février 2014 - 03:12
#21
Posté 22 février 2014 - 04:33
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
Posté 22 février 2014 - 02:52
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
Posté 23 février 2014 - 07:03
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.





Retour en haut






