The Dink Network

Reply to Re: Dink with Lua scripting

If you don't have an account, just leave the password field blank.
Username:
Password:
Subject:
Antispam: Enter Dink Smallwood's last name (surname) below.
Formatting: :) :( ;( :P ;) :D >( : :s :O evil cat blood
Bold font Italic font hyperlink Code tags
Message:
 
 
January 27th 2014, 03:21 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
I apologize for the lack of updates. My vacation has finished, and the time I have to work on this project has greatly diminished. That being said, I'm not done, so don't lose hope, if you were waiting for me to finish.

As a treat for the impatient, why don't I demonstrate how I've dealt with choice menus? The choice menu is the strangest construct in DinkC, it doesn't follow the rules of any other programing language I've ever seen. Because of its odd structure, I cannot directly replicate it in Lua. Just a reminder of how choice menus work in DinkC first:

choice_start(); 
set_y 240 
set_title_color 15 
title_start(); 
This is the title
title_end(); 
"Choice 1" 
(&cow > 1) (&sheep < 5) "Choice 2" 
"Choice 3" 
choice_end();

if (&result == 1)
{
  // Do "Choice 1" stuff
}
// etc.


If you're a fan of that structure, the way you can imitate that the most in Lua goes like this:

local choice_menu = dink.create_choice_menu({
"Choice 1",
{global.cow > 1 and global.sheep < 5, "Choice 2"},
"Choice 3"
}, "This is the title", 240, 15)
choice_menu: show()

if global.result == 1 then
  -- Do "Choice 1" stuff
elseif global.result == 2 then
  -- etc.
end


Not quite as elegant as the DinkC solution, but again, that cannot be quite replicated in a proper programming language. However, as Lua support object orientation, I still think we emerge victorious in a comparison. This is how the choice menu is meant to be used in Lua:

local choice_menu = dink.create_choice_menu()

local choice1 = choice_menu:add_choice("Choice 1")
local choice2 = choice_menu:add_choice("Choice 2", global.cow > 1 and global.sheep < 5)
local choice3 = choice_menu:add_choice("Choice 3")

local choice_result = choice_menu: show()

if choice_result == choice1 then
  -- Do "Choice 1" stuff
elseif choice_result == choice2 then
  -- etc.
end


Why do I think this is better?

First of all, you get choice result objects from the add_choice method, which you can use in your if statements later. If you name these well, you don't have to keep scrolling back up and count where in your choice menu that choice is, so you can compare against the right result number. Another obvious benefit is that if you were to shuffle your choice order, you wouldn't have to change a thing anywhere else. In DinkC, if you move "Choice 2" to the top, then it would suddenly be &result == 1, and you'd have to change your if statements around. In Lua, "Choice 2" would still result in choice_result == choice2, and so no change is necessary.

Second (and this also works with the DinkC-like shorthand shown first), you can prepare your choice menu in one location, and use it in another. You can re-use the same choice menu objects over and over again, once created. Here's an example from my "escape.lua" file (The Lua counterpart of DinkC's "escape.c"):

function main()
  dink.playsound(18, 22050, 0, nil, false)
  player:freeze()
  
  -- Prepare escape menu
  local escape_menu = dink.create_choice_menu()
  local escape_load = escape_menu:add_choice("Load a previously saved game")
  local escape_restart = escape_menu:add_choice("Restart")
  local escape_quit = escape_menu:add_choice("Quit to system")
  local escape_help = escape_menu:add_choice("Help")
  local escape_continue = escape_menu:add_choice("Continue")
  local escape_gamepad = escape_menu:add_choice("View/change gamepad buttons")
  local escape_save = escape_menu:add_choice("Save game")
  --escape_save.condition = false -- Disable save-anywhere choice
  
  -- Prepare quit menu
  local quit_menu = dink.create_choice_menu()
  local quit_yes = quit_menu:add_choice("Yes, I really want to quit the game")
  local quit_no = quit_menu:add_choice("I was just kidding, back to the action, please")

  -- <Prepare all the other escape menus>
  -- ...

  while true do
    local escape_result = escape_menu: show()
    
    if escape_result == escape_continue then
      player:unfreeze()
      dink.kill_this_task()
      return
    elseif escape_result == escape_quit then
      local quit_result = quit_menu: show()
      
      if quit_result == quit_no then
        dink.wait(300)
        player: say("Phew, that was a close one!")
      elseif quit_result == quit_yes then
        dink.kill_game()
      end
      
      player:unfreeze()
      dink.kill_this_task()
    end
  end
end


I've obviously left out a lot of the "escape.lua" functionality here, but you get the gist: You can prepare the menus one place, and use them in another, which can result in a nice noise reduction in the part of your code that acts upon the choices. And if you think about it, by separating choice menu creation from choice menu usage, you could even move the choice menu creation out of your code files entirely and into a file dedicated to choice menu creation if you wanted to.

If you have any feedback, feel free to drop me a reply. Again, I am still working on this, the pace has just slowed down quite a bit due to my vacation having ended.