Difference between revisions of "Talk:DuplicateAllItems"

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search
imported>Haama
imported>Scruggs
(thanks for the explanation)
 
(5 intermediate revisions by 2 users not shown)
Line 11: Line 11:
:At the very, very least, I'm certain that items don't lose their script (those, as with any new item, the variables start off at 0)
:At the very, very least, I'm certain that items don't lose their script (those, as with any new item, the variables start off at 0)
:--[[User:Haama|Haama]] 00:04, 10 July 2007 (EDT)
:--[[User:Haama|Haama]] 00:04, 10 July 2007 (EDT)
:Here's the test script. It adds a key with a script on it to the player, the uses DuplicateAllItems to a persistent remote container, scans through the player's inventory and removes each of those items from the remote container, and then opens the container. When opened, the container would still have a copy of the key in it (meaning it was a different FormID), and when you took the key it's OnAdd block would fire (meaning it still had a script, and since the variables on the original were set when first added to the player, it also meant the variables of the duped item were at 0). This happened for other items with scripts on them as well.
<pre>scn aaaTestScript
;Results - health/charge/etc. doesn't seem to matter
;  However, scripted items won't have the same ID
;    Also, scripted items seem to keep their script, at least when moved to the player
;    Also, the ID for scripted objects changes each time, so whenever you duplicate you get an extra item that counts towards GetNumItems
short InvPosition
ref pInvObj
short InvObjAmount
short NumItems
begin GameMode
  player.AddItem MQ07BasementKey 1
  player.DuplicateAllItems aaaTestCont
  set InvPosition to (player.GetNumItems - 1)
  Label 1
  if (InvPosition >= 0)
    set pInvObj to (player.GetInventoryObject InvPosition)
    if (aaaTestCont.GetItemCount pInvObj)
      set InvObjAmount to (aaaTestCont.GetItemCount pInvObj)
      aaaTestCont.RemoveItem pInvObj InvObjAmount
    endif
    set InvPosition to (InvPosition - 1)
  Goto 1
  endif
set NumItems to aaaTestCont.GetNumItems
message "aaaTestCont has %.0f items", NumItems
aaaTestCont.Activate player
  StopQuest aaaTest
