scrAddAction Examples

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

scrAddAction is a great function. It let's you add an action to the right-hand side of a dockscreen. Rather than taking the entire .xml file which contains the dockscreen and overwriting it, you can just add one (or more) action. Much easier and also means multiple mods can be run without too much interference.

To get the most out of this topic get the scrAddActionMod from xelerus.de http://xelerus.de/index.php?s=mod&id=1565&d=1 and a text editor like Notepad++ or Sublime Text. Also a decompiled version of Stars Of The Pilgrim which is a folder called 'Transcendence_Source' (search the forum/Multiverse for info on how to do this with Transdata).

TranscendentGeek has also done a great forum tutorial on scrAddAction in Modding Reference, "Using ScrAddAction To Change Dockscreens Without Overwrting" https://forums.kronosaur.com/viewtopic.php?f=8&t=5092.

This is the syntax of scrAddAction.

(scrAddAction screen actionID pos label [key] [special] code)

Doesn't mean much just now so let's work through it.

scrAddAction is the function. When the game sees this it will put another action in the right-hand side of a dockscreen. There are quite a few uses of it in 'Transcendence_Source" but, personally, I don't understand any of them because they are too complex. So I've written a few mods to make it easier. Most are based on the 'Ship's Interior' dockscreen which you see when you press 'S' when playing the game.

screen is usually gScreen. It's shorthand for the game for the screen we are working with at the moment.

actionID starts with ' and has a text name after it. I don't understand it but something must be here and it needs to start with '. It must also be different from all other uses in scrAddAction in the same dockscreen as we will see later. The xelerus function description says "string to identify action with later" which is of no help either :lol:.

pos This is the position in the dockscreen list where the action will appear. The first value for this is 0. Using 0 will place the action at the top of the list. 1 will put it second on the list. And so on. Weird but you get used to it. A special case (and very handy) is -1 which will put the action at the bottom of the list.

label is the text/wording that will appear in the dockscreen action list. Common examples are 'Done' and 'Continue'. Note that text must be in this format; "Added Action".

[key] is one of the letters in the 'label' (see above) that will cause the action you are adding to happen. Using 'Done' from above, the key would be 'D'. 'B' is used quite a bit in the example mods as we will see shortly. Once again the key you want to use must be in this format; "A" (if using 'Added Action' as the label, see above).

[special] is another that I don't understand. The difference here is that you don't have to put anything in. The [] brackets mean this is optional. The xelerus description is "list or token describing special functionality". Whatever! EDIT: this is used to add keyboard shortcuts to actions. The shortcuts that I know of are default, cancel, prevKey and nextKey.
'default' means pressing 'Enter' on the keyboard will also cause this action to happen.
'cancel' means pressing 'Esc' will also cause this action to happen.
'prevKey' has two keys. The 'Up Arrow' and 'Left Arrow' will cause this action to happen.
And 'nextKey' is the 'Down Arrow' and 'Right Arrow' also causing this action to happen.
Note that by convention, 'cancel' is usually used on 'Done', 'Undock' or 'Back' in most screens. This helps because hitting 'Esc' repeatedly will let you exit back through multiple dockscreens quickly.
If there is only one action (other than 'Done') include 'default' on that action. This helps because you can easily progress through dockscreens by using 'Enter'. The Benedict mission dialogue is a great example of this.

code The best bit. Here we tell the game what we want to happen or where we want the game to go to make things happen. I have had trouble getting complex code to run in scrAddAction so I usually send the game somewhere else to use complex code (realistically it could also be my lack of coding knowledge). But a couple of code lines to do something simple or redirect the game usually works OK.

To the example mods .The first one is scrAddActionMod ShipsInterior

Here's the important code.

Code: Select all

<OnGlobalPaneInit>
	(if (and (eq aScreenUNID &dsShipInterior;) (eq aPane "Default"))
		(scrAddAction
			gScreen
			'addBoom
			-1
			"Boom"
			"B"
			(block Nil
				(plyMessage gPlayer "Boom")
				(objDestroy gPlayership gPlayership)
			)
		)
	);if
</OnGloablPaneInit>
We'll look at this as two parts. The 'if' line of code and the 'scrAddAction' block of code.

The if line tells the game when to run the scrAddAction code. All of this code is inside an <OnGlobalPaneInit> block. This is a function set up so that every time the game goes to a pane in any dockscreen it runs any code which is inside a <OnGlobalPaneInit> block. Without the 'if' code the "Boom" option would come up everywhere in every pane, not just in the Ship's Interior dockscreen.

