Author Topic: [SOLVED] Trouble porting a script  (Read 277 times)

MetalZelda

  • Hero Member
  • *****
  • Posts: 508
    • View Profile
[SOLVED] Trouble porting a script
« on: June 25, 2017, 04:40:28 pm »
Hello.

So, I am porting a RUBY script to lua.
This script will allow easier pause menu creation, replacing cursor position by user defined positions. Like so

Code: Lua
  1. local elements = {
  2.   config = {save = true},
  3.   {"rupee_bag", 68, 78, "info"},
  4.   {"bomb_bag", 68, 104, "info"},
  5.   {"quiver", 68, 130, "info"},
  6.   {"deku_nuts_bag", 68, 156, "info"},
  7.   {"bombchu_bag", 68, 182, "info"},
  8.   {"sword", 217, 84, "action"},
  9.   {"tunic", 209, 180, "action", variant = "_1"},
  10.   {"tunic", 233, 180, "action", variant = "_2"},
  11.   {"tunic", 257, 180, "action", variant = "_3"},
  12.   {"glove", 209, 132, "info"},
  13.   {"shield", 233, 132, "info"},
  14.   {"climb_ring", 257, 132, "info"},
  15.   {"sword_biggoron", 249, 84, "action"},
  16. }

The 2nd and 3rd index is used to place an item on the X and Y axis, as well as the cursor

This is the RUBY script I'm trying to port

Code: Ruby
  1. # Initialize variables for the weightings on the vertical and horizontal
  2.       # directions
  3.                         wv, wh = 0, 0
  4.       # The weightings for the secondary and primary axis relative to input
  5.                         w1, w2 = 1, 2
  6.       # Initialize a variable for the direction and get the direction
  7.       # pressed by the user
  8.       input_dir = 0
  9.       input_dir = 2 if Input.repeat?(Input::DOWN)
  10.       input_dir = 4 if Input.repeat?(Input::LEFT)
  11.       input_dir = 6 if Input.repeat?(Input::RIGHT)
  12.       input_dir = 8 if Input.repeat?(Input::UP)
  13.       # Do nothing if no button was pressed
  14.       return if input_dir == 0
  15.       #get the item
  16.       item = self.item
  17.       #if the item is left toggle and the input direction is left
  18.       if item == :left_toggle && input_dir == 4
  19.         #move to the left window
  20.         return $scene.move_window(6)
  21.       #elsif the item is right toggle and the input direction is right
  22.       elsif item == :right_toggle && input_dir == 6
  23.         #move to the right window
  24.         return $scene.move_window(4)
  25.       end
  26.       # Setup the weightings for each direction
  27.                         if  (input_dir == 2 or input_dir == 8)
  28.                                 wv, wh = w1, w2
  29.                         elsif (input_dir == 4 or input_dir == 6)
  30.                                 wv, wh = w2, w1
  31.                         end
  32.       # Get the xy position of the current item
  33.                         cxy = @xy_pos[@index]
  34.       # Create default value for the closest item's distance (absurdly large)
  35.       closest_index = -1
  36.                         closest_distance = 9999999
  37.       # Loop through every item
  38.                         for i in 0...@xy_pos.size
  39.                                 # Skip if it is the old item or is in the opposite direction
  40.                                 if @index == i or
  41.                                    (input_dir == 2 and @xy_pos[i][1] < cxy[1]) or
  42.                                    (input_dir == 4 and @xy_pos[i][0] > cxy[0]) or
  43.                                    (input_dir == 6 and @xy_pos[i][0] < cxy[0]) or
  44.                                    (input_dir == 8 and @xy_pos[i][1] > cxy[1])
  45.                                         next
  46.                                 end
  47.         # Get the distance from the last highlighted item to this tested one
  48.                                 dist_h = (@xy_pos[i][0] - cxy[0]).abs
  49.                                 dist_v = (@xy_pos[i][1] - cxy[1]).abs
  50.         # If it is really against the primary axis
  51.         if (wh == w1 and w2 * dist_h < dist_v) or
  52.             (wv == w1 and w2 * dist_v < dist_h)
  53.           next
  54.         end
  55.         # Get the distance multiplied with their weightings
  56.                                 dist = dist_h * wh + dist_v * wv
  57.         # Set at closest item if appropriate
  58.                                 if (dist < closest_distance)
  59.                                         closest_distance = dist
  60.                                         closest_index = i
  61.                                 end
  62.                         end
  63.       # Do nothing if nothing was selected
  64.       return if closest_index == -1
  65.       @index = closest_index
  66.       #move cursor
  67.       move_cursor

@xy_pos is already defined in the elements variable, @cxy is the current cursor position, they are already defined

The only problem, RUBY have a skip iterator whereas I can't find the closest thing for lua

