[TUTORIAL] Creating menus + two library scripts

The place to discuss scripting and game modifications for X³: Terran Conflict and X³: Albion Prelude.

Moderators: Moderators for English X Forum, Scripting / Modding Moderators

User avatar
ScRaT_GER
Posts: 1958
Joined: Tue, 8. Jan 08, 19:19
x3tc

[TUTORIAL] Creating menus + two library scripts

Post by ScRaT_GER » Fri, 16. Oct 09, 23:45

Creating beautiful menus in X³:Terran Conflict

Since patch 2.5 is finally out, I decided to release a little tutorial on menus I wrote some time ago. It will especially describe the new menu commands coming with patch 2.5.

To fully understand this tutorial you should at least know how arrays work, because they are the basis for menus.

Other than that, there is not much to know.

-----------------------------------------------
Download: Tutorial - Creating menus (85 Kbyte)

Alternative link: Creating beautiful menus in X3: Terran Conflict (Egosoft X3 wiki)
-----------------------------------------------

If requested, I might add pictures to the tutorial, but I hope it is understandable anyways.

-----------------------------------------------
Library scripts

lib.scrat.format
A library for formatting your menus more easily.


lib.scrat.expand
A library for adding expandable menu selections to your script.
Examle animation:
Image



Both are explained and available here.

Alternative link:
Creating menus + two library scripts (Egosoft X3 wiki)

Please report, ask questions and give feedback.

-----------------------------------------------


For any comment, idea, mistake feel free to post in this thread.

Greetings,
ScRaT
Last edited by ScRaT_GER on Sat, 3. Mar 12, 17:54, edited 5 times in total.

User avatar
Litcube
Posts: 4245
Joined: Fri, 20. Oct 06, 19:02
xr

Post by Litcube » Fri, 16. Oct 09, 23:58

Nice! Thanks!

Cycrow
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 20600
Joined: Mon, 15. Nov 04, 00:26
x4

Post by Cycrow » Sat, 17. Oct 09, 00:04

one thing u didn't really mention about columns.
using a - value will right align based on the number, so as you said, -1 will be at the end. but u can use other numbers, -10 would move the text 10 pixels to the left, so there will be a 10 pixel gap between the end of the text and the edge of the menu

so this allows you to create column both ways, -1, -100, -200, could create 3 columns, all right aligned

and for value selections, it is possible to have the selections work without selecting an option from the menu, ie, if you press escape u get the return value of -1, without any of the changed value selections, but it is possible to get it working like that, by creating the selections manually and storing the array. As the menus will directly manipulate that array to change the values, u can then check it after to get whats changed, even when esc was pressed to close the menu.

1.60 of my cheats scripts does this for anyone who wants an example of it.

also looking at the board ship preload will help with column, as that uses custom columns as well

User avatar
ScRaT_GER
Posts: 1958
Joined: Tue, 8. Jan 08, 19:19
x3tc

Post by ScRaT_GER » Sat, 17. Oct 09, 00:12

so this allows you to create column both ways, -1, -100, -200, could create 3 columns, all right aligned
You're right. I'll mention that.
it is possible to have the selections work without selecting an option from the menu, ie, if you press escape u get the return value of -1
I mentioned that.
As the menus will directly manipulate that array to change the values, u can then check it after to get whats changed, even when esc was pressed to close the menu.
Which array will they directly manipulate (in the following code example)?

Code: Select all

add value selection to menu: $menu, text=$text, value array=$array, default=$id, return id=$dummy
Greetings,
ScRaT

Cycrow
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 20600
Joined: Mon, 15. Nov 04, 00:26
x4

Post by Cycrow » Sat, 17. Oct 09, 00:28

yes its the value array that it changes, specifically, the "default" argument

when u change a selection, it will update that part of the array

User avatar
ScRaT_GER
Posts: 1958
Joined: Tue, 8. Jan 08, 19:19
x3tc

Post by ScRaT_GER » Sat, 17. Oct 09, 00:31

Ah, thanks for the info.

I will add that in the next version.

Greetings,
ScRaT

Logain Abler
Posts: 2254
Joined: Mon, 31. Oct 05, 09:44
x4

Post by Logain Abler » Sun, 24. Jan 10, 20:16

Hi ScRat_GER,

Great guide which is helping me convert my menus, thanks :-)

However I'm having an issue with the game locking up if I try to make my menus dynamic.

Do you whats wrong with the below:

'plugin.FDN4.Node.Menu.Global' is called as a task by the menu and it works out the docks current used storage level:

Code: Select all