Looking again at the 'if' line of code we see;

Code: Select all

(if (and (eq aScreenUNID &dsShipInterior;) (eq aPane "Default"))
which translates as 'if aScreenUNID is '&dsShipInterior;' and aPane is 'default' then run the scrAddAction code block. If not ignore it'.
As explanation we quote the xelerus function description:
aScreenUNID is the UNID of the screen being shown
aPane is the pane being shown

Here's the start of the code from the 'Ship's Interior' dockscreen which comes up when you press 'S' playing the game. There's more but this is all we need to see.

Code: Select all

<DockScreen UNID="&dsShipInterior;"
	name=	"Ship's Interior"
	>
	<Panes>
		<Default
			desc=	"You are inside the main compartment of your ship. etc">

This shows us that if we are in the 'Ship's Interior' dockscreen then aScreenUNID is indeed '&dsShipInterior;'.
The <Default after <Panes> is the name of the pane we are in as well. So aPane is also 'Default' when we are in the 'Ship's Interior' dockscreen.
Because these both match, the scrAddAction code will run and Boom will appear at the bottom of the list on the right-hand side of the dockscreen.

Now the 'scrAddAction code block.

Code: Select all

		(scrAddAction
			gScreen
			'addBoom
			-1
			"Boom"
			"B"
			(block Nil
				(plyMessage gPlayer "Boom")
				(objDestroy gPlayership gPlayership)
			);block
		)
Although this is only one line of code I've placed it vertically to help explain it.
screen is gScreen. It normally will be unless you are doing complex code.
'addBoom is the actionID. Again I don't know how to use it but something must be there.
-1 is the pos. This is the position of the action in the list. -1 places the action at the bottom of the list.
"Boom" is the label of the action that appears in the list. In simple examples it is text and must be enclosed in ".
"B" is the key that will be highlighted in "Boom" and will make the code run. This also must be inside ".
Note that there is no [special] entry here. It's optional, 'cancel' is already used by 'Back To Cockpit' and with 4 other actions here it doesn't make much sense to put a shortcut on this action.
Lastly the code. This is what happens when you press "B". In this case you get a message on the screen that says "Boom" and your ship blows up. Not very useful but I've been dying to use that line of code since AP posted it some time ago :lol:.

So running the mod will give you a list of actions in the Ship's Interior dockscreen that will read:
Ship Configuration
Missions
View Cargo Hold
Refuel Reactor
Back To Cockpit
Boom

But if you press 'B' you don't die. Instead of 'Boom' you return to the cockpit. This is because there are two options on the list that have 'B' as their key. 'Back To Cockpit' and 'Boom'. The game will run the first one it comes to. Note that clicking on 'Boom" will destroy your ship. The action works, the game just always uses the first B option.
To fix this we can either move 'Boom' up the list by changing the pos from -1 to another value (but this still leaves two B options in the list) or we can change the key to 'o' in the scrAddAction code which would mean pressing 'o' would make the 'Boom' code run. A neater solution might be to change the label to 'Goodbye' and the key to 'G' because there are no other actions using G.


The second mod is called ScrAddAction Mod ShipsInterior To Dockscreen.

Here's some of the important code

Code: Select all

(if (and (eq aScreenUNID &dsShipInterior;) (eq aPane "Default"))
	(scrAddAction
		gScreen
		'addBoomOption
		4
		"Boom Options"
		"B"
		(scrShowScreen gScreen "&dsD789BoomDockscreen;")
	)
);if
It is very similar to the previous mod. Changes are:
the actionID is 'addBoomOption' instead of 'addBoom. If you have 'addBoom for both and are running both mods then you will get an error.
pos is now 4, not -1. This places it fifth in the list and just above 'Back To Cockpit'. So pressing 'B' in this mod makes you go to the 'Boom' dockscreen instead of returning to the cockpit because the game comes to this 'B' option first.
label is now "Boom Options". You can use "Boom" again, the game will allow that, but it becomes very confusing to use.
Lastly the code is different. Instead of going Boom we use the function scrShowScreen to go to a dockscreen called 'dsD789BoomDockscreen'. This is also in this mod and will give us the option of going Boom either now or later.

Note the last line of code above ");if". This bracket matches the 'if' at the beginning of the code This is a trick I picked up from marsrocks' code. It can be very handy to keep track of where your brackets are. Everything after ; is ignored by the game. See the comments in the mod for examples. So you could also use ");scrAddAction" as the second to last line of code to help keep track. It's not really necessary here with such a small amount of code but as your mods grow it may come in handy.

In the mod is this dockscreen code. Note the use of D789 in the DockScreen UNID=. this is called UNID mangling and eliminates the chance of another mod having the same UNID name. D789 is a prefix I registered on the forum and is used in all my UNIDs (or will be when I update them).

Code: Select all

<DockScreen UNID= "&dsD789BoomDockscreen;"
		name=		"Boom Dockscreen"
		nestedScreen=	"true"
		>

	<Panes>
		<Default>
			<OnPaneInit>
				(scrSetDesc gScreen "Choose the Boom option you would like.")
			</OnPaneInit>

			<Actions>
				<Action id="actionNow" default="1">
					(block Nil
						(plyMessage gPlayer "Boom")
						(objDestroy gPlayership gPlayership)
					);block
				</Action>

				<Action id= "actionLater" cancel="1">
					(scrExitScreen gScreen)
				</Action>
			</Actions>
		</Default>
	</Panes>
</Dockscreen>
On pressing 'B' in the Ship's Interior dockscreen we go to this dockscreen. Here we have the option to 'Go Boom Now' or 'Go Boom Later'.
It's a bit more complex than the previous mod but the advantage of being able to do this comes from there only being enough room in a dockscreen for 8 options. Five are already used in the Ship's Interior dockscreen. So if you want to add more than a couple of additional actions to that screen you might run out of room, especially if you run other mods that also use the 'Ship's Interior' dockscreen.

Here we use the key 'N' to make us go Boom. The 'default="1"' code means that pressing 'Enter' on the keyboard will also make the action happen.

The other option is 'L' for Later. This gives us the option to not be destroyed, instead returning us to the previous screen. The 'cancel="1" code means pressing 'Esc' on the keyboard will also run the scrExitScreen code which takes us back to the Ship's Interior dockscreen. Putting 'cancel="1"' somewhere in all your dockscreens is a good idea as it gives you a way out when writing code. Otherwise you can end up stuck in a screen with no way out except Ctrl-Alt-Delete and restart. (damhik :)). Note the third line of code as well, 'nestedScreen="true"'. Using this means that the (scrExitScreen gScreen) line of code takes us back to the original dockscreen, in this case 'Ship's Interior'. Without the nestedScreen= you will be returned straight to the cockpit.
Last edited by relanat on Thu Jun 22, 2017 5:49 pm, edited 5 times in total.
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

