Trying to force equip a usable item.

Started by DementedKirby, July 29, 2015, 01:17:42 AM

Previous topic - Next topic
Okay, so here's the code for the item:

local item = ...

function item:on_created()
  self:set_brandish_when_picked(true)
  self:set_savegame_variable("possession_book")
  self:set_sound_when_picked(nil)
  self:set_assignable(true)
end

function item:on_using()
   sol.audio.play_sound("bush")
end


It exists, has a dialogue, is set to assignable, and presumably everything else I need to be able to use it.

Playing around to see how the Solarus functions work, I made a sensor that will automatically assign that item (book) to one of the item keys like so:

local map = ...
local game = ...

function equipBook:on_activated()
   function game:set_item_assigned(1, book)
   end
end


So, I'm assuming that with the item created and everything specified, that this sensor will equip the item to slot 1 in order to use it (before going over to the item I'm opening a chest with the item to make sure the hero gets it). Unfortunately, I get this error:

Error: Failed to load script 'maps/Map5': [string "maps/Map5.lua"]:5: <name> or '...' expected near '1'
Error: In maps/Map5: attempt to call a string value

I have no idea why.

Replace (in your map script)
Code (lua) Select
local game = ...
By
Code (lua) Select
local game = map:get_game()

The `...` allow to get the arguments passed to the script, so you can only get the map from a map script by this way (the item from an item script, etc).

And for the `equipBook:on_activated` method, I think you need to write something like this :
Code (lua) Select

function equipBook:on_activated()
  game:set_item_assigned(1, game:get_item("book"))
end


You have defined the method instead of call it and the variable `book` isn't defined, you need to get it by the method `game:get_item`.
SQE developer

Okay, so I changed everything you told me and I got this as error:
Error: In on_activated: [string "maps/Map5.lua"]:5: attempt to call method 'get_item' (a nil value)

It's weird, it means that this method is not defined in game. However, it is in the API and for me it works very well.

But I have even so a bug because it is necessary to possess an item before assigning it.

I suggest you do it in another way to get your item directly with the map editor, placing it in a chest or on the ground.
SQE developer

That's the thing; I did place it in a chest. I go to the chest first then go to the sensor to equip the item in the slot and nothing happens. I know it should be equipped because I know the sensor is working because I put some sounds to see if it's working. The sound happens but I can't use the item when hitting any of the keys (X or V).

I don't understand why the method `get_item` isn't defined in your script, but you can try with this code (in the map script) :
Code (lua) Select

function map:on_obtained_treasure(item)
  if item:get_name() == "book" then
    game:set_item_assigned(1, item)
  end
end

This way the item will be automatically assigned when you retrieve it.
SQE developer

Now I get this:
Error: In on_obtained_treasure: [string "maps/Map5.lua"]:25: attempt to call method 'set_item_assigned' (a nil value)
???
Why are these codes not working? I'm pretty much doing what I'm supposed to be doing and nothing. Something so simple as setting an item to a slot is taking me over a day to get to work. This is very frustrating...

There is a problem with the `game` variable and I cannot help you more than that with the infos you gave me.

Could you give me a link with all the data of your quest? (Github, Drive, Dropbox, or something else)
SQE developer