while $menu.check == [TRUE]
 
  $infoHeader = array alloc: size=0
  append 1 to array $infoHeader
  $text = read text: page=$PageID id=122
  append $text to array $infoHeader
  append 120 to array $infoHeader
  $curr = $node->get total volume in cargo bay
  $curr = convert number $curr to string
   
  $max = convert number $max to string
  $storage = '(' + $curr +  ')'
  append $storage to array $infoHeader
  
  $current = sprintf: pageid=$PageID textid=2030, $node, null, null, null, null
  set global variable: name=$current value=$infoHeader
  
  = wait 1000 ms
  $menu.check = $node->get local variable: name=$menu
end
This is the menu (segment of it):

Code: Select all

$task = $node->get next available task: starting=$PageID
$node->start task $task with script 'plugin.FDN4.Node.Menu.Global' and prio 100: arg1=$node arg2=null arg3=null arg4=null arg5=null
 
while [TRUE] 
  $text = read text: page=$PageID id=104
  $menu = create custom menu array: heading=$text

  $text = read text: page=$PageID id=909
  add custom menu heading to array $menu: title=$text
   
  $storage.check = sprintf: pageid=$PageID textid=2030, $node, null, null, null, null
  $storage = get global variable: name=$storage.check
  add custom menu item to array $menu: text=$storage returnvalue=null
     
  $text = read text: page=$PageID id=104
  $desc = sprintf: pageid=$PageID textid=9000, $name, null, null, null, null
  $ret = open custom menu: title=$text description=$desc option array=$menu
   
  skip if not is datatyp[ $ret ] == {DATATYP_ARRAY}
    $ret = $ret[0]
  if $ret == -1 
    goto label exit
  else
    = [THIS]->call script 'plugin.FDN4.Node.Menu.Action' : node=$node  action=$ret 
  end
   
end
There is more to the menu but the above is what I've done to try and make the stock level dynamic.

The lockup happens just after the '= wait 1000 ms'

Any pointer would be great.

Thanks

LA

Cycrow
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 20600
Joined: Mon, 15. Nov 04, 00:26
x4

Post by Cycrow » Sun, 24. Jan 10, 20:28

i assume what your trying to do is have the infolines change while the menu is still open ?

your script wont accomplish that however.

when you run the menu script, it will get the global varible ones, $storage, and display your menu, but the script will wait until you close the menu, by escape, or selecting an option, which means it will only update when a selection is made and the menu will close and reopen.

is that how you wanted it to work ?

what kind of lockup is it, does the game just completly stop ?
and is it always at the same point ?

what if you remove the the line below it, does it still lock up ?

also, you dont seem to have $menu defined, is that set somewhere else?

Logain Abler
Posts: 2254
Joined: Mon, 31. Oct 05, 09:44
x4

Post by Logain Abler » Sun, 24. Jan 10, 20:49

Cycrow wrote:i assume what your trying to do is have the infolines change while the menu is still open ?

your script wont accomplish that however.

when you run the menu script, it will get the global varible ones, $storage, and display your menu, but the script will wait until you close the menu, by escape, or selecting an option, which means it will only update when a selection is made and the menu will close and reopen.

is that how you wanted it to work ?

what kind of lockup is it, does the game just completly stop ?
and is it always at the same point ?

what if you remove the the line below it, does it still lock up ?

also, you dont seem to have $menu defined, is that set somewhere else?
Hi Cycrow,

Thanks for the quick reply.

The menu works fine normally, if I don't try and make the value update dynamically.

From ScRat_GER guide I was hoping the get the value to update every second like an in-game menu.

The lockup happens when the 'plugin.FDN4.Node.Menu.Global' loops after its first call.

If I remove the while statement from 'plugin.FDN4.Node.Menu.Global' so it only runs once there is no lockup.

Looks like I've mis-understood the guide.


On a linked issue, I can get the new 2.5 columns working fine with 'add custom menu item to array :<Array>: text=$array returnvalue=null' but nothing shows if I use the 'add custom menu info line to array:<Array>: text=$array'?


Thanks
LA

Cycrow
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 20600
Joined: Mon, 15. Nov 04, 00:26
x4

Post by Cycrow » Sun, 24. Jan 10, 20:59

you can technically make the menu update every seconds, but you need to manipulate the menu array directly.

also, after your infolines, trying adding a blank one below, there seems to be a problem with it counting infolines when using a text array

just set the blank one to use a text of ' '
ie, a single space.

for the dynamic update, u'll need to use the same array, not keep creating a new one

could do something like

Code: Select all

$storageInfo = create array with arguments, 1, $text1, 120, $text2

