ObjAddItem, ObjGetItems, ShpInstallArmor

Freeform discussion about anything related to modding Transcendence.
Post Reply
robotarozum
Miner
Miner
Posts: 35
Joined: Sat Nov 30, 2013 10:05 pm

So I'm trying to install certain armors without selecting them from dockscreens. I thought what I would do is...

Code: Select all

(objadditem gplayership (itmcreate 0xD518FF28 4) 4)
(shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28^U") 0) 0)
(shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28^U") 0) 1)
(shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28^U") 0) 2)
(shpinstallarmor gplayership (@ (objgetitems gplayership "unid:0xD518FF28^U") 0) 3)
It turns out this crashes the game, which is obviously a bit of a concern, so I broke it down piece by piece in the debug console.

- The first line works fine, four segments of the armor are put into my cargo. (And no other armor is in there.)

- The (objgetitems) is where things get weird. If I do it with just the unid, I get three returns: one classified as uninstalled, two classified as installed. I have no idea what that means. If I then do unid^a I get an empty set(!). Going through all the objgetitems criteria the first unid^I is classified as a miscellaneous device (user created), the second as a weapon (user created), the third as fuel(!!!). And not fuel I made up, plain old helium fuel rods. This explains why the game crashed, but what the heck is that unid criteria doing?

Does anyone have experience using ObjGetItems in this way? Or another way of getting at this?
robotarozum
Miner
Miner
Posts: 35
Joined: Sat Nov 30, 2013 10:05 pm

Ok so I looked shpinstallarmor on xelerus and just used...

(shpInstallArmor gPlayership (itmCreate 0xD518FF28 1) 0)

...and it worked a treat, but I'm still really confused by the objgetitems part.
george moromisato
Developer
Developer
Posts: 2997
Joined: Thu Jul 24, 2003 9:53 pm
Contact:

The most important thing to remember about items (armor, devices, etc.) is that you can only manipulate them by value not by reference. What does that means? Here is a quick tutorial:

When you call a function like:

(objAddItem gPlayerShip (itmcreate 0xD518FF28 4) 4)

you add a single item record to the player ship. The player ship's inventory will look like this:

Player Ship Inventory:
[UNID: 0xD518FF28 count:4 flags:none]

First, notice that even though you've created 4 armor segments there is only a single record. The record itself has a count of 4, which is how we keep track. This is done for efficiency. Otherwise, if you pick up 1000 rounds of ammo we would have 1000 records, which is too expensive.

Next, notice that there is no ID field! The fact that there is no ID field means that you can't refer to the record by ID. So how do you refer to the armor segments? How do you, for example, install them?

You need to install them by describing exactly the items that you want to install. You have to refer to them by value. Effectively, you need to do something like this:

(shpInstallArmor gPlayerShip "the armor that looks like: [UNID: 0xD518FF28 count:4 flags:none]")

Of course, the above won't work, but the function itmCreate essentially is a way of creating records of that form. So the following works:

(shpInstallArmor gPlayerShip (itmCreate 0xD518FF28 1) 0)

Indeed, the output of itmCreate is a record structure. Under the covers:

(itmCreate 0xD518FF28 1) -> [UNID: 0xD518FF28 count:1 flags:none]

After you do this, you will end up with inventory that looks like this:

Player Ship Inventory:
[UNID: 0xD518FF28 count:3 flags:none]
[UNID: 0xD518FF28 count:1 flags:installed installedAt:0]

Notice that the act of installing armor changes the record! Because the record has changed, you can't refer to it by the original name. For example, suppose I wanted to enhance the armor I just installed. I might naively try this:

(shpEnhanceItem gPlayerShip (itmCreate 0xD518FF28 1))

Which armor segment would get enhanced? Because the installed armor has changed (because it is installed), I can't use the same code to refer to it anymore. I need to do something like:

(shpEnhanceItem gPlayerShip "the armor that looks like: [UNID: 0xD518FF28 count:1 flags:installed installedAt:0]")

Unfortunately, itmCreate can't output that kind of record (it doesn't know how to set the installed flag), so you can't use it. Instead, you need to find the item on the player ship and use that. objGetItems returns a list of item records that match a specific criteria.

(objGetItems gPlayerShip "unid:0xD518FF28;") ->
[UNID: 0xD518FF28 count:3 flags:none]
[UNID: 0xD518FF28 count:1 flags:installed installedAt:0]

Since both records match the UNID, objGetItems returns both the installed and uninstalled. If I only want the installed item, I need the 'I' flag:

(objGetItems gPlayerShip "unid:0xD518FF28; I") ->
[UNID: 0xD518FF28 count:1 flags:installed installedAt:0]

Of course, the result is still a list, so I would need to use the '@' syntax to get the first element of the list:

(shpEnhanceItem gPlayerShip (@ (objGetItems gPlayerShip "unid:0xD518FF28; I") 0))

objGetItems is a way to find the item record that you want to refer to. So with that (long) tutorial out of the way, we can talk about your code.

In your first example, there is a small bug in the criteria for objGetItems. Your code should be something like:

Code: Select all

(objadditem gplayership (itmcreate 0xD518FF28 4) 4)
(shpinstallarmor gplayership (@ (objgetitems gplayership "* +unid:0xD518FF28; U") 0) 0)
(shpinstallarmor gplayership (@ (objgetitems gplayership "* +unid:0xD518FF28; U") 0) 1)
(shpinstallarmor gplayership (@ (objgetitems gplayership "* +unid:0xD518FF28; U") 0) 2)
(shpinstallarmor gplayership (@ (objgetitems gplayership "* +unid:0xD518FF28; U") 0) 3)
Notice that the "unid:..." term ends in a semi-colon. And the "U" term doesn't need a "^".

But your second example works just as well because you've described the item perfectly. The second method would get into problems if the item were enhanced, damaged, installed, or had data associated with it. In those cases, you need to use the objGetItems syntax.

Also, many functions return the item record after modification. For example, objSetItemData returns the newly modified item record and you can use the result to refer to the item in subsequent calls.

[Edit: Fixed the syntax on objGetItems.]
robotarozum
Miner
Miner
Posts: 35
Joined: Sat Nov 30, 2013 10:05 pm

Ah, that all makes sense. Thanks so much! :)
User avatar
digdug
Fleet Admiral
Fleet Admiral
Posts: 2620
Joined: Mon Oct 29, 2007 9:23 pm
Location: Decoding hieroglyphics on Tan-Ru-Dorem

ohh, nice !
wiki wiki :)