July 29, 2015, 07:00:45 PM #8 Last Edit: July 29, 2015, 07:22:39 PM by DementedKirby
Yeah, I probably should just give up trying to do everything from scratch (which is what I would like to do given a model/instructions or whatever and not just copy/pasting Mystery of Solarus's luas) for the moment. I know that it's more efficient to work off of the Solarus game and work my way from there, but I want to add way more items than Mystery of Solarus has. So by that reason alone I can't really use its menu. I did read over the code (all the luas to make the game run) and apparently there's like a million things I have to have going on in order to even make a Zelda game possible (before the player being even able to start a quest). I can design maps and dungeons and puzzles and items but in the end, all I can do is test. I can't really get a game started until I'm able to develop the system of equipping items.

That being said, I decided to try and code my item into Mystery of Solarus (and force equipping it) which actually works given what you suggested. So I really have no idea what's wrong with my own game. However, to move past my problem of something as simple as equipping the thing and try to at least make the item work before I can implement it in my own game, I'm trying to make the Book of Mudora. So I'll work off of Mystery of Solarus to at least test my items. I would like to be able to contribute as well in item scripting because my game is really ambitious and I'm working on a whole bunch of other things (I got an Iron Boots concept to work wonderfully and simply, so at least I'm happy for that, lol). As soon as I'm able to get my bearings in Solarus I can be able to share my discoveries with the community (like after I finish getting the Book of Mudora to work, lol).

Using this item requires a change in the hero's graphics (already created an animation and directions for it and set them up in the appropriate place in the hero tab) and named it 'book'. This is the code for the book:

local item = ...

function item:on_created()

  self:set_savegame_variable("possession_book")
  self:set_assignable(true)
end

function item:on_using()
sol.audio.play_sound("bush")
end


Ok, as I was getting the info you asked in order to help on the other game, now I can't get this to work in Mystery of Solarus either. Lemme first check again to see what I did wrong...

UPDATE:
Here's what I want the book to do:

local item = ...
local game = map:get_game()

function item:on_created()

  self:set_savegame_variable("possession_book")
  self:set_assignable(true)
end

function item:on_using()
  hero:freeze()
  hero:set_animation(book)
  game:start_dialog("book.test")
  hero:unfreeze()
end


The item is equipped as you say and everything works until I make the item do something. As long as the only thing in the book.lua is

local item = ...

function item:on_created()

  self:set_savegame_variable("possession_book")
  self:set_assignable(true)
end


it works. If I add the item:on_using() function to the book.lua, the error goes so far as to not even force equip it as you say. So basically, I can only force equip the item via the map script you gave me in the 1st slot so long as the book.lua has no other lines of code besides being created. The mystery continues...

Okay, finally got it working. I think the problem was adding the map get game line.

Anyways, so it finally works except that the hero freezes when using the item and doesn't unfreeze. Not only that, but the animation doesn't change as I want it to. Here' what the book is trying to do:

function item:on_using()
  hero:set_animation(book)
  game:start_dialog("book.test")
  self:set_finished()
end

The book animation I'm referring to is an animation in the hero entity that I made which is just one frame in all four directions of him reading the book. But, nothing happens. Well, to be more precise, it freezes and nothing happens, lol.

This isn't what the book is going to do. I'm just testing to see if I can get this item to work per se. The purpose of the book is to check to see if the hero is in certain spots that require translating. When the location matches one of the books locations, then instead of getting the usual dialog, you'd get the translated dialog. In theory it should work. However, I want to give a message when the hero uses the book when there's nothing to read. I still want the animation to occur though because I want to first see if it works.[/code]

I haven't tested this but I think it should work better like this (you made a few mistakes explained in comments) :
Code (lua) Select

local item = ...
local game = item:get_game() -- not map:get_game(), map isn't defined here

function item:on_created()

  self:set_savegame_variable("possession_book")
  self:set_assignable(true)
end

function item:on_using()
  hero:set_animation("book") -- this method get a string as parameter, book doesn't exists here
  game:start_dialog("book.test", nil, function ()  -- use the callback function of the dialog to finish after this one
    item:set_finished()
  end)
end


You should see the messages in the error.txt file and learn to determine what it really mean to fix that yourself. ;)
SQE developer

July 29, 2015, 09:41:30 PM #11 Last Edit: July 29, 2015, 09:45:01 PM by DementedKirby
Thanks for explaining the errors of my code! You've been really helpful and I appreciate it (now that you mention the error.txt, this game in particular isn't generating an error.txt file in its folder after closing the game window so that maybe a whole other problem altogether...) Yet, despite literally just copy/pasting your code, it's still not working but for some reason,  The hero still freezes and doesn't do absolutely anything else after I use the item for a first time. Oh, and yeah, the book animation is one I created in the hero folder of the entities part of the quest. It's literally only one frame (regardless of direction; all four directions is the same sprite) and it's called "book".

UPDATE:
The problem is changing the hero's animation. I made the line into a comment and everything else worked. Meaning that I can't simply use that command to change the hero's graphic as he's using the item? That feels a bit counter-intuitive... How then would I be able to program other items like the Hammer and Net? Link's gotta change graphics when using these items. I've been reading the documentation and it talks about set animations already coded into Solarus but if I'm able to make new animations I should be able to access them the same way, no?

If you have any problems with the error.txt file, you can always start the engine or editor from a console. If you're on Windows there is an option in the editor settings to display a console at launch.

This way you see all the error messages directly into the console.
SQE developer

Ok, got it, here's the error:
Error: In on_using: [string "items/book.lua"]:11: attempt to index global 'hero' (a nil value)

Ok, the `hero` variable isn't defined here, you need to get it like that:
Code (lua) Select

item:get_map():get_entity("hero")

So you can replace the line 11 by:
Code (lua) Select

item:get_map():get_entity("hero"):set_animation("book")
SQE developer