$task = $node->get next available task: starting=$PageID 
$node->start task $task with script 'plugin.FDN4.Node.Menu.Global' and prio 100: arg1=$node arg2=$storageInfo arg3=null arg4=null arg5=null 
  
while [TRUE]
  $text = read text: page=$PageID id=104 
  $menu = create custom menu array: heading=$text 

  $text = read text: page=$PageID id=909 
  add custom menu heading to array $menu: title=$text 
    
  add custom menu item to array $menu: text=$storageInfo returnvalue=null
then in your other, you will have a second argument that will be this array

Code: Select all

while $node -> get local variable: name=$menu
 $curr = $node->get total volume in cargo bay 
  $curr = convert number $curr to string 
    
  $max = convert number $max to string 
  $storage = '(' + $curr +  ')'
  $storeageInfo[3] = $storage
 
  = wait 1000 ms
end
also, you never said what the $menu is defined as ? i mean the one in plugin.FDN4.Node.Menu.Global

Logain Abler
Posts: 2254
Joined: Mon, 31. Oct 05, 09:44
x4

Post by Logain Abler » Sun, 24. Jan 10, 21:06

Cycrow wrote:you can technically make the menu update every seconds, but you need to manipulate the menu array directly.

also, after your infolines, trying adding a blank one below, there seems to be a problem with it counting infolines when using a text array

just set the blank one to use a text of ' '
ie, a single space.

for the dynamic update, u'll need to use the same array, not keep creating a new one

could do something like

Code: Select all

$storageInfo = create array with arguments, 1, $text1, 120, $text2

$task = $node->get next available task: starting=$PageID 
$node->start task $task with script 'plugin.FDN4.Node.Menu.Global' and prio 100: arg1=$node arg2=$storageInfo arg3=null arg4=null arg5=null 
  
while [TRUE]
  $text = read text: page=$PageID id=104 
  $menu = create custom menu array: heading=$text 

  $text = read text: page=$PageID id=909 
  add custom menu heading to array $menu: title=$text 
    
  add custom menu item to array $menu: text=$storageInfo returnvalue=null
then in your other, you will have a second argument that will be this array

Code: Select all

while $node -> get local variable: name=$menu
 $curr = $node->get total volume in cargo bay 
  $curr = convert number $curr to string 
    
  $max = convert number $max to string 
  $storage = '(' + $curr +  ')'
  $storeageInfo[3] = $storage
 
  = wait 1000 ms
end
also, you never said what the $menu is defined as ? i mean the one in plugin.FDN4.Node.Menu.Global
Cheers Cycrow, time to have another play, which is half the fun :-)

LA

User avatar
Litcube
Posts: 4245
Joined: Fri, 20. Oct 06, 19:02
xr

Post by Litcube » Tue, 26. Jan 10, 03:55

Wait - you can update menu items without re-opening the menu? That is hardcore.

Logain Abler
Posts: 2254
Joined: Mon, 31. Oct 05, 09:44
x4

Post by Logain Abler » Tue, 26. Jan 10, 09:38

Litcube wrote:Wait - you can update menu items without re-opening the menu? That is hardcore.
Yes you can, have a read of ScRat_GER's guide and dynamic menus; the example code he uses works a treat.

I just approached it the wrong way in my attempt.

LA

Logain Abler
Posts: 2254
Joined: Mon, 31. Oct 05, 09:44
x4

Post by Logain Abler » Tue, 26. Jan 10, 10:07

I’ve not seen this issue/consideration posted (although I’m sure it‘s been mentioned) so I thought it may help others.

When using the new ‘create new array, arguments’ command for menu value selection, if you change the selection then call another command, say one that open another menu, or uses an input box without first ensuring the selection change is written, your update will be lost.

An example would be Cycrow excellent cheat scripts (which I’ve used to learn how to write the new style menus), if you open the menu, change the unlimited insurance value, then use another command that calls another input (create ship or station) you will notice that the insurance value has reverted to is initial value. This is because the code which updates values based on the user selection is only called when the page is updated. You need to ensure its called if before you open another menu or input box from your initial menu.

I noticed this as the menus I’m building had the same issue:

The first example is a template I use based on Cycrow cheat menu:

Code: Select all

while [TRUE] 
   
  $menu = create custom menu array: heading='text goes here'
  add custom menu heading to array $menu: title='text goes here'
   
  'Your Menu items are built here'
   
  $ret = open custom menu: title='text' description='text' option array=$menu
   
  skip if not is datatyp[ $ret ] == {DATATYP_ARRAY}
    $ret = $ret[0]
  if $ret == -1 
    goto label exit
  else
        'Code to call other page or updates goes here' 
  end   