This is my attempt in Lua, which still fails, the cursor will still highlight the current item forever

Code: Lua
  1. function submenu:set_cursor_position(command)
  2.   local width = sol.video.get_quest_size()
  3.   width = width / 2 - 160
  4.  
  5.   local current_x = self.cursor_position.x
  6.   local current_y = self.cursor_position.y
  7.        
  8.   -- Create default value for the closest item's distance
  9.   local closest_index = -1
  10.   local closest_distance = 320
  11.        
  12.   -- Initialize variables for the weightings on the vertical and horizontal direction
  13.   local wv, wh = 0, 0
  14.        
  15.   -- The weightings for the secondary and primary axis relative to input
  16.   local w1, w2 = 1, 2
  17.        
  18.   -- Setup the weightings for each direction
  19.   if (command == "down" or command == "up") then
  20.     wv, wh = w1, w2
  21.   elseif (command == "left" or command == "right") then
  22.         wv, wh = w2, w1
  23.   end
  24.  
  25.   for i = 1, #self.items do
  26.     local item = self.items[i]
  27.         local item_x = item.x
  28.         local item_y = item.y
  29.         local current_item_index = self:find_item(self:find_item_axis(self.cursor_position.x, self.cursor_position.y))
  30.        
  31.         --  Skip if it is the old item or is in the opposite direction
  32.         if current_item_index == i or (command == "down" and item_y < current_y) or (command == "left" and item_x > current_x) or (command == "right" and item_x < current_x) or (command == "up" and item_y > current_y) then
  33.           -- tried goto
  34.         end
  35.        
  36.         -- Get the distance of the current item and the new one
  37.         local dist_h = math.abs(item_x - current_x)
  38.         local dist_v = math.abs(item_y - current_y)
  39.                
  40.         if (wh == w1 and w2 * dist_h < dist_v) or (wv == w1 and w2 * dist_v < dist_h) then
  41.           goto matched
  42.         end
  43.        
  44.         ::matched::
  45.     -- # Get the distance multiplied with their weightings
  46.         local dist = (dist_h * wh + dist_v * wv)
  47.                  
  48.         -- # Set at closest item if appropriate
  49.         if (dist < closest_distance) then
  50.           closest_distance = dist
  51.           closest_index = i
  52.         end
  53.   end
  54.        
  55.   local item = self.items[closest_index]
  56.   local x = item.x
  57.   local y = item.y - 5 
  58.        
  59.   self.cursor_position = {x = x, y = y + 5}
  60.   self.cursor_sprite_x = x + width
  61.   self.cursor_sprite_y = y
  62.   self.game:set_custom_command_effect("action", item.effect)
  63.  
  64.   local caption_item = item.item .. "_" .. self.game:get_item(item.item):get_variant()
  65.   if item.item == "tunic" then
  66.     caption_item = "tunic_" .. self:get_tunic_variant()
  67.   end
  68.  
  69.   self:set_caption(self.caption_text_keys[caption_item])  
  70.   self.game:set_value("equipment_last_index", position)
  71. end
  72.  
  73.  

Is there a Lua equivalent of "next" ?

Next = https://www.tutorialspoint.com/ruby/ruby_loops.htm
Jumps to the next iteration of the most internal loop. Terminates execution of a block if called within a block (with yield or call returning nil).
« Last Edit: July 03, 2017, 01:25:32 pm by MetalZelda »

Maxs

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Trouble porting a script
« Reply #1 on: June 25, 2017, 06:35:43 pm »
I don't think that there are a Lua equivalent to the next statement of Ruby, but you can easily reproduce this with a variable.

For example :

Code: Ruby
  1. for i in 0...@xy_pos.size
  2.   if (condition)
  3.      next
  4.   end
  5.   # rest of the code
  6. end
  7.  

becomes :

Code: Lua
  1. for i = 1, #items do
  2.   local to_next = false
  3.   if (condition) then
  4.      to_next = true
  5.   end
  6.  
  7.   if not to_next then
  8.     -- rest of the code
  9.   end
  10. end
  11.  
SQE developer

llamazing

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Trouble porting a script
« Reply #2 on: June 25, 2017, 06:41:04 pm »
There isn't an equivalent to next in lua, but you can accomplish the same thing using if statements. Take the two simplified examples (using lua syntax for illustration purposes)

Code: Lua
  1. for i = 1, #self.items do
  2.     if index == i then
  3.         next --not valid lua
  4.     end
  5.    
  6.     print("not skipped")
  7. end

Code: Lua
  1. --equivalent to the following
  2. for i = 1, #self.items do
  3.     if index ~= i then
  4.         print("not skipped")
  5.     end
  6. end

