Jump to content

Item importation


argent77

Recommended Posts

I'm curious what are the containers "K#ImportContainer" on maps BD6100 and AR0602 needed for? They are used to store and transfer party equipment during the SoD/SoA transition. But then there is nothing done with them. Do you plan to do something with them later on?

The way they are currently used seems to prevent the IMPORTxx.2DA files (and mod-added import tables) as well as certain unique BG1 items from being processed in the SoA starting dungeon script.

Link to comment
I'm curious what are the containers "K#ImportContainer" on maps BD6100 and AR0602 needed for? They are used to store and transfer party equipment during the SoD/SoA transition. But then there is nothing done with them. Do you plan to do something with them later on?

 

EET_Tweaks will have optional tweak that moves all non-imported party inventory to the container near Ilyich (that hostile Duergar Dwarf). Modders can also access this container to do something neat with these items (even if that tweak is installed - items will be moved by that tweak when you are near Ilyich, so plenty of time to move some/all of them somewhere else or set additional variables).

 

The way they are currently used seems to prevent the IMPORTxx.2DA files (and mod-added import tables) as well as certain unique BG1 items from being processed in the SoA starting dungeon script.

 

 

As you can see in changelog I've been messing with item importration for RC6, Here is how it now works (well not yet, since RC6 is unreleased):

 

1. BD6100.ARE (last area in SoD) and AR0602.ARE (Irenicus Dungeon) have invisible 'K#ImportContainer' containers

 

2. At the end of SoD invisible 'K#TELBGT.CRE' is spawned that has this transition code as an Override script:

 

 

IF
  Global("K#FrameDelay","LOCALS",0)
THEN
  RESPONSE #100
    SetGlobal("K#FrameDelay","LOCALS",1)
    DisableAI(Player1,FALSE)
    DisableAI(Player2,FALSE)
    DisableAI(Player3,FALSE)
    DisableAI(Player4,FALSE)
    DisableAI(Player5,FALSE)
    DisableAI(Player6,FALSE)
    ApplySpellRES("K#REST",Player1) // No such index
    ApplySpellRES("K#REST",Player2) // No such index
    ApplySpellRES("K#REST",Player3) // No such index
    ApplySpellRES("K#REST",Player4) // No such index
    ApplySpellRES("K#REST",Player5) // No such index
    ApplySpellRES("K#REST",Player6) // No such index
    ActionOverride(Player2,MakeUnselectable(1))
    ActionOverride(Player3,MakeUnselectable(1))
    ActionOverride(Player4,MakeUnselectable(1))
    ActionOverride(Player5,MakeUnselectable(1))
    ActionOverride(Player6,MakeUnselectable(1))
    SetGlobal("K#temp","GLOBAL",29)
    AdvanceTime(ONE_MONTH)
    AddGlobals("K#DaysPassed","K#temp")
    TakeObjectGoldGlobal("K#ImportGold","GLOBAL",Player1)
    TakeItemListPartyNum("IMPORT01",1)
    TakeItemListPartyNum("IMPORT02",1)
    TakeItemListPartyNum("IMPORT03",1)
    TakeItemListPartyNum("K#IMPORT",17)
    StartCutSceneEx("BDSODIMP",TRUE)
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player1,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player2,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player3,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player4,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player5,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player6,ALL))
END

IF
  Global("K#FrameDelay","LOCALS",1)
THEN
  RESPONSE #100
    SetGlobal("K#FrameDelay","LOCALS",2)
    ApplySpellRES("K#UNREST",Player1) // No such index
    ApplySpellRES("K#UNREST",Player2) // No such index
    ApplySpellRES("K#UNREST",Player3) // No such index
    ApplySpellRES("K#UNREST",Player4) // No such index
    ApplySpellRES("K#UNREST",Player5) // No such index
    ApplySpellRES("K#UNREST",Player6) // No such index
END