end
 
exit:
if $aValues 
  $count = size of array $aValues
  while $count 
    dec $count =
    $a = $aValues[$count]
    $wasOn = $aDefaults[$count]
    gosub sub.DoValue
  end
end
return null
 
sub.DoValue:
$id = $a[4]
$isOn = $a[3]
if $isOn != $wasOn 
  if $id == 'status' 
    if $wasOn == 1 
     'Code to update valube selection goes here'
    end
end
endsub
return null
I’ve added a new sub that is called when another update or command is called other than exit.

Code: Select all

while [TRUE] 
   
  $menu = create custom menu array: heading='text goes here'
  add custom menu heading to array $menu: title='text goes here'
   
  'Your Menu items are built here'
   
  $ret = open custom menu: title='text' description='text' option array=$menu
   
  skip if not is datatyp[ $ret ] == {DATATYP_ARRAY}
    $ret = $ret[0]
  if $ret == -1 
    goto label exit
  else
    gosub sub.load
    'Code to call other page or updates goes here' 
  end   
end
 
exit:
if $aValues 
  $count = size of array $aValues
  while $count 
    dec $count =
    $a = $aValues[$count]
    $wasOn = $aDefaults[$count]
    gosub sub.DoValue
  end
end
return null
 
sub.load:
if $aValues 
  $count = size of array $aValues
  while $count 
    dec $count =
    $a = $aValues[$count]
    $wasOn = $aDefaults[$count]
    gosub sub.DoValue
  end
end
endsub
 
sub.DoValue:
$id = $a[4]
$isOn = $a[3]
if $isOn != $wasOn 
  if $id == 'status' 
    if $wasOn == 1 
     'Code to update value selection goes here'
    end
end
endsub
return null
Like I’ve said, I’m sure it’s been mentioned but if your like me it helps to have examples. Hope it helps.

LA

Logain Abler
Posts: 2254
Joined: Mon, 31. Oct 05, 09:44
x4

Post by Logain Abler » Wed, 27. Jan 10, 10:52

Hi Cycrow,

Thanks for your pointer with the dynamic menu update.

After a few hours testing I got it working, my initial code was close, it looked like the script which updates the array in the Global didn’t like working directly with objects.

So something like ‘$current = $node->get total amount of ware $ware in cargo bay’ would cause the game to freeze, however if I called another script to provide the value it works with no issue.

Code: Select all

WORKS:
$a = array alloc: size=4
$a[0] = 1
$a[2] = 120
$aStorage = create new array, arguments=$a, [TRUE], null, null, null
$global = sprintf: pageid=$PageID textid=2041, $node, null, null, null, null
set global variable: name=$global value=$aStorage
 
while $active == 1 
   
  $curr = [THIS]->call script 'plugin.FDN4.Node.Menu.Values' : node=$node  caller='curr' 
  $max = [THIS]->call script 'plugin.FDN4.Node.Menu.Values' : node=$node  caller='max' 

  $text = read text: page=$PageID id=122
  $storage = '(' + $curr + '/' + $max + ')' 
   
  $aStorage[0][1] = $text
  $aStorage[0][3] = $storage
  = wait 1000 ms
   
  $active = get global variable: name=$is.active 
end


CAUSES FREEZE
$a = array alloc: size=4
$a[0] = 1
$a[2] = 120
$aStorage = create new array, arguments=$a, [TRUE], null, null, null
$global = sprintf: pageid=$PageID textid=2041, $node, null, null, null, null
set global variable: name=$global value=$aStorage
 
while $active == 1 
   
  $curr = $node->get total volume in cargo bay
  $curr = convert number $curr to string
  $max = 50000000 
  $max = convert number $max to string

  $text = read text: page=$PageID id=122
  $storage = '(' + $curr + '/' + $max + ')' 
   
  $aStorage[0][1] = $text
  $aStorage[0][3] = $storage
  = wait 1000 ms
   
  $active = get global variable: name=$is.active 
end
Steps I found that work:
Open script which updates the required values to global array (script1)
Open Menu (script 2)
Use a third script (script3) called by (script1) when you need to return a value from an object.

My FDN Nodes now have menus which dynamically update the storage used, just like in-game menus 

The issue I have now is that the menu won’t show dynamic updates when the menu item which is global is referred from within a while loop, say you want to list wares and their amounts.


LA

Post Reply

Return to “X³: Terran Conflict / Albion Prelude - Scripts and Modding”