Having Trouble with Quest simulation

Started by gmanplays@gmail.com, January 06, 2019, 08:42:35 PM

Previous topic - Next topic
I've been back on Solarus ever since I saw it got updated again, but unfortunately I've not been able to get the "Run quest" function of the quest editor to run. Whenever I click "run quest", the screen merely remains blank (without presenting the solarus logo) and eventually I get the following error:

>Error: In main: scripts/game_manager.lua:103: attempt to call method 'register_event' (a nil value)

Here's the problem line:

>game_meta:register_event("on_map_changed", function(game)

However, when I go and check that particular line and cross-reference it with another line (located above line 103) that contains the method "register_event", it seems to be working just fine. Doesn't that mean that register_event has a non-nil value? For example, here's a line that makes use of register_event that does not incur an error, located above the problem line

>game:register_event("on_joypad_button_pressed", function(game, button)

Now, I know that this has "game:" instead of "game_meta:" but I changed it to "game:" and it gave me an error at that line. I'm not sure that'd make a difference either. Anyways, I probably need someone technically competent to aid me here, go ahead and comment if you need more info.

So, the whole "register event" stuff is from this "multi events" script that most everyone uses- have you added that, and if so, have you called it in the appropriate places?

I might not be understanding your whole problem if the multi-events system is working fine elsewhere though. Maybe post your whole game_manager script.

Also, are you trying to run your own quest? Someone else's? The default quest that is created when you make a new project?

Make sure you include the multi-events script at the top with require("scripts/multi_events") (or whatever the file path is to the script in your quest).

I agree with Max. Please let us know if the problem is solved.
RIP Aaron Swartz

So I inserted the line Alex recommended, and I booted. The results: I got the logo going now, but then I'm presented with the same black screen and a new error. This one reads:

>Error: In on_finished: main.lua:20: attempt to call method 'start_game' (a nil value)

The main.lua script does make mention at the beginning a similar require("scripts/game_manager) line, so that's not the problem this time. Here's copy of the script (problem line is italicized. I tried playing around with it the best I could but I didn't make any headway).

-- This is the main Lua script of your project.
-- You will probably make a title screen and then start a game.
-- See the Lua API! http://www.solarus-games.org/doc/latest

local game_manager = require("scripts/game_manager")

-- This function is called when Solarus starts.
function sol.main:on_started()

  -- Setting a language is useful to display text and dialogs.
  sol.language.set_language("en")

  local solarus_logo = require("scripts/menus/solarus_logo")

  -- Show the Solarus logo initially.
  sol.menu.start(self, solarus_logo)

  -- Start the game when the Solarus logo menu is finished.
  solarus_logo.on_finished = function()
    game_manager:start_game()
  end

end

-- Event called when the player pressed a keyboard key.
function sol.main:on_key_pressed(key, modifiers)

  local handled = false
  if key == "f5" then
    -- F5: change the video mode.
    sol.video.switch_mode()
    handled = true
  elseif key == "f11" or
    (key == "return" and (modifiers.alt or modifiers.control)) then
    -- F11 or Ctrl + return or Alt + Return: switch fullscreen.
    sol.video.set_fullscreen(not sol.video.is_fullscreen())
    handled = true
  elseif key == "f4" and modifiers.alt then
    -- Alt + F4: stop the program.
    sol.main.exit()
    handled = true
  elseif key == "escape" and sol.main.game == nil then
    -- Escape in title screens: stop the program.
    sol.main.exit()
    handled = true
  end

  return handled
end

main.lua is trying to call game_manager:start_game(), which must not exist in your game_manager.lua script.

While that's the case, where should I insert then game_manager:start_game()? What prefix should I use? Function, game, game_meta, or another? Thanks much for y'alls help by the way, been a great help so far

What's in your game manager script? The problems you're having sound like ones that come from not having the basic files set up properly.

A bit of overview that might help you figure this stuff out- the only thing that the "run quest" button runs is main.lua. There, most likely, there's a like something like:
local game_manager = require("scripts/game_manager")
Which means, now, in the main.lua script, whenever "game_manager" is written, it's referring to whatever the "scripts/game_manager" returns. Probably there ought to be a "start_game" function in your game manager, which would create or load a game.

What are you trying to run? A game you made yourself? Someone else's game? The default quest that is created when you go to file>new quest?

Here's the game manager script:

-- Script that creates a game ready to be played.

-- Usage:
-- local game_manager = require("scripts/game_manager")
-- local game = game_manager:create("savegame_file_name")
-- game:start()

local game_manager = {}

local initial_game = require("scripts/initial_game")
local multi_events = require("scripts/multi_events")

-- Creates a game ready to be played.
function game_manager:create(file_name)

  local exists = sol.game.exists(file_name)
  local game = sol.game.load(file_name)
  if not exists then
    -- Initialize a new savegame.
    initial_game:initialize_new_savegame(game)
  end

  -- Function called when the player presses a key during the game.
  game:register_event("on_key_pressed", function(game, key)

    if game.customizing_command then
      -- Don't treat this input normally, it will be recorded as a new command binding
      -- by the commands menu.
      return false
    end

    local handled = false
    if game:is_pause_allowed() then  -- Keys below are menus.
      if key == game:get_value("keyboard_save") then
        if not game:is_paused() and
          not game:is_dialog_enabled() and
          game:get_life() > 0 then
        game:start_dialog("save_quit", function(answer)
          if answer == 1 then
            -- Continue.
            sol.audio.play_sound("danger")
          elseif answer == 2 then
            -- Save and quit.
            sol.audio.play_sound("danger")
            game:save()
            sol.main.reset()
          else
            -- Quit without saving.
            sol.audio.play_sound("danger")
            sol.main.reset()
          end
        end)
        handled = true
      end
      end
    end

    return handled
  end)

  -- Function called when the player presses a joypad button during the game.
  game:register_event("on_joypad_button_pressed", function(game, button)
    if game.customizing_command then
      -- Don't treat this input normally, it will be recorded as a new command binding.
      return false
    end

    local handled = false

    local joypad_action = "button " .. button
    if game:is_pause_allowed() then  -- Keys below are menus.
      if joypad_action == game:get_value("joypad_save") then
        if not game:is_paused() and
            not game:is_dialog_enabled() and
            game:get_life() > 0 then
          game:start_dialog("save_quit", function(answer)
            if answer == 2 then
              -- Continue.
              sol.audio.play_sound("danger")
            elseif answer == 3 then
              -- Save and quit.
              sol.audio.play_sound("danger")
              game:save()
              sol.main.reset()
            else
              -- Quit without saving.
              sol.audio.play_sound("danger")
              sol.main.reset()
            end
          end)
          handled = true
        end
      end
    end

    return handled
  end)

  return game
end

-- TODO the engine should have an event game:on_world_changed().
local game_meta = sol.main.get_metatable("game")
game_meta:register_event("on_map_changed", function(game)

  local map = game:get_map()
  local new_world = map:get_world()
  local previous_world = game.previous_world
  local world_changed = previous_world == nil or
      new_world == nil or
      new_world ~= previous_world
  game.previous_world = new_world
  if world_changed then
    if game.notify_world_changed ~= nil then
      game:notify_world_changed(previous_world, new_world)
    end
  end
end)

game_meta:register_event("on_game_over_started", function(game)
  -- Reset the previous world info on game-over
  -- so that notify_world_changed gets called.
  game.previous_world = nil
end)

return game_manager

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

It's true that in main there's a string like the one you posted, but there's no such "start_game" string in game manager.
I'm currently running the default quest that's created when one goes to file>new quest

When you do File > New Quest in Solarus 1.6, main.lua is not the one you posted.

Come to think of it, I did originally make this quest in 1.5 before I knew that 1.6 was out. I then got 1.6 and it automatically updated the file. Do you think that the main.lua of that quest didn't change in that update, and is now incompatible with the current version?

January 09, 2019, 06:08:49 AM #10 Last Edit: January 09, 2019, 06:13:13 AM by Max
So, if you post your code like this:
[code=Lua]
Paste your code here
[\code]

(Except use a forward slash, not a backslash!)
It'll make it much easier to read for us : )

If you haven't changed anything in the game manager yourself on purpose, you should be able to copy the scripts from the 1.6 new quest into your current project. Or copy your current project's files into a new quest.

It looks like the problem is your main is calling game_manager:start_game(), which is not a function that the game manager you posted has. It looks like you might want to instead call game_manager:create("put the file name here")

For example, here's a couple lines in my main:

local game = game_manager:create"save1.dat"
  sol.main:start_savegame(game)


It sends a string, "save1.dat" to the game manager script to make a new game, or load one if it already exists, which the game_manager sends back as "game". Then we start that game with Sol.main.start_savegame

IT WORKED BOYS

Thanks much for all y'alls help  ;D

Quote from: gmanplays@gmail.com on January 09, 2019, 12:46:54 AM
I then got 1.6 and it automatically updated the file
No, when you update to 1.6 Solarus does not touch your scripts at all.