initial item code in armorSelector help please

Freeform discussion about anything related to modding Transcendence.
Post Reply
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Trying to get an armorSelector dockscreen cursor to default to any damaged armor segment on an EI7000 auton.

From what I can work out "initialItem" is looking for a number corresponding to the armor installed location, in this case 0-11 to match the 12 armor segments on an EI700, or 'shields whcih places the cursor on the shields.

But I can't get the dockscreen to do anything but default to the topmost armor segment, location 0, or to the shields, 'shields.

I have tried various combinations using itmGetArmorInstalledLocation which should return a segment number.

As I understand it if the code doesn't find a damaged segment it should default to shields. That would work.

Possibly itmGetArmorInstalledLocation returning 1 for the shield slot isn't helping, or does the armor segment need to be linked to scrData 'armorSeg? If so how does 'armorSeg data differ from InstalledLocation (except in shields where it is 'shields instead of a number)?

Anyone made this work before or see where I'm going wrong? TIA.
Stupid code. Do what I want, not what I typed in!
User avatar
0xABCDEF
Militia Lieutenant
Militia Lieutenant
Posts: 124
Joined: Thu May 19, 2016 12:58 am
Location: Was destroyed by a Phobos-class dreadnought in the Eridani system

Whar does your code look like? The initialItem attribute accepts a string containing TLisp if the string begins with "=". I believe that the value of initialItem refers to the index of an item as it appears in the list of items to show (in case the list includes non-armor items) and not necessarily the installed location of an item since that is how it works in other item picker screens.
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

I didn't know about the 'shields option. But in a regular itemPicker, the initialItem code runs for every item in the list, until it returns non-nil for one of them, and that one is selected. Unfortunately, if none of them return non-nil, the last one is selected. So I think you want something like:

Code: Select all

initialItem="(or (itmMatches (scrGetItem gScreen) 'aD) (not (objGetItems gSource 'aID)))"
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

Edit: The post I was answering seems to have been deleted. It suggested that the value of an attribute needs to begin with an = to be evaluated as code. But that's true of some attributes, but not others. The initalItem in dsAutonBay doesn't start with =. And some attributes are not allowed to be code at all.
User avatar
0xABCDEF
Militia Lieutenant
Militia Lieutenant
Posts: 124
Joined: Thu May 19, 2016 12:58 am
Location: Was destroyed by a Phobos-class dreadnought in the Eridani system

Sorry, It turned out that I was looking at an incorrect part of the source code and had to delete the inaccurate references. Not many attributes accept code, but those that do usually begin code strings with "=", although that does not seem to be required anymore.
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Thank you both. The hardest part is working out what the game actually wants sometimes. This will help. I tried a couple of dozen different lots of code mainly using itmGetProperty 'damaged but couldn't make it happen so thought I would pick the brains of more experienced people. Thanks again.
Stupid code. Do what I want, not what I typed in!
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Many thanks. The code works almost perfectly. Unfortunately, on entering the screen for the first time, for some reason, even if there are damaged armor segments the cursor defaults to the top armor segment (location 0). On all screen entries after that it works fine and will default to the lowest number damaged armor segment (unless no damaged segments, then it stays at the top) even if you exit the screen and return later. It's just the very first time it stays at the top.

Howeve if you repair all the armor (the cursor then defaults to the top segment) and it then gets damaged again when you enter the screen after it gets damaged, once again, even though there is damaged armor the cursor defaults to the first segment again.

Any ideas about what is happening there? I always struggle writing initialItem code although I can usually reverse-engineer whats happening in working examples.
==============

dsRPGManageArmor, the only armorSelector screen in SOTP, always defaults to the first armor segment except when it is returning from one of the replace/install/upgrade screens.

Here's the initialItem code for dsRPGManageArmor:

Code: Select all

