Initialize element

Freeform discussion about anything related to modding Transcendence.
Post Reply
User avatar
ptbptb
Militia Lieutenant
Militia Lieutenant
Posts: 143
Joined: Mon May 10, 2010 7:34 pm

Is it possible to use the Initialize element in DockScreen to hide inappropriate items in a list?

For example, when you go to a tinker station and ask for a 'custom job' you could remove all the items that cannot be made into anything useful.
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

That can be done using the <ListOptions> element of itemPicker screens. There should be some examples of that in vanilla code. I think the armor repair screens use them to limit the items to only damaged ones. If not I think I have used it in godmod, via DSF. If you have any questions I would be happy to help, but after dinner :)
User avatar
ptbptb
Militia Lieutenant
Militia Lieutenant
Posts: 143
Joined: Mon May 10, 2010 7:34 pm

alterecco wrote:That can be done using the <ListOptions> element of itemPicker screens.
Yes, but the List attribute where you set criteria does not allow you to include specific items - only select by item type, modifier, etc.
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

You do not control this in the list attribute, but inside the body of the element. Have a look at the dsExchangeBuy screen from Transcendence.xml line 2992

Basically what goes on is: You can use scrSetListFilter inside the the ListOptions body. It takes two arguments; the screen (always gScreen) and then a mixed argument (it can be a boolean, a criteria string and more). What you can do is pass it a function that takes one argument. This function will be called once for every item in the initial list (as controlled by the `list' attribute) and if the function returns true the item is included, else it is excluded.

Hope that makes sense
User avatar
ptbptb
Militia Lieutenant
Militia Lieutenant
Posts: 143
Joined: Mon May 10, 2010 7:34 pm

alterecco wrote:Hope that makes sense
Well, I thought it did, but I still haven't quite got things working.

The following is what I tried sticking into ListOptions, but it doesn't display any items even when they should match (e.g. when I have Titanium ore in the cargo hold)

Any ideas?

Code: Select all

            <ListOptions
               dataFrom=   "player"
               list=      "*U"
               >
              (block (thisItem itemUNID)
                 (setq thisItem (scrGetItem gScreen))
                 (setq itemUNID (itmGetUNID thisItem))
                 (setq gMargin (lambda Nil
                    (switch 
                       (eq itemUNID &itTitaniumOre;)
                          True
                       (eq itemUNID &itHeavyWater;)
                          True
                       (eq itemUNID &itSiliconArmorPatch;)
                          True
                       (eq itemUNID &itCarbonSpool;)
                          True
                       (eq itemUNID &itPlasteelOre;)
                          True
                       (eq itemUNID &itHyperfiberRoll;)
                          True
                       (eq itemUNID &itDuralloyOre;)
                         True
                       (eq itemUNID &itReactiveArmor;)
                          True
                       (eq itemUNID &itCeralloyOre;)
                          True
                       (eq itemUNID &itOrthoSteelOre;)
                          True
                       (eq itemUNID &itClass1Deflector;)
                          True
                       (eq itemUNID &itClass2Deflector;)
                          True
                       (eq itemUNID &itSuperconductingCoil;)
                          True
                       (eq itemUNID &itLaserCannon;)
                          True
                       (eq itemUNID &itPartisanCannon;)
                          True
                       (eq itemUNID &itTurbolaserCannon;)
                          True
                       (eq itemUNID &itRadioactiveWaste;)
                          True
                       (eq itemUNID &itFusionTrigger;)
                          True
                       (eq itemUNID &itRepairingNanos;)
                          True
                       NIl
                    )
                 ))
                 (scrSetListFilter gScreen gMargin)
              )
            </ListOptions>
Also tried this alternative code.

Code: Select all

(block (thisItem itemUNID)
    (setq thisItem (scrGetItem gScreen))
    (setq itemUNID (itmGetUNID thisItem))
    (setq gMargin (lambda Nil
        (block (testWork foundPartial)
            ; Loop through our table looking to see if there
            ; is something that we can convert
 
            (setq foundPartial Nil)
            (enum (objGetStaticData gSource 'CustomWork) testWork
                (block Nil
                    (if (eq (item testWork 0) (itmGetUNID gItem))
                        (setq foundPartial True)
                     )
                 ) ; close block
             )
         )
         foundPartial
     ))
    (scrSetListFilter gScreen gMargin)
 ) ; close block
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

ptbptb wrote:Well, I thought it did, but I still haven't quite got things working.
You have to pass it a lambda, not a block. Like so:

Code: Select all

<ListOptions
    dataFrom=   "player"
    list=      "*U"
    >
    (scrSetListFilter gScreen (lambda (itm)
        (block (whatever)
            (if (something)
                ;; then True
                True
                ;; else false
                Nil
            )
        )
    ))
</ListOption>
This lambda you can define in the global scope, or inline like above. This function is then called once per item, with the item as the sole argument, and based on the return value of that function the item is included or not
User avatar
ptbptb
Militia Lieutenant
Militia Lieutenant
Posts: 143
Joined: Mon May 10, 2010 7:34 pm

Sorry to be a pest, but still not there (although hopefully closer). Where does 'itm' get defined? Is it automatically defined inside the ListOption element or something?

Anyway, this is what I've got now.

Code: Select all

(scrSetListFilter gScreen (lambda (itm) 
	 (block (testWork foundPartial)
		 (setq thisItem (scrGetItem gScreen))
		 (setq itemUNID (itmGetUNID thisItem))
		; Loop through our table looking to see if there
		; is something that we can convert
		 (setq foundPartial Nil)
		 (enum (objGetStaticData gSource 'CustomWork) testWork
			 (if (eq (item testWork 0) (itmGetUNID gItem))
			 	 (setq foundPartial True)
			)
		)
		foundPartial
	)
))
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

After reading your post again I realised I perhaps should have used your example for explaining, and actually answered your question :) I will leave my original post below intact

`itm' is defined in the lambda as the name of the arguement passed in. When the list is filtered the engine passes each item to this lambda, so whichever lambda you use for the filter, must take at least one argument.

This is how I would write your function

Code: Select all

(scrSetListFilter gScreen (lambda (itm)
  (block (found)
    (enumWhile (objGetStaticData gSource 'CustomWork) (not found) work
      (if (eq (item work 0) (itmGetUNID itm)) (setq found True))
    )
    found
  )
)) 

====================================================
Original Post


Hmm, ok... Let me see how I can explain this properly.

If the argument to scrSetListFilter is a lambda (a function, but let us just call them lambdas), then that lambda will be called once for each item in the list, with the item as it's argument

Let us take an example. In this dockscreen I only want uninstalled enhanced weapons to show up. I will use the built in (itmIsEnhanced item) -> Nil or mods lambda for testing this:

Code: Select all

<ListOptions
  dataFrom="player"
  list="*wU"
  >
  (scrSetListFilter gScreen itmIsEnhanced)
</ListOptions>
Here, the `list' attribute limits the list to uninstalled weapons, and since I set the ListFilter (by using scrSetListFilter) to a lambda, this lambda will be called over and over again for each uninstalled weapon, and only return Non-Nil on weapons that are enhanced. Thus, the final item list will only contain enhanced uninstalled weapons.

Let us try another example, where we build the lambda ourselves. For example if I want to show all items on a station produced by Makayev or Bushido. I will spell the code out a bit more than I would normally.

Code: Select all

;; first we define the lambda we will use for the list filter.
;; It takes one argument: the current item being queried for
;; inclusion in the final list
(setq itmIsMakayevOrBushido (lambda (itm)
  (block (affirmative)
    (if (or (itmHasAttribute itm "Makayev")
             (itmHasAttribute itm "Bushido")
        )
        ;; item has one of the two modifiers
        (setq affirmative True)
        ;; item has none of the modifiers
        (setq affirmative Nil)
    )
  )
))

;; now we use this function inside of the ListOptions tag...
;; so imagine the following is inside a DockScreen somewhere

<ListOptions
  dataFrom="station"
  list="*"
  >
  (scrSetListFilter gScreen itmIsMakayevOrBushido)
</ListOptions>

Now our homemade lambda will do all the hard work of weeding out unwanted items from the final list. The version I would actually use looks like this

Code: Select all

<ListOptions
  dataFrom="station"
  list="*"
  >
  (scrSetListFilter gScreen (lambda (itm) (or (itmHasAttribute itm "Makayev") (itmHasAttribute itm "Bushido"))))
</ListOptions>
I hope that it makes sense now :)
User avatar
ptbptb
Militia Lieutenant
Militia Lieutenant
Posts: 143
Joined: Mon May 10, 2010 7:34 pm

The 'lambda' thing is one of the points I struggle most with in tscript. I shall probably come back to read this several times in the future. :oops:

Anyway, thanks very much on behalf of myself an any other confused would-be modder who finds this thread.
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

A lambda is just a function definition. It wraps a piece of code for later execution:

Code: Select all

(dbgOutput "I will run immediately")
;; vs
(setq runIt (lambda Nil (dbgOutput "I will not run until I am called")))

;; to call the above lambda, use parentheses
(runIt)
You can pass arguments to lambdas, just like other languages allow you to.

Code: Select all


;; let us define a lambda that takes one argument
(setq myLambda (lambda (arg)
  (dbgOutput "I was passed the argument: " arg)
))

;; call the lambda with one argument
(myLambda "I am the value being passed")
;; call it again, just for fun
(myLambda (cat 42 "The result of the cat will be the value passed"))
Post Reply