So in your for block you could do the following in lua (note I have not tested it so there may be errors):
Code: Lua
  1. for i,item in ipairs(self.items) do
  2.     local item_x = item.x
  3.     local item_y = item.y
  4.     local current_item_index = self:find_item(self:find_item_axis(self.cursor_position.x, self.cursor_position.y))
  5.    
  6.     --  Skip if it is the old item or is in the opposite direction
  7.     if current_item_index ~= i and (command ~= "down" or item_y >= current_y) and (command ~= "left" or item_x <= current_x) and (command ~= "right" or item_x >= current_x) and (command ~= "up" or item_y <= current_y) then
  8.         -- Get the distance of the current item and the new one
  9.         local dist_h = math.abs(item_x - current_x)
  10.         local dist_v = math.abs(item_y - current_y)
  11.        
  12.         if (wh ~= w1 or w2 * dist_h >= dist_v) and (wv ~= w1 or w2 * dist_v >= dist_h) then
  13.             -- # Get the distance multiplied with their weightings
  14.             local dist = (dist_h * wh + dist_v * wv)
  15.        
  16.             -- # Set at closest item if appropriate
  17.             if (dist < closest_distance) then
  18.                 closest_distance = dist
  19.                 closest_index = i
  20.             end
  21.         else
  22.             --equivalent to next, do nothing this iteration
  23.         end
  24.     else
  25.         --equivalent to next, do nothing this iteration
  26.     end
  27. end

Also note that instead of doing
Code: Lua
  1. for i = 1, #self.items do
  2.     local item = self.items[i]
  3.     ...
  4. end

it is better to use
Code: Lua
  1. for i,item in ipairs(self.items) do
  2.     ...
  3. end

MetalZelda

  • Hero Member
  • *****
  • Posts: 508
    • View Profile
Re: Trouble porting a script
« Reply #3 on: June 25, 2017, 09:44:27 pm »
This kinda work, it is better than last time because now the cursor and item change.

However, this is messy, it only loops through 2 items, the distance system works but it only loops between 2 items, light be the command stuff but it looks ok ...

Code: Lua
  1. function submenu:set_cursor_position(command)
  2.   local width = sol.video.get_quest_size()
  3.   width = width / 2 - 160
  4.  
  5.   local current_x = self.cursor_position.x
  6.   local current_y = self.cursor_position.y
  7.        
  8.   -- Create default value for the closest item's distance
  9.   local closest_index = -1
  10.   local closest_distance = 9999999
  11.   local index = self:find_item(self:find_item_axis(current_x, current_y))
  12.        
  13.   -- Initialize variables for the weightings on the vertical and horizontal direction
  14.   local wv, wh = 0, 0
  15.        
  16.   -- The weightings for the secondary and primary axis relative to input
  17.   local w1, w2 = 1, 2
  18.        
  19.   -- Setup the weightings for each direction
  20.   if  (command == "down" or command == "up") then
  21.     wv, wh = w1, w2
  22.   elseif (command == "left" or command == "right") then
  23.         wv, wh = w2, w1
  24.   end
  25.  
  26.   for i, item in ipairs(self.items) do
  27.     local x = item.x
  28.         local y = item.y
  29.        
  30.         --  This isn't the old item or the opposite direction
  31.         if index ~= i or (command ~= "down" and y > current_y) or (command ~= "left" and x < current_x) or (command ~= "right" and x > current_x) or (command ~= "up" and y < current_y) then
  32.           -- Get the distance of the current item and the new one
  33.           local dist_h = math.abs(x - current_x)
  34.           local dist_v = math.abs(y - current_y)
  35.          
  36.           if (wh ~= w1 or w2 * dist_h > dist_v) and (wv ~= w1 or w2 * dist_v > dist_h) then
  37.             local dist = (dist_h * wh + dist_v * wv)
  38.                
  39.                 -- Set at closest item if appropriate
  40.             if (dist < closest_distance) then
  41.                   closest_distance = dist
  42.                   closest_index = i
  43.             end
  44.           end    
  45.         end
  46.   end
  47.  
  48.   local item = self.items[closest_index]
  49.   local x = item.x
  50.   local y = item.y - 5 
  51.        
  52.   self.cursor_position = {x = x, y = y + 5}
  53.   self.cursor_sprite_x = x + width
  54.   self.cursor_sprite_y = y
  55.   self.game:set_custom_command_effect("action", item.effect)
  56.  
  57.   local caption_item = item.item .. "_" .. self.game:get_item(item.item):get_variant()
  58.  
  59.   self:set_caption(self.caption_text_keys[caption_item])  
  60.   self.game:set_value(self.menu .. "_last_index", tostring(x) .. "," .. tostring(y + 5))
  61. end

index prints the right item index in the array so this is not the culprit there
Hmmm, that's the 1st time a ruby script port grinds my gears
« Last Edit: June 25, 2017, 09:47:59 pm by MetalZelda »