BTW, to install/replace shield/weapon/armors we devised a number of functions to make our life easier. In particular I think Atarlost has the latest versions.
RPC
Fleet Admiral
Fleet Admiral
Posts: 2876
Joined: Thu Feb 03, 2011 5:21 am
Location: Hmm... I'm confused. Anybody have a starmap to the Core?

Tutorial List on the Wiki and Installing Mods
Get on Discord for mod help and general chat
Image
Image
Der Tod ist der zeitlose Frieden und das leben ist der Krieg
Wir müssen wissen — wir werden wissen!
I don't want any sort of copyright on my Transcendence mods. Feel free to take/modify whatever you want.
robotarozum
Miner
Miner
Posts: 35
Joined: Sat Nov 30, 2013 10:05 pm

Okay I have tried it some more and the "unid" criterion just isn't working at all, I think the client I have cannot interpret between it and the others. When I do (objgetitems gplayership X) I get...

"unid:0xd518ff40;"
devices and fuel
"unid:0xd518FF40;"
devices
"unid:0xD518FF40;"
nothing (nothing is Damaged)
"UNID:0xd518ff40;"
nothing (both Uninstalled and Installed obviously must return nothing)

This makes sense if we assume the code treats unid as merely a collection of the letters u n i and d and same for UNID. I am running version 1.2. Has anyone successfully used this criterion with objgetitems?
george moromisato
Developer
Developer
Posts: 2997
Joined: Thu Jul 24, 2003 9:53 pm
Contact:

robotarozum wrote:Okay I have tried it some more and the "unid" criterion just isn't working at all, I think the client I have cannot interpret between it and the others. When I do (objgetitems gplayership X) I get...

"unid:0xd518ff40;"
devices and fuel
"unid:0xd518FF40;"
devices
"unid:0xD518FF40;"
nothing (nothing is Damaged)
"UNID:0xd518ff40;"
nothing (both Uninstalled and Installed obviously must return nothing)

This makes sense if we assume the code treats unid as merely a collection of the letters u n i and d and same for UNID. I am running version 1.2. Has anyone successfully used this criterion with objgetitems?
Apologies! I got the syntax wrong. Try:

"* +unid:0xD518FF40;"

The "+" is necessary to tell the code that you want UNIDs that match. The "*" at the beginning is necessary to include all item types (otherwise you get nothing).
robotarozum
Miner
Miner
Posts: 35
Joined: Sat Nov 30, 2013 10:05 pm

Aha! Yes, that is working just fine. Thanks again! :)
Post Reply