initialItem="=(block (
	(desiredSeg (scrGetData gScreen 'armorSeg))
	(seg
		(switch
			(not (scrGetItem gScreen))
				'shields

			(itmMatches (scrGetItem gScreen) 's)
				'shields

			(itmGetArmorInstalledLocation (scrGetItem gScreen))
			)
		)
	)

	(or (not desiredSeg) (eq seg desiredSeg))
	)"

The <OnPaneInit> code uses:

Code: Select all

(scrSetData gScreen 'armorSeg 'shields)

and

(scrSetData gScreen 'armorSeg (itmGetArmorInstalledLocation theItem))
to remember where the cursor was. But this is only after the screen has been entered already.

Here's part of the mod screen. It's a modified copy of dsRPGManageArmor.

Code: Select all

<DockScreen UNID="&dsD789FreighterShowArmor;"
		name=	"Armor and Shields"
		type=		"armorSelector"
		>

	<ListOptions
		dataFrom=	"shipObj"
		list=		"asI"
		initialItem="=(or (itmMatches (scrGetItem gScreen) 'aD) (not (objGetItems gSource 'aID)))"
		/>

	<Panes>
		<Default>
			<OnPaneInit>
				(block (
					(theItem (scrGetItem gScreen))
					(theShip shipObj)
					)
						;Set installed position of armor for armor repair in next dockscreen.
					(setq gArmorSegment (itmGetArmorInstalledLocation (scrGetItem gScreen)))

						;Hide shield enable/disable until needed.
					(scrShowAction gScreen 'actionShieldEnable Nil)
					(scrShowAction gScreen 'actionShieldDisable Nil)

					(switch
							;If no item is selected we assume that we have an empty shield generator slot.
						(not theItem)
							(block (
								(desc Nil)
								)

								(scrSetControlValue gScreen 'currentItem {
									title: "Shield Generator Slot"
									desc: "Your ship does not have a shield generator installed."
									})

									;Remember that we have the shield generator selected
							;	(scrSetData gScreen 'armorSeg 'shields)
								(scrShowAction gScreen 'actionRepairArmor Nil)
							)

							;If this is the shield generator.
						(eq (itmGetProperty theItem 'category) 'shields)
							(block Nil
								(setq desc (cat (itmGetName theItem 0x0021) " installed."))

									;Set the description
								(scrSetControlValue gScreen 'currentItem {
									source: theShip
									item: theItem
									})

									;Remember that we have the shield generator selected
							;	(scrSetData gScreen 'armorSeg 'shields)
								(scrShowAction gScreen 'actionRepairArmor Nil)

									;Enable/disable actions.
								(block Nil
									(switch
										(eq (objGetItemProperty shipObj theItem 'enabled) True)
											(block Nil
												(scrShowAction gScreen 'actionShieldEnable Nil)
												(scrShowAction gScreen 'actionShieldDisable True)
											)
										(eq (objGetItemProperty shipObj theItem 'enabled) Nil)
											(block Nil
												(scrShowAction gScreen 'actionShieldEnable True)
												(scrShowAction gScreen 'actionShieldDisable Nil)
											)
									)
								)
							)

							;Otherwise, we expect armor.
						(block Nil
								;Remember the armor segment so that we can come back to this same selection.
					;		(scrSetData gScreen 'armorSeg (itmGetArmorInstalledLocation theItem))

								;Set the description
							(scrSetControlValue gScreen 'currentItem {
								source: theShip
								item: theItem
								})

								;Repair armor.
							(setq knownItemsInHold (filter (objGetItems theShip "* +ArmorRepair; +Consumable") entry (itmIsKnown entry)))
							(switch
								;
								(and (neq (objGetArmorLevel theShip theItem) 100)
									(ls (count knownItemsInHold) 1)
								)
									(block Nil
										(scrEnableAction gScreen 'actionRepairArmor Nil)
										(scrSetActionDesc gScreen 'actionRepairArmor "Armor damaged: No repair items in hold.")
									)

									;If the armor segment is damaged, enable the Repair Armor action.
								(neq (objGetArmorLevel theShip theItem) 100)
									(scrSetActionDesc gScreen 'actionRepairArmor "Select to fix armor")

									;Else disable it.
								(block Nil
									(scrEnableAction gScreen 'actionRepairArmor Nil)
									(scrSetActionDesc gScreen 'actionRepairArmor "No armor damage")
								)
							)
						)
					)
				)
			</OnPaneInit>

			<Controls>
				<ItemDisplay id="currentItem"/>
			</Controls>

			<Actions>
				<Action id="actionRepairArmor">
					(block Nil
							;need to carry over armor info to next screen with criteria.
						(scrShowScreen gScreen &dsD789FreighterShipRepairArmor; {
							criteria: "gArmorSegment"
							})
						(typSetData &dsD789FreighterShipRepairArmor; 'screenEntries Nil)
					)
				</Action>
For information, there needs to be a second = in the initial item code here. Without it, ie initialItem="(or, the cursor always defaults to the top armor segment regardless of damaged segments or number of screen entries.
Stupid code. Do what I want, not what I typed in!
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

Oh, that might be checking the armor's 'damaged property, not whether its hp is less than max. But in that case, I'd be surprised it would work at all. Try this:

Code: Select all

"=(or (gr (objGetArmorDamage gSource (scrGetItem gScreen)) 0)
	(and
		(eq (itmGetArmorInstalledLocation (scrGetItem gScreen)) 0)
		(not (filter (objGetItems gSource 'aI) theArmor (gr (objGetArmorDamage gSource theArmor) 0)))
	)
)"
relanat wrote:
Tue Aug 01, 2017 6:55 am
For information, there needs to be a second = in the initial item code here. Without it, ie initialItem="(or, the cursor always defaults to the top armor segment regardless of damaged segments or number of screen entries.
That's interesting. As I said, the one in dsAutonBay works without the =. But it looks like all the others have it, so maybe it's one of those things that may work, but aren't guaranteed to, unless you use the exact right formatting?
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Excellent. That code did it. Now, no matter how I try to fool it, the first damaged segment is selected or the first segment if no armor is damaged. Thank you.
Stupid code. Do what I want, not what I typed in!
Post Reply