Cutscene builder bug

Started by boaromayo, February 20, 2019, 01:04:06 PM

Previous topic - Next topic
I'm using std::gregwar's cutscene builder for my game, and for some reason, this error pops up whenever .hero_start_treasure() is called:

QuoteError: In timer callback: [string "scripts/maps/cutscene.lua"]:252: bad argument #2 to start_treasure (integer expected, got function))

I tried using different arguments to call that function, but that same error prompt still pops up.

Here's snippets of my cutscene code:


function map:cutscene()
    -- Some other code here...
    .set_direction(hero,0)
    .dont_wait_for.hero_animation("walking")
    .movement(
      {
        type = "target",
        entity = hero,
        properties = {
          speed = 80,
          target = {124,200},
          smooth = true,
          ignore_obstacles = true
        }
      })
    .dont_wait_for.hero_animation("stopped")
    .wait(500)
    .hero_start_treasure("prison_key", 1, "prison_key_get") -- This is where an error is triggered.
    .exec(game:set_value("main_story", 2))
    -- More code below...


Could this be a bug in the cutscene builder?

Hi boaromayo,

Glad to see you found some use for this old little helper. Where did you found it ? On the forum ?

The fact is that it is no more maintained because Solarus 1.6 can use coroutines to express this kind of asynchronous behaviour.
So yes this could be a bug... but it won't be fixed as  far as i'm concerned.

The new way to write cutscenes (among other things) easily is to use `coroutine_helper.lua` from the free-resource-pack. (https://gitlab.com/solarus-games/solarus-free-resource-pack/blob/dev/data/scripts/coroutine_helper.lua)

This will allow you to write cutscene even more easily.

Best

February 20, 2019, 02:47:35 PM #2 Last Edit: February 20, 2019, 03:44:40 PM by boaromayo
Hey, gregwar, thanks for the quick response!

I found the cutscene builder in this forum post here. It's been so helpful in putting my scenes together!

Also, thanks for the coroutine helper script!

Looks like I'm going to have to do rewrites now that that script is no longer going to be updated...

EDIT: Btw, can the coroutine helper be expanded to have more features, such as freezing or unfreezing the hero, or having the camera move to a certain location on the map? Plus, does this script only work on Solarus 1.6?

QuoteEDIT: Btw, can the coroutine helper be expanded to have more features, such as freezing or unfreezing the hero, or having the camera move to a certain location on the map? Plus, does this script only work on Solarus 1.6?

Coroutine helper works very differently of cutscene builder. Whereas in cutscene_builder the only actions you could do were things allowed by the script, in coroutines you can call any engine function during the cutscene as long as they do not require waiting. (hero:freeze() for example). For the engine features that take a callback you can use wait_for to suspend the coroutine until the callback is called. I hope this is clear. If you need more help you can ask questions on the discord server.

Happy Making!

I managed to do a workaround using the cutscene builder, and the cutscene worked smoothly.

Thanks for the help anyway!

Sorry to necropost a bit, but I've been playing around with this coroutine_helper script and wondered if there was any additional documentation.

For example, I don't understand what wait_for might be used for - are there example of specific engine functions that this might utilize this?

You also specifically pointed out hero:freeze - was this saying this function would NOT work with this coroutine setup? I'm having sporadic issues with hero:freeze working, either inside or outside of the coroutine, so I wasn't sure if that was known behaviour.

Quote from: wrightmat on October 28, 2019, 06:38:05 PM
Sorry to necropost a bit, but I've been playing around with this coroutine_helper script and wondered if there was any additional documentation.

The documentation is in the form of a comment at the top of the script file.

Quote from: wrightmat on October 28, 2019, 06:38:05 PM
For example, I don't understand what wait_for might be used for - are there example of specific engine functions that this might utilize this?

wait_for() is a generic implementation of "wait for a function with a callback to complete". You can use it with any function whose last argument is a callback function (the coroutine script supplies the callback so you don't have to).

Example:
Code (lua) Select

map:start_coroutine(function()
  wait_for(map.move_camera, map, 100, 0, 128)
  dialog("sample_dialog")
  wait(100)
  wait_for(hero.start_treasure, hero, "ultimate_sword", 1, nil) --nil for unused savegame_variable parameter
  print("done!")
end)


Which is basically equivalent to:
Code (lua) Select

map:move_camera(100, 0, 128, function()
  game:start_dialog("sample_dialog", nil, function()
    sol.timer.start(map, 100, function()
      hero:start_treasure("ultimate_sword", 1, nil, function()
        print("done!")
      end)
    end)
  end)
end)


The first example is easier to read, isn't it? 8)

Be sure you are using the latest version of the coroutine_helper script because there was a bug in specifying nil parameters in the wait_for() function. See https://gitlab.com/solarus-games/solarus-free-resource-pack/issues/16

Quote from: wrightmat on October 28, 2019, 06:38:05 PM
You also specifically pointed out hero:freeze - was this saying this function would NOT work with this coroutine setup? I'm having sporadic issues with hero:freeze working, either inside or outside of the coroutine, so I wasn't sure if that was known behaviour.

I think the point stdgregwar was making is that hero:freeze() would not have worked in the old cutscene builder script, but it does work in with the coroutine helper script (as does any function that doesn't require waiting). If a function does require waiting and isn't already setup to be used in the coroutine helper script, then you'd have to edit the coroutine helper script to incorporate it (or get it to work using wait_for()).

October 30, 2019, 03:06:56 PM #7 Last Edit: October 30, 2019, 04:18:59 PM by wrightmat
Thanks llamazing - that's really helpful! And I just grabbed the script less than a month ago, so I've only worked with the most recent version.

The specific problem I'm having relates to hero:freeze() presumably not working. With this code the hero does not freeze:


  map:start_coroutine(function()
    hero:freeze()
    m:set_target(296, 728);
    movement(m, npc)
    m:set_target(184, 656);
    movement(m, npc)
    dialog("npcs.npc")
    game:set_value("quest", 0)
    hero:unfreeze()
  end)


Strangely enough, hero:get_state() still returns "frozen" as expected, but I have full control.

Huh. Seems to be a weird issue with map:on_started() since hero:freeze() works when I call it later. If I build in a one second delay, everything is fine. Not sure if this is an issue with the engine or the script.

Map:on_started is called before isn't a good place to start this. Map:on_opening_transition_finished() is called after on_sarted, and also the hero is automatically unfrozen after the transition is over, which is probably the issue you're solving with the 1sec delay.

Try calling this from on_opening_transition_finished, that might fix it


I wasn't aware of that bug. Thanks so much - works great now!