The third mod is very similar to the previous one and is called scrAddActionMod ShipsInterior to NotRealShip.
It differs in creating a 'not real' ship to run the code rather than going to another dockscreen. I've used this before to run <Events> code because I couldn't make them run inside the scrAddAction code block. It may not be necessary but is included here because it works.

The code changes are pos is 0 which puts the option 'N'otReal Boom at the top of the list. The actionID is 'addVirtualBoom and the code has changed.
The relevant code is

Code: Select all

(if (and (eq aScreenUNID &dsShipInterior;) (eq aPane "Default"))
	(scrAddAction
		gScreen
		'addVirtualBoom
		0
		"NotReal Boom"
		"N"
		(block Nil
			(sysCreateShip &scD789NotRealBoomCodeShip; Nil &svPlayer;)
			(scrExitScreen gScreen 'forceUndock)
		)
	)
);if
This code creates a ship (a ShipClass scD789NotRealBoomCodeShip) which is described next. The (scrExitScreen gSreen gScreen 'forceUndock) code always returns us to the cockpit without going back through any previous dockscreens.

Here's the ship code.

Code: Select all

<ShipClass UNID="&scD789NotRealBoomCodeShip;"
			>

	<Image	imageID="&rsItems1;" imageX="0" imageY="0" imageWidth="1" imageHeight="1" imageFrameCount="0" imageTicksPerFrame="0"/>

	<Events>
		<OnCreate>
			(block Nil
				(plyMessage gPlayer "Boom")
				(objDestroy gPlayership gPlayership)
			);block
		</OnCreate>
	</Events>
</ShipClass>
All this does is create a ship which is one pixel in size. It doesn't have any weapons or a real image or armor. But inside the <Events> block there is an <OnCreate> block. So when scrAddAction creates the ship when you press 'N' this code will run because <OnCreate> code runs, you guessed it, when the ship is created. This is cheap and nasty code but it worked. It's possible you could just use a virtual ship by having 'virtual="true"' just below the ShipClass UNID= and getting rid of the image line of code, but I haven't tried that.


Lastly we have scrAddActionMod Corporate.

Code: Select all

	(if (and (eq aScreen "0x0015200C/Main") (eq aPane "Default"))
		(scrAddAction
			gScreen
			'addBoom
			-1
			"Boom"
			"B"
			(block Nil
				(plyMessage gPlayer "Boom")
				(objDestroy gPlayership gPlayership)
			)
		)
	)
This is identical to the first mod, scrAddAction Mod ShipsInterior, but comes up when you dock at a Corporate Enclave, not in the Ship's Interior dockscreen. This is included because it uses a different format to select which dockscreen it will appear in. Note that the actionID here can be 'addBoom again as in the first mod. This must be because we are in a different dockscreen to Ship's Interior.

Some of the Corporate Enclave code from CorporateHierarchy.xml in Transcendence_Source. Line 1030.

Code: Select all

<StationType UNID="&stCorporateEnclave;"
		name=				"Corporate enclave"
		sovereign=			"&svCorporate;"
		inherit=			"&baCorporateStation;"

		dockScreen=			"Main"
and from Line 1073

Code: Select all

	<DockScreens>
		<Main>
			<Panes>
				<Default
						desc=	"You are in the docking level of a Corporate Enclave, etc.">
Note here that the dockscreen for the Corporate Enclave doesn't have a 'DockScreen UNID=' line of code, only a <DockScreens> block. It doesn't need a UNID because it is defined inside the StationType UNID of the Corporate Enclave.
Because of this the 'if' line of code has to be in a slightly different format.

Code: Select all

	(if (and (eq aScreen "0x0015200C/Main") (eq aPane "Default"))
From the xelerus function explanation: aScreen is the screen name. This has to be in the format "hexUNID/name". The hex UNID is the hex number equivalent of stCorporateEnclave, 'the StationType UNID=' (see the first line of Corp Enclave code above). To find this we go to HumanSpaceVol1.xml in Transcendence_Source which has a list of the game UNIDs and search for enclave. On Line 903 we have

Code: Select all

<!ENTITY stCorporateEnclave	"0x0015200C">
So the hex number we need is '0x0015200C'.
The name of the dockscreen is <Main> as seen in the second lot of Corp Enclave code above (there is also another dockscreen below <Main> called <CorporateLevel> but the scrAddAction code won't show there because the dockscreen name isn't Main). In the above code we also see that the Pane name is '<Default'. So aScreen is "0x0015200C/Main" and aPane is "Default" so the scrAddAction code will run.


As you can see in the following image, if all the mods are selected it fills the dockscreen list with no room for any more. The Corporate Enclaves will also have a Boom option. And pressing 'B' will select the 'Boom Options' action because it is first on the list. The other 'B' actions work but you need to click them with the mouse to get them to work.


And finally, an example which shows that we can set the scrAddAction code to run in multiple dockscreens.
This line of code, from Stargate Gate N Go in the Stargate Docking mod, will cause the code to run in any of the three stargates that are in the game.

Code: Select all

(if 
	 (or (eq aScreenUNID &stStargate;)(eq aScreenUNID &stMajellenStargate;)(eq aScreenUNID &stUnchartedMajellenStargate;)) 
The 'or' function means that if aScreenUNID is any of the three listed above then scrAddAction will run.

Note that you don't need to check aPane here because all three stargates only have one pane. (See Stargates.xml in Transcendence_Source for the code). The Ship's Interior dockscreen also only has one pane but it was better for teaching purposes if we checked for aPane there as well.


I hope that helps. If anything is unclear or wrong let me know, please. This is based on the 1.8a1 version of Stars Of The Pilgrim.
EDIT: These are only simple examples to get you modding quicker. You can mess about with the different parts of the function and do really complex stuff but you'll need the IRC people to help you!

For more info on dockscreens see the following two topics, Be aware that some of the info is dated, especially in the first topic,
Dockscreens! https://forums.kronosaur.com/viewtopic.php?f=8&t=1833
Upcoming dock screen changes https://forums.kronosaur.com/viewtopic.php?f=8&t=3537
Attachments
all boom mods (900 x 540).jpg
all boom mods (900 x 540).jpg (77.13 KiB) Viewed 1831 times
Stupid code. Do what I want, not what I typed in!
Post Reply