IF
  InPartyAllowDead(Player2)
  !Name("None",Player2)
THEN
  RESPONSE #100
    ActionOverride(Player2,LeaveParty())
    ActionOverride(Player2,DestroySelf())
    Continue()
END

IF
  InPartyAllowDead(Player3)
  !Name("None",Player3)
THEN
  RESPONSE #100
    ActionOverride(Player3,LeaveParty())
    ActionOverride(Player3,DestroySelf())
    Continue()
END

IF
  InPartyAllowDead(Player4)
  !Name("None",Player4)
THEN
  RESPONSE #100
    ActionOverride(Player4,LeaveParty())
    ActionOverride(Player4,DestroySelf())
    Continue()
END

IF
  InPartyAllowDead(Player5)
  !Name("None",Player5)
THEN
  RESPONSE #100
    ActionOverride(Player5,LeaveParty())
    ActionOverride(Player5,DestroySelf())
    Continue()
END

IF
  InPartyAllowDead(Player6)
  !Name("None",Player6)
THEN
  RESPONSE #100
    ActionOverride(Player6,LeaveParty())
    ActionOverride(Player6,DestroySelf())
    Continue()
END

IF
  True()
THEN
  RESPONSE #100
    GivePartyAllEquipment()
    SetGlobal("SPRITE_IS_DEADKHALID","GLOBAL",1)
    SetGlobal("SPRITE_IS_DEADDYNAHEIR","GLOBAL",1)
    SetGlobal("SPRITE_IS_DEADCALAHAN","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADCARBOS","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADDIANA","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADEDWIN","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADFTOWNNASH3","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADGORF","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADIMOEN2","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADKING","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADKNIGHT1","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADPAWN","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADQUEEN","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADROGER","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADSENDAI","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADSHANK","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADTARNOR","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADTAZOK","GLOBAL",0)
    SetGlobal("SPRITE_IS_DEADWILLIAM","GLOBAL",0)
    Wait(1)
    MoveToCampaign("SoA")
    LeaveAreaLUAPanic("AR0602","",[3744.2801],S)
    ActionOverride(Player1,LeaveAreaLUA("AR0602","",[3744.2801],S))
    ActionOverride(Player2,LeaveAreaLUA("AR0602","",[3585.2917],SWW))
    ActionOverride(Player3,LeaveAreaLUA("AR0602","",[3532.2956],NW))
    ActionOverride(Player4,LeaveAreaLUA("AR0602","",[3374.3068],NNE))
    ActionOverride(Player5,LeaveAreaLUA("AR0602","",[3824.2447],E))
    ActionOverride(Player6,LeaveAreaLUA("AR0602","",[3889.2479],SSE))
    MultiPlayerSync()
    DestroySelf()
END

 

 

 

3. As you can see above transition creature:

- stores all party gold in "K#ImportGold" global variable

- takes 3 items from party using IMPORT01-03.2DA (default BG2 item importation)

- takes 17 more items from party using K#IMPORT.2DA (by default it contains MISC47, CHAN06, SW1H15, SW1H16, so other default items referenced in AR0602. Other slots are empty, so modders can use them)

- starts slightly modified version of vanilla SoD 'BDSODIMP.BCS' (added TakePartyItem and DestroyItem to each reference) which not only sets variable for SoD items but also destroy them to not create duplicates (patch 2.x distributes these items in BG2:EE content)

- moves all the rest of party items to K#ImportContainer

- kicks out non-multiplayer characters

- gives back Player1 items that the creature took from the party (that is why it was 3 + up to 17)

 

4. So now we're in Irenicus Dungeon with all BG2 importation items in player 1 inventory (so vanilla code that calls IMPORT01-03.2DA and checks for item presence can detect them) and all SoD items imported (variables already set)

 

5. Code that destroys Inventory in Irenicus Dungeon has been removed

 