end</pre>
:--[[User:Haama|Haama]] 00:15, 10 July 2007 (EDT)
:: Hmm. I think the problem with that script is that it checks getItemCount immediately following addItem. You can't rely on the item to be added immediately - it may not appear in the inventory for at least one frame.
:: The reason I say this is that the formID of the base object '''doesn't''' appear to change after calling duplicateAllItems. You can check this yourself if you have two containers: one empty and one with a single item in it (for simplicity's sake). Call duplicateAllItems to copy the item in one container to the other. Then check getInventoryObject 0 on both containers - you will get the same formID both times. [[User:Scruggs|Scruggs]] 00:45, 10 July 2007 (EDT)
:::For items without scripts the formID will be the same, but scripted items will have new formIDs (FFs, so cloned formIDs). Here's some more through tests - Setup: beginning player with several armour pieces, etc. and an amulet of kings as the only scripted item. First test is the same as above, but one line has been added to the end
<pre>set pInvObj to (aaaTestCont.GetInventoryObject 0)</pre>
:::(and checked with SQV aaaTest). The second test copies an amulet of kings from one chest to another, and grabs the base object ID. The final test turns the amulet of kings into a non-quest item, and repeats the second test. For all of them, the ''duped'' amulet of kings base object had new FormIDs (FF000B13, FF000B14, FF000B15) and when I took them from the inventory they wouldn't stack with the other amulet of kings (and after the final test I was able to drop only 2 of them). Here's the code:
<pre>scn aaaTestScript
short InvPosition
ref pInvObj
short InvObjAmount
short NumItems
short Test
begin GameMode
  if (Test == 0)
;  player.AddItem MQ07BasementKey 1
    player.DuplicateAllItems aaaTestCont
    set InvPosition to (player.GetNumItems - 1)
    Label 1
    if (InvPosition >= 0)
      set pInvObj to (player.GetInventoryObject InvPosition)
      if (aaaTestCont.GetItemCount pInvObj)
        set InvObjAmount to (aaaTestCont.GetItemCount pInvObj)
        aaaTestCont.RemoveItem pInvObj InvObjAmount
      endif
      set InvPosition to (InvPosition - 1)
      Goto 1
    endif
    set NumItems to aaaTestCont.GetNumItems
    message "aaaTestCont has %.0f items", NumItems
    set pInvObj to (aaaTestCont.GetInventoryObject 0)
    aaaTestCont.Activate player
  elseif (Test == 1)
    aaaTestCont.RemoveAllItems
    aaaTestCont.AddItem AmuletOfKings 1
    aaaTestCont.DuplicateAllItems aaaTestCont2
    set pInvObj to (aaaTestCont2.GetInventoryObject 0)
    aaaTestCont2.Activate player
  elseif (Test == 2)
    SetQuestItem 0 AmuletOfKings
    aaaTestCont.RemoveAllItems
    aaaTestCont.AddItem AmuletOfKings 1
    aaaTestCont.DuplicateAllItems aaaTestCont2
    set pInvObj to (aaaTestCont2.GetInventoryObject 0)
    aaaTestCont2.Activate player
  endif
  StopQuest aaaTest
end</pre>
:::By the way, this has proven true for both CSv.8/Obv1.1 and CSv1.2/OBv1.4.2 so far.
:::--[[User:Haama|Haama]] 01:54, 10 July 2007 (EDT)
:::: Oh, I see. Thanks for clearing that up. And I have to repeat: that's just weird.  ;) [[User:Scruggs|Scruggs]] 02:34, 10 July 2007 (EDT)

Latest revision as of 01:34, 10 July 2007

The duplicate will have a new FormID, meaning if (Original == New) will never be true

    * More importantly, meaning if any script referenced the original the duplicate
 will not work. For instance if (player.GetItemCount AmuletOfKings) will never be true
 if the player has the duplicate. 

Really? That's...weird. Are we sure about this? Scruggs 23:56, 9 July 2007 (EDT)

Try it, and yes I'm very sure... many objects were broken upon this discovery... well, ideas were broken, and a request for DuplicateAllItems2 was made
Hmm... let me see if I can find the test file, though
--Haama 00:02, 10 July 2007 (EDT)
At the very, very least, I'm certain that items don't lose their script (those, as with any new item, the variables start off at 0)
--Haama 00:04, 10 July 2007 (EDT)
Here's the test script. It adds a key with a script on it to the player, the uses DuplicateAllItems to a persistent remote container, scans through the player's inventory and removes each of those items from the remote container, and then opens the container. When opened, the container would still have a copy of the key in it (meaning it was a different FormID), and when you took the key it's OnAdd block would fire (meaning it still had a script, and since the variables on the original were set when first added to the player, it also meant the variables of the duped item were at 0). This happened for other items with scripts on them as well.
scn aaaTestScript

;Results - health/charge/etc. doesn't seem to matter
;  However, scripted items won't have the same ID
;    Also, scripted items seem to keep their script, at least when moved to the player
;    Also, the ID for scripted objects changes each time, so whenever you duplicate you get an extra item that counts towards GetNumItems

short InvPosition
ref pInvObj
short InvObjAmount

short NumItems

begin GameMode
  player.AddItem MQ07BasementKey 1
  player.DuplicateAllItems aaaTestCont
  set InvPosition to (player.GetNumItems - 1)
  Label 1
  if (InvPosition >= 0)
    set pInvObj to (player.GetInventoryObject InvPosition)
    if (aaaTestCont.GetItemCount pInvObj)
      set InvObjAmount to (aaaTestCont.GetItemCount pInvObj)
      aaaTestCont.RemoveItem pInvObj InvObjAmount
    endif
    set InvPosition to (InvPosition - 1)
   Goto 1
  endif
set NumItems to aaaTestCont.GetNumItems
message "aaaTestCont has %.0f items", NumItems
aaaTestCont.Activate player
  StopQuest aaaTest
end
--Haama 00:15, 10 July 2007 (EDT)
Hmm. I think the problem with that script is that it checks getItemCount immediately following addItem. You can't rely on the item to be added immediately - it may not appear in the inventory for at least one frame.
The reason I say this is that the formID of the base object doesn't appear to change after calling duplicateAllItems. You can check this yourself if you have two containers: one empty and one with a single item in it (for simplicity's sake). Call duplicateAllItems to copy the item in one container to the other. Then check getInventoryObject 0 on both containers - you will get the same formID both times. Scruggs 00:45, 10 July 2007 (EDT)
For items without scripts the formID will be the same, but scripted items will have new formIDs (FFs, so cloned formIDs). Here's some more through tests - Setup: beginning player with several armour pieces, etc. and an amulet of kings as the only scripted item. First test is the same as above, but one line has been added to the end
set pInvObj to (aaaTestCont.GetInventoryObject 0)
(and checked with SQV aaaTest). The second test copies an amulet of kings from one chest to another, and grabs the base object ID. The final test turns the amulet of kings into a non-quest item, and repeats the second test. For all of them, the duped amulet of kings base object had new FormIDs (FF000B13, FF000B14, FF000B15) and when I took them from the inventory they wouldn't stack with the other amulet of kings (and after the final test I was able to drop only 2 of them). Here's the code:
scn aaaTestScript


short InvPosition
ref pInvObj
short InvObjAmount

short NumItems

short Test



begin GameMode
  if (Test == 0)
;  player.AddItem MQ07BasementKey 1
    player.DuplicateAllItems aaaTestCont
    set InvPosition to (player.GetNumItems - 1)
    Label 1
    if (InvPosition >= 0)
      set pInvObj to (player.GetInventoryObject InvPosition)
      if (aaaTestCont.GetItemCount pInvObj)
        set InvObjAmount to (aaaTestCont.GetItemCount pInvObj)
        aaaTestCont.RemoveItem pInvObj InvObjAmount
      endif
      set InvPosition to (InvPosition - 1)
      Goto 1
    endif
    set NumItems to aaaTestCont.GetNumItems
    message "aaaTestCont has %.0f items", NumItems
    set pInvObj to (aaaTestCont.GetInventoryObject 0)
    aaaTestCont.Activate player
  elseif (Test == 1)
    aaaTestCont.RemoveAllItems
    aaaTestCont.AddItem AmuletOfKings 1
    aaaTestCont.DuplicateAllItems aaaTestCont2
    set pInvObj to (aaaTestCont2.GetInventoryObject 0)
    aaaTestCont2.Activate player
  elseif (Test == 2)
    SetQuestItem 0 AmuletOfKings
    aaaTestCont.RemoveAllItems
    aaaTestCont.AddItem AmuletOfKings 1
    aaaTestCont.DuplicateAllItems aaaTestCont2
    set pInvObj to (aaaTestCont2.GetInventoryObject 0)
    aaaTestCont2.Activate player
  endif
  StopQuest aaaTest
end
By the way, this has proven true for both CSv.8/Obv1.1 and CSv1.2/OBv1.4.2 so far.
--Haama 01:54, 10 July 2007 (EDT)
Oh, I see. Thanks for clearing that up. And I have to repeat: that's just weird.  ;) Scruggs 02:34, 10 July 2007 (EDT)