llamazing

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Trouble porting a script
« Reply #4 on: June 25, 2017, 10:05:02 pm »
Do  you have a sample project available? It's a bit hard to troubleshoot from the forum.

Also double-check that I negated those if statements correctly.

MetalZelda

  • Hero Member
  • *****
  • Posts: 508
    • View Profile
Re: Trouble porting a script
« Reply #5 on: June 29, 2017, 05:54:36 pm »
Do  you have a sample project available? It's a bit hard to troubleshoot from the forum.

Also double-check that I negated those if statements correctly.

I will upload a sample demo tomorrow, i'm currently very busy

Diarandor

  • Hero Member
  • *****
  • Posts: 779
  • Cats are cool! (ΦωΦ)
    • View Profile
Re: Trouble porting a script
« Reply #6 on: June 29, 2017, 06:22:56 pm »
Cool! ;D We will start testing it soon.

MetalZelda

  • Hero Member
  • *****
  • Posts: 508
    • View Profile
Re: Trouble porting a script
« Reply #7 on: July 02, 2017, 03:47:13 pm »
Somehow I got the thing to work properly, I don't even know how

Code: Lua
  1. function submenu:set_cursor_position(command)
  2.   -- Initialize variables for the weightings on the vertical and horizontal
  3.   -- directions
  4.   local wv, wh = 0, 0
  5.   -- The weightings for the secondary and primary axis relative to input
  6.   local w1, w2 = 1, 2
  7.  
  8.   local input = -1
  9.   if command == "right" then
  10.     input = 0
  11.   elseif command == "up" then
  12.     input = 1
  13.   elseif command == "left" then
  14.     input = 2
  15.   elseif command == "down" then
  16.     input = 3
  17.   end
  18.  
  19.   if input == -1 then return end
  20.  
  21.   -- Setup the weightings for each direction
  22.   if  (input == 1 or input == 3) then
  23.         wv, wh = w1, w2
  24.   elseif (input == 0 or input == 2) then
  25.         wv, wh = w2, w1
  26.   end
  27.  
  28.   local width = sol.video.get_quest_size()
  29.   width = width / 2 - 160
  30.  
  31.   local current_x = self.cursor_position.x
  32.   local current_y = self.cursor_position.y
  33.  
  34.   -- Create default value for the closest item's distance
  35.   local closest_index = -1
  36.   local closest_distance = 9999999
  37.   local index = self:find_item(self:find_item_axis(current_x, current_y))
  38.  
  39.   for i, item in ipairs(self.items) do
  40.     local item_x = item.x
  41.     local item_y = item.y
  42.    
  43.     --  Skip if it is the old item or is in the opposite direction
  44.     if index ~= i and (input ~= 3 or item_y >= current_y) and (input ~= 2 or item_x <= current_x) and (input ~= 0 or item_x >= current_x) and (input ~= 1 or item_y <= current_y) then
  45.       -- Get the distance of the current item and the new one
  46.       local dist_h = math.abs(item_x - current_x)
  47.       local dist_v = math.abs(item_y - current_y)
  48.        
  49.       if (wh ~= w1 or w2 * dist_h >= dist_v) and (wv ~= w1 or w2 * dist_v >= dist_h) then
  50.         -- # Get the distance multiplied with their weightings
  51.         local dist = (dist_h * wh + dist_v * wv)
  52.        
  53.         -- # Set at closest item if appropriate
  54.         if (dist < closest_distance) then
  55.           closest_distance = dist
  56.           closest_index = i
  57.         end
  58.       end
  59.     end
  60.   end
  61.  
  62.   if closest_index == -1 then return end
  63.  
  64.   local item = self.items[closest_index]
  65.   local x = item.x
  66.   local y = item.y - 5 
  67.        
  68.   self.cursor_position = {x = x, y = y + 5}
  69.   self.cursor_sprite_x = x + width
  70.   self.cursor_sprite_y = y
  71.   self.game:set_custom_command_effect("action", item.effect)
  72.  
  73.   self:set_caption(self.caption_text_keys[caption_item])  
  74.   self.game:set_value(self.menu .. "_last_index", closest_index)
  75. end

There is still some problem regarding some items but that's because I use some wizzard stuffs, for example, you need a separate item for each tunic variant, else it will be stuck on the tunic.

What makes this useful is, the simpliciity of menu customisation, you just have to put a x and y value for your item, the script determine the input pressed and stuffs, instead of using cursor position stuffs

This was my Quest status menu before the change


Notice how it is done ... Manually by stuffs

Now, it just looks like this


All of my menues now run this code

The pro is that it is easier to make and place objects in the menues, the cons is that every objects need to be an item
« Last Edit: July 03, 2017, 01:12:56 pm by MetalZelda »