6. Remaining items from party inventory (from BD6100 and those still in inventory during Irenicus Dungeon) ends up in invisisble container in Irenicus Dungeon via:

    ActionOverride("K#ImportContainer",TakeCreatureItems(Player1,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player2,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player3,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player4,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player5,ALL))
    ActionOverride("K#ImportContainer",TakeCreatureItems(Player6,ALL))
    MoveContainerContents("BD6100*K#ImportContainer","AR0602*K#ImportContainer")

The reason why we are checking inventory at the end of SoD is to make sure that all items that belongs to party will be imported rather than just player1 inventory. All importation code from AR0602.BCS remains unchanged, so it still does the job.

 

-----------

 

Things important for modders:

- if you want to edit IMPORT01-03.2DA - no problem, it will work

- if you want to set some additional variables or do something with items before transition to SoA either patch vanilla 'BDSODIMP.BCS' (called in both end SoD area and Irenicus Dungeon) or extend top 'K#TELBGT.BCS'

- if you want to make sure that items will be in player1 inventory at the start of Irenicus Dungeon than add them as new rows to K#IMPORT.2DA

- if you want to do something with other not imported items than feel free to do so by accessing invisible 'K#ImportContainer' container in Irenicus Dungeon

- and the gold is stored in a global variable just in case

 

-----------

 

Until 1.0 (not RC) is released the implementation is not set in stone, so please share your feedback.

Link to comment

 

 

 

5. Code that destroys Inventory in Irenicus Dungeon has been removed

So this mod www.urstuff2athkatla.com is obsolete for EET?

 

yes. The only thing that mod does is removing 'DestroyAllEquipment()' action. In EET what's left on party when it migrates to BG2 (or when character is imported) goes to invisible K#ImportContainer after AR0602 item importation code is done or later to Illych's chest if you install optional tweak. Or wherever modders will move these items. I think mod that for example distributes party items among Athkatla shops would be cool, although I'm not planning to write one.

Link to comment

 

 

 

 

5. Code that destroys Inventory in Irenicus Dungeon has been removed

So this mod www.urstuff2athkatla.com is obsolete for EET?

 

yes. The only thing that mod does is removing 'DestroyAllEquipment()' action. In EET what's left on party when it migrates to BG2 (or when character is imported) goes to invisible K#ImportContainer after AR0602 item importation code is done or later to Illych's chest if you install optional tweak. Or wherever modders will move these items. I think mod that for example distributes party items among Athkatla shops would be cool, although I'm not planning to write one.

 

A mod to add stolen party items (stolen by Irenicus greedy duergars) to shops in Athkatla makes sense.

