Skip to content

Tool To Extract Or Export Lists, Names, Descriptions, Resources, Etc. Of Files

AbelAbel Member Posts: 785
edited January 2014 in General Modding
Is there such a thing out there?
Right now, I'd like to export a list of items (not the items files but a list of them) from a specific store.
I know EEKeeper can do so in a txt or csv but with all items and only for items, spells and creatures.
I tried DLTCEP, NI and some older tools but they can only read and show in a GUI the information I need. They can extract files too, but that's all. I gave a quick look at Weidu too, but it doesn't seem to be able to process anything deeper than the file level.

Comments

  • IsayaIsaya Member, Translator (NDA) Posts: 752
    Using WeiDU you would be able to read the store file content and generate a text file of its content using the format that suits you, but that requires learning how to manipulate data of the STO file in a tp2 file and mimick a mod installation that would simply generate a listing file instead of installing anything.

    Using Near Infinity is probably easier if you want to process only a few files. You can print the content of the file when you're in the Edit tab of the store. If you install a PDF printer such as PDF Creator, you can print the content of the window (it will "scroll" to print the full content) in a PDF file. Then in your PDF viewer, you'll be able to select the list of item among the rest.
  • AbelAbel Member Posts: 785
    edited January 2014
    Haha, merci @Isaya ;) !
    You're right! Actually, it's the only way in NI. I found that I could select and copy/paste the content of the edit tab indeed. Alas, not all information where there. I also tried printing, but when the line is too long, it prints "..." and leaves some content.

    I'm intrigued about the method you describe for Weidu. I'm looking into the documentation. I see there's a BYTE_AT offset function. Also READ_BYTE offset variable [ ELSE value ]. Is that what you're thinking about?
    Post edited by Abel on
  • AbelAbel Member Posts: 785
    edited February 2014
    So, I found the answer for WeiDU :) ! Link here.
  • IsayaIsaya Member, Translator (NDA) Posts: 752
    edited February 2014
    I'm sorry I missed your previous answer.

    I have some WeiDU code that extract shop details like this, if you want:
    Nom : Erdane
    Code : ERDANE
    Type : Magasin
    Flags : vend, achète,
    Taux vente : 150
    Taux achat : 50
    Taux dépréciation : 5
    Echec du vol à la tire : 20
    Coût d'identification : 100
    Prix des chambres :
    Soins proposés : non extrait
    Types d'objets achetés : non extrait
    Boissons : non extrait
    Objets à vendre : Code Charges Nombre à vendre Stock
    LEAT10 0 1 Stock réapprovisionné
    DAGG01 0 10 Stock limité
    DART01 10 5 Stock réapprovisionné
    DART02 10 50 Stock limité
    DART03 10 20 Stock limité
    SW1H20 0 5 Stock réapprovisionné
    AROW01 20 0 Stock réapprovisionné
    AROW04 10 40 Stock limité
    AROW02 10 100 Stock limité
    AROW08 10 40 Stock limité
    BOLT01 20 1 Stock réapprovisionné
    BOLT02 10 100 Stock limité
    BOLT03 10 60 Stock limité
    BULL01 20 1 Stock réapprovisionné
    BULL02 10 30 Stock limité
    BULL03 1 80 Stock limité
    POTN08 1 20 Stock limité
    POTN36 1 15 Stock limité
    POTN19 1 5 Stock limité
    POTN03 1 5 Stock limité
    POTN20 1 10 Stock limité
    POTN39 1 5 Stock limité
    WAND05 20 1 Stock limité
    It was written for Baldur's Gate / Baldur's Gate II, but I believe there is no change in BGEE.

    I wasn't interested in extracting what the shop buys, but it's not big deal to add.

    You can indeed extract a lot of data from the game files using WeiDU, provided you learn the files structures. I used similar code to automate almost completely generation of articles about items (sample) and spells for an encyclopedia on a French website.
    I started from the forum topic you found, especially from Miloch's code.

    Now it's just thousands of line of probably bad WeiDU code though.
  • AbelAbel Member Posts: 785
    Hey @Isaya, no problem at all!
    I would gladly have a look at what code you still hold and are willing to share.
    The website is very well made. Still misses some information, but I see there's an extensive bestiary!
  • IsayaIsaya Member, Translator (NDA) Posts: 752
    I'm mostly dealing with what can be automated, namely spells and items, and also looking for where to find items in the game (thank you again WeiDU, and NI for "search for reference" for all tricky cases). I agree the bestiary work done is amazing (a math teacher devised the monster threat rating ;-) ).

    Here is the shop data extraction code.
    // --------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------- // Liste de magasins/sacs // --------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------- BEGIN ~Liste des magasins~ NO_LOG_RECORD OUTER_INNER_PATCH ~12~ BEGIN WRITE_BYTE 1 0x0a READ_ASCII 1 lnl(1) WRITE_BYTE 0 0x0d READ_ASCII 0 mnl(1) READ_ASCII 0 nl(2) END OUTER_SPRINT ~list~ ~~ OUTER_SPRINT ~article~ ~~ OUTER_SPRINT ~stoitemlist~ ~~ // Partie tableau <<<<<<<< .../extractSortObjetBG-inlined/t-stotmp.txt ResRef;Name;Flags;Type >>>>>>>> COPY ~.../extractSortObjetBG-inlined/t-stotmp.txt~ ~override/stolist.csv~ // Partie description <<<<<<<< .../extractSortObjetBG-inlined/t-stodesctmp.txt Description et contenu des magasins et sacs, en enrichir si on envisage de faire des articles >>>>>>>> COPY ~.../extractSortObjetBG-inlined/t-stodesctmp.txt~ ~override/stodesc.txt~ // Liste d'objets en magasin <<<<<<<< .../extractSortObjetBG-inlined/t-stoitemtmp.txt Liste d'objets présents en magasin : non classée, avec doublons (accumulation magasin par magasin) >>>>>>>> COPY ~.../extractSortObjetBG-inlined/t-stoitemtmp.txt~ ~override/stoitemlist.txt~ // Extraction proprement dite des données des magasins // Liste établie à partir d'une recherche de dialogues et de créatures ouvrant le magasin (StartStore) SPRINT ~crg~ ~\(ERDANE\|FRIEND\|HIGHHEDG\|INN0103\|INN0105\|INN0119\|INN2616\|INN3304\|INN3307\|INN3351\|INN3357\|INN4801\|STO0703\|STO1112\|STO1115\|STO4803\|STO4901\|STO4906\|STO4908\|STO4909\|STOBLACK\|STOCHEAP\|STOSILEN\|STOVAI\|TAERUM\|TAV0114\|TAV0154\|TAV0705\|TAV0721\|TAV1215\|TAV4809\|TEM0002\|TEM0131\|TEM0132\|TEM2304\|TEM2601\|TEM3402\|TEM4802\|ULGOTH\)\.sto~ COPY_EXISTING_REGEXP GLOB ~%crg%~ ~override~ PATCH_IF (~%SOURCE_SIZE%~ > 0x9b) BEGIN // Les manipulations ultérieures vont écraser SOURCE_RES, hors on veut garder le nom du magasin SPRINT ~nomSto~ ~%SOURCE_RES%~ // Type READ_LONG 0x08 type PATCH_IF (type = ~0~) BEGIN SPRINT ~strtype~ ~Magasin~ END ELSE PATCH_IF (type = ~1~) BEGIN SPRINT ~strtype~ ~Taverne~ END ELSE PATCH_IF (type = ~2~) BEGIN SPRINT ~strtype~ ~Auberge~ END ELSE PATCH_IF (type = ~3~) BEGIN SPRINT ~strtype~ ~Temple~ END ELSE PATCH_IF (type = ~5~) BEGIN SPRINT ~strtype~ ~Conteneur~ END ELSE SPRINT ~strtype~ ~inconnu~ // Nom READ_LONG 0x0c strrefname READ_STRREF 0x0c name // Flags READ_LONG 0x10 flags SPRINT ~strflags~ ~~ PATCH_IF (((flags & 0b00000000000000000000000000000001) >> 0) = 1) BEGIN SPRINT ~strflags~ ~%strflags%vend, ~ END PATCH_IF (((flags & 0b00000000000000000000000000000010) >> 1) = 1) BEGIN SPRINT ~strflags~ ~%strflags%achète, ~ END PATCH_IF (((flags & 0b00000000000000000000000000000100) >> 2) = 1) BEGIN SPRINT ~strflags~ ~%strflags%identifie, ~ END PATCH_IF (((flags & 0b00000000000000000000000000001000) >> 3) = 1) BEGIN SPRINT ~strflags~ ~%strflags%vol possible, ~ END PATCH_IF (((flags & 0b00000000000000000000000000010000) >> 4) = 1) BEGIN SPRINT ~strflags~ ~%strflags%accepte don, ~ END PATCH_IF (((flags & 0b00000000000000000000000000100000) >> 5) = 1) BEGIN SPRINT ~strflags~ ~%strflags%vend soin, ~ END PATCH_IF (((flags & 0b00000000000000000000000001000000) >> 6) = 1) BEGIN SPRINT ~strflags~ ~%strflags%vend boisson, ~ END PATCH_IF (((flags & 0b00000000000000000001000000000000) >> 12) = 1) BEGIN SPRINT ~strflags~ ~%strflags%receleur~ END READ_LONG 0x14 pourcentvente READ_LONG 0x18 pourcentachat READ_LONG 0x1c depreciation READ_SHORT 0x20 echecvol READ_LONG 0x40 coutident // Chambres SPRINT chambres ~~ PATCH_IF type = 2 THEN BEGIN READ_LONG 0x5c roomflags PATCH_IF (((roomflags & 0b00000000000000000000000000000001) >> 0) = 1) BEGIN READ_LONG 0x60 prix SPRINT ~chambres~ ~%chambres%Paysan (%prix%), ~ END PATCH_IF (((roomflags & 0b00000000000000000000000000000010) >> 1) = 1) BEGIN READ_LONG 0x64 prix SPRINT ~chambres~ ~%chambres%Marchand (%prix%), ~ END PATCH_IF (((roomflags & 0b00000000000000000000000000000100) >> 2) = 1) BEGIN READ_LONG 0x68 prix SPRINT ~chambres~ ~%chambres%Noble (%prix%), ~ END PATCH_IF (((roomflags & 0b00000000000000000000000000001000) >> 3) = 1) BEGIN READ_LONG 0x6c prix SPRINT ~chambres~ ~%chambres%Royal (%prix%), ~ END END // PATCH_IF SPRINT listeobjet ~~ PATCH_IF (~%strflags%~ STRING_CONTAINS_REGEXP ~vend,~) = 0 THEN BEGIN // Vend des objets ~strtype~ ~Magasin~ SPRINT listeobjet ~Objets à vendre : Code Charges Nombre à vendre Stock~ // Lecture des objets // repris du tutorial 9.24 de la doc WeiDU, et adapté au fichier STO GET_OFFSET_ARRAY item_array 0x34 4 0x38 4 0 0 0x1c PHP_EACH item_array AS int => item_off BEGIN // READ_ASCII (item_off + 0x00) codeObjet READ_SHORT (item_off + 0x0a) charge READ_LONG (item_off + 0x14) stock READ_LONG (item_off + 0x18) reappro PATCH_IF reappro = 0 BEGIN SPRINT strreappro ~Stock limité~ END ELSE PATCH_IF reappro = 1 BEGIN SPRINT strreappro ~Stock réapprovisionné~ END ELSE BEGIN SPRINT strreappro ~Réapprovisionnement invalide~ END SPRINT listeobjet ~%listeobjet%%nl%%codeObjet% %charge% %stock% %strreappro%~ SPRINT stoitemlist ~%stoitemlist%%nl%%codeObjet%~ END // PHP_EACH END // PATCH_IF // Ecriture seulement si le nom et la description de l'objet sont définis // Pas applicable pour les magasins car certains n'ont pas de nom //PATCH_IF (strrefname >= 0) AND (strrefname <= 24123) PATCH_IF (type = ~0~) OR (type = ~1~) OR (type = ~2~) OR (type = ~3~) THEN BEGIN // Liste de magasins SPRINT ~list~ ~%list%%nomSto%;%name%;%strflags% (%flags%);%strtype% (%type%) %nl%~ // Information pour magasin, taverne, auberge, temple, ou sac SPRINT ~nouvmag~ ~[HR][/HR] Nom : %name% Code : %nomSto% Type : %strtype% Flags : %strflags% Taux vente : %pourcentvente% Taux achat : %pourcentachat% Taux dépréciation : %depreciation% Echec du vol à la tire : %echecvol% Coût d'identification : %coutident% Prix des chambres : %chambres% Soins proposés : non extrait Types d'objets achetés : non extrait Boissons : non extrait %listeobjet%~ // Ajout de l'article SPRINT ~article~ ~%article%%nl%%nl%%nl%%nouvmag%~ END // PATCH_IF (strrefname >= 0) AND (strrefname <= 24123) END // PATCH_IF (~%SOURCE_SIZE%~ > 0x9b) BUT_ONLY_IF_IT_CHANGES // Ecritures des fichiers APPEND ~stolist.csv~ ~%list%~ APPEND ~stodesc.txt~ ~%article%~ APPEND ~stoitemlist.txt~ ~%stoitemlist%~
    It's very much inspired by Miloch's code and by my attempts at extracting item and spell data.
    This part is somehow readable, as it's purely informative.
    In comparison, my item extraction code is a mess, partly due to including a lot of formatting constraints for the articles.
    For the rest of the code, if you have a use, I'll either attach or send by mail due to size.
  • AbelAbel Member Posts: 785
    Very interesting!
    How exactly do you use this?
    <<<<<<<< >>>>>>>>
    What do you use this for?
    OUTER_INNER_PATCH ~12~ BEGIN WRITE_BYTE 1 0x0a READ_ASCII 1 lnl(1) WRITE_BYTE 0 0x0d READ_ASCII 0 mnl(1) READ_ASCII 0 nl(2) END
    I see you somehow copied txt into csv. Didn't know it was possible:
    COPY ~.../extractSortObjetBG-inlined/t-stotmp.txt~ ~override/stolist.csv~
    It's amusing to see how you use SPRINT to set variables. Didn't think about it:
    SPRINT ~crg~ ~\(ERDANE\|FRIEND\|HIGHHEDG\|INN0103\|INN0105\|INN0119\|INN2616\|INN3304\|INN3307\|INN3351\|INN3357\|INN4801\|STO0703\|STO1112\|STO1115\|STO4803\|STO4901\|STO4906\|STO4908\|STO4909\|STOBLACK\|STOCHEAP\|STOSILEN\|STOVAI\|TAERUM\|TAV0114\|TAV0154\|TAV0705\|TAV0721\|TAV1215\|TAV4809\|TEM0002\|TEM0131\|TEM0132\|TEM2304\|TEM2601\|TEM3402\|TEM4802\|ULGOTH\)\.sto~
    If it's no bother, yes, could you attach the other files?
  • IsayaIsaya Member, Translator (NDA) Posts: 752
    <<< and >>> (with the exact amount of them, not this short form) is used to create an external file with the name stated after <<< and containing the text in between. This is better explained in chapter 8 of the WeiDU documentation.
    You could without if you included the same content in a file in your "mod". Let's say it's either for lazyness or to keep everything in the tp2 file.

    The 0x0a and 0x0d are characters used in text files to mark the end of a line. They differ on Linux, old Mac (new use the same as Linux) and Windows. This code is borrowed from Miloch and provides a way to create a variable that you can use in strings to insert end of lines, as for generating the lists, using the %lnl% variable. Don't ask me more, I just know it works. ;-)

    I used csv extension because the formatting of data I used separates data with a semi colon. It's just a text file but using the csv extension makes it easier to open with Excel/Open Office, that's all. The "magic" of creating the csv format comes from the way the code writes the data with the ; separator. Again this is borrowed from Miloch's code on G3.
    The file is created into the override folder as this is the only way to proceed with WeiDU (I tried other directories without success).

    Actually the whole mess (written for Baldur's Gate file format, especially for extracting from ITM and CRE) is in a single file. Don't forget your spelunking equipment before diving!
  • AbelAbel Member Posts: 785
    Thanks @Isaya! Now I've something to work on ;) !
  • WispWisp Member Posts: 1,102
    Isaya said:


    The 0x0a and 0x0d are characters used in text files to mark the end of a line. They differ on Linux, old Mac (new use the same as Linux) and Windows. This code is borrowed from Miloch and provides a way to create a variable that you can use in strings to insert end of lines, as for generating the lists, using the %lnl% variable. Don't ask me more, I just know it works. ;-)

    Just so you know, WeiDU has defined the variables %LNL%, %WNL% etc. since some time back, allowing you to forego defining them yourself.
Sign In or Register to comment.