(although I'm not planning to write one.)

On the other hand, EET will open much more possibilities to gain items (including IWD) and moving back to old areas so that the (old) idea of importing stuff across the formerly separated game parts may become far less important than in the *old* game.

Link to comment

So I can manually add up to 17 entries to the predefined K#IMPORT.2DA which are temporarily placed into Player1's inventory? Alternative #1: I can add my own code to BDSODIMP.BCS to set up variables which can be evaluated later by script. Alternative #2: I can add my own code to K#TELBGT.BCS to do basically the same as in BDSODIMP.BCS.

Let's take the imports from my Golem Construction mod as example. It allows you to import up to 7 items from the party inventory (protagonist and optional multiplayer characters), based on 4 different import tables, to be scattered around the initial level of Chateau Irenicus. What would be the best strategy to support both starting a new game with imported characters and continuing a game from the SoD campaign?

Link to comment

So I can manually add up to 17 entries to the predefined K#IMPORT.2DA,? Alternative #1: I can add my own code to BDSODIMP.BCS to set up variables which can be evaluated later by script. Alternative #2: I can add my own code to K#TELBGT.BCS to do basically the same as in BDSODIMP.BCS.

 

no, all 17 will be imported, not just 1. As you can see in code the creature does this when the party is not kicked yet:

    TakeItemListPartyNum("IMPORT01",1)
    TakeItemListPartyNum("IMPORT02",1)
    TakeItemListPartyNum("IMPORT03",1)
    TakeItemListPartyNum("K#IMPORT",17)

And than it gives back these items to player1 / multiplayer party after other items are moved to invisible container and NPCs are kicked:

GivePartyAllEquipment()

The problem is 20 items limitation (if you give more than the excessive items will be dropped on ground). Not sure how to implement more. Thankfully SoD items importation is done via variables.

 

 

Let's take the imports from my Golem Construction mod as example. It allows you to import up to 7 items from the party inventory (protagonist and optional multiplayer characters), based on 4 different import tables, to be scattered around the initial level of Chateau Irenicus. What would be the best strategy to support both starting a new game with imported characters and continuing a game from the SoD campaign?

in such case you can append all 7 to K#IMPORT.2DA and don't do anything else. Your AR0602.BCS code will work for both character importation and transition (the latter would have benefit of getting these items from whole party rather than just player1 or multi-player characters).

 

Or you could append your item importation code for example to BDSODIMP.BCS with DestroyItem() action since this script is triggered in both SoD ending and in Irenicus Dungeon. Here is how the script looks like when patched by EET:

 

 

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_01","GLOBAL",0)
  PartyHasItem("BDSW1H06") // Voidsword +3
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDSW1H06") // Voidsword +3
    DestroyItem("BDSW1H06") // Voidsword +3
    SetGlobal("BD_SOD_IMPORT_01","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_02","GLOBAL",0)
  PartyHasItem("BDHAMM02") // Voidhammer +3
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDHAMM02") // Voidhammer +3
    DestroyItem("BDHAMM02") // Voidhammer +3
    SetGlobal("BD_SOD_IMPORT_02","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_03","GLOBAL",0)
  PartyHasItem("BDROBE05") // Robe of Red Flames
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDROBE05") // Robe of Red Flames
    DestroyItem("BDROBE05") // Robe of Red Flames
    SetGlobal("BD_SOD_IMPORT_03","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_04","GLOBAL",0)
  PartyHasItem("BDBELT02") // Belt of the Skillful Blade
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDBELT02") // Belt of the Skillful Blade
    DestroyItem("BDBELT02") // Belt of the Skillful Blade
    SetGlobal("BD_SOD_IMPORT_04","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_05","GLOBAL",0)
  PartyHasItem("BDAMUL02") // Archer's Eyes
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDAMUL02") // Archer's Eyes
    DestroyItem("BDAMUL02") // Archer's Eyes
    SetGlobal("BD_SOD_IMPORT_05","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_06","GLOBAL",0)
  PartyHasItem("BDHELM09") // Helmet of Dumathoin
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDHELM09") // Helmet of Dumathoin
    DestroyItem("BDHELM09") // Helmet of Dumathoin
    SetGlobal("BD_SOD_IMPORT_06","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_07","GLOBAL",0)
  PartyHasItem("BDHELM11") // Bard Hat
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDHELM11") // Bard Hat
    DestroyItem("BDHELM11") // Bard Hat
    SetGlobal("BD_SOD_IMPORT_07","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_08","GLOBAL",0)
  PartyHasItem("BDDART01") // Biter +2
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDDART01") // Biter +2
    DestroyItem("BDDART01") // Biter +2
    SetGlobal("BD_SOD_IMPORT_08","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_09","GLOBAL",0)
  PartyHasItem("BDBRD03") // Tangled Strings
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDBRD03") // Tangled Strings
    DestroyItem("BDBRD03") // Tangled Strings
    SetGlobal("BD_SOD_IMPORT_09","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_10","GLOBAL",0)
  PartyHasItem("BDSHLD01") // Buckler of the Fist +2
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDSHLD01") // Buckler of the Fist +2
    DestroyItem("BDSHLD01") // Buckler of the Fist +2
    SetGlobal("BD_SOD_IMPORT_10","GLOBAL",1)
    Continue()
END

IF
  Global("BD_HAVE_SOD","GLOBAL",1)
  Global("BD_SOD_IMPORT_11","GLOBAL",0)
  PartyHasItem("BDSW2H01") // Dragon Blade +3
THEN
  RESPONSE #100
    CutSceneId(Player1)
    TakePartyItem("BDSW2H01") // Dragon Blade +3
    DestroyItem("BDSW2H01") // Dragon Blade +3
    SetGlobal("BD_SOD_IMPORT_11","GLOBAL",1)
    Continue()
END

 

 

 

What about starting new BG2-SoA game?

 

the same. EET just replaces 'DestroyAllEquipment()' action present in AR0602 with ActionOverride("K#ImportContainer",TakeCreatureItems

Link to comment

Just throwing in an idea. Is it possible to use a temporary bag of holding to store all the items marked for importation? You could place it into Player1's inventory so that the script can process the items, and remove it afterwards. That way you're not limited to the 20 slots inventory space. Maybe it's also possible to transfer all containers from the whole party into Player1's inventory to be used during item importation in AR0602. The main issue to solve is probably putting items from all the item tables (or full character inventory?) into the bag via script.

Link to comment

Just throwing in an idea. Is it possible to use a temporary bag of holding to store all the items marked for importation? You could place it into Player1's inventory so that the script can process the items, and remove it afterwards. That way you're not limited to the 20 slots inventory space. Maybe it's also possible to transfer all containers from the whole party into Player1's inventory to be used during item importation in AR0602. The main issue to solve is probably putting items from all the item tables (or full character inventory?) into the bag via script.

 

According to IESDP triggers related to item checks work for bags of holding so this indeed sounds like a good idea :thumbsup: I don't think there is a way to automatically move all items to bag other than referencing each of item 1 by 1 via:

AddStoreItem(S:Store*,S:Item*,I:Count*,I:Flags*)

but that shouldn't be a problem with weidu. To make it easier for modders we can add automatic read from K#IMPORT.2DA and generate the script on the fly via EET_end finalise component (so don't even bother at unique numbers in column 1 - not sure if they even change anything but with this system the file won;t be directly used in game). This way all items referenced in that 2da will end up in player1 inventory after transition.

 

I will implement it for RC6 and we will see if everything works as expected. Thanks for great idea.

Link to comment

I've just tested implementation proposed by argent and it works as expected. Once again thanks for suggestion.

 

All you need to do in order to ensure item importation in your mod is adding code like this:

ACTION_IF GAME_IS ~eet~ BEGIN
  APPEND ~K#IMPORT.2DA~ ~1 SW1H01~ UNLESS ~SW1H01~
  APPEND ~K#IMPORT.2DA~ ~1 SW1H02~ UNLESS ~SW1H02~
  APPEND ~K#IMPORT.2DA~ ~1 MISC01~ UNLESS ~MISC01~
  //etc.
END

this way the code you normally add in AR0602.BCS will be valid for both Character importation and EET migration to SoA. The latter has the benefit of importing unlimited amount of items from whole party rather than just player1.

Link to comment

Great work. :goodwork:

 

To clarify, that means in addition to the regular AR0602.BCS importation code I have to add the items in question to K#IMPORT.2DA as well if EET has been detected?

 

Thanks. Following files are checked during last component installation to automatically generate item importation code:

- BDSODIMP.BCS

- IMPORT01.2DA

- IMPORT02.2DA

- IMPORT03.2DA

- K#IMPORT.2DA

 

So if your mod doesn't extend any of these first 4 vanilla files by default you will need to append your file name to K#IMPORT.2DA in order to make it detectable from the Player1 inventory in Irenicus Dungeon (if party migrated from SoD that is). Amount of files doesn't matter since all imported items sits in dummy bag of holding, so feel free to append as many as you like.

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...