Solarus-Games English Forum

Solarus => Development => Topic started by: Dragon_noir on May 19, 2015, 07:23:30 PM

Title: Small keys
Post by: Dragon_noir on May 19, 2015, 07:23:30 PM
How do you enable small keys on a map?
Title: Re: Small keys
Post by: Christopho on May 19, 2015, 08:44:55 PM
This can be done in Lua.
If your map is called "my_map", you can make an item "small_key_my_map" that has an amount (the number of small keys), and set this item as required on each locked door of this map.
Title: Re: Small keys
Post by: Dragon_noir on May 19, 2015, 09:21:55 PM
I don't really understand, I'm just beginning to learn how to program.

Do I need to create a new item for each key I want in a map?(I can't seem to be able to create a key without this line of code

item:set_savegame_variable("")
)

this is the code for small keys i have now (from Zelda DX)

local item = ...

function item:on_created()

  item:set_shadow("small")
  item:set_brandish_when_picked(false)
  item:set_sound_when_picked("picked_small_key")
  item:set_savegame_variable("possession_small_key")
end

function item:on_obtaining(variant, savegame_variable)

  item:get_game():add_small_key()
end

Title: Re: Small keys
Post by: Christopho on May 19, 2015, 10:00:39 PM
Zelda Mystery of Solarus DX has a system of small keys different from was I was suggesting. In ZSDX there is only one "small_key" item for the whole game, and the Lua scripts detects in what current dungeon we are to increment the correct savegame variable.

What you can do is a small key item for each dungeon. For example in dungeon 1, you can make several treasure chests containing the item "dungeon_1_small_key".
Your small key item script should do something like item:set_amount_savegame_variable("dungeon_1_small_key_amount") instead of item:set_savegame_variable("possession_small_key"). Because this is an item with an amount: you want to save an integer (the number of small keys), not a boolean (whether the player has an item).

(I should do a tutorial about small keys :))
Title: Re: Small keys
Post by: Dragon_noir on May 19, 2015, 10:29:00 PM
Ok I tried it , but now I'm getting this error message:

Error: In create_door: bad argument #1 to ? (Bad field 'opening_condition' (equipment item 'small_key' is not saved))

, and my doors do not appear on the map.

This is my small key code now:

local item = ...

function item:on_created()

  item:set_shadow("small")
  item:set_brandish_when_picked(false)
  item:set_sound_when_picked("picked_small_key")
  item:set_amount_savegame_variable("dungeon_small_key_amount")
end

function item:on_obtaining(variant, savegame_variable)

  item:get_game():add_small_key()
end
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 08:50:05 AM
For doors to work with an item, the possession state of the item also needs to be saved (maybe I should change that, actually). So in item:on_created(), try to also add item:set_savegame_variable("dungeon_small_key_possession").

And remove the item:on_obtaining() function, it is not needed if the door directly checks the item. (ZSDX is not a great example for small keys, it does more complicated things for historical reasons.)
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 09:04:27 AM
Actually I think I forgot something important here...
We need two items: one for the small key counter, and one for the obtainable small keys. Like we do for rupees: there is an rupee item and a rupee bag item.
So for dungeon 1, they would be called "dungeon_1_small_key_counter" and "dungeon_1_small_key"

dungeon_1_small_key_counter.lua:

local item = ...

function item:on_created()
  item:set_savegame_variable("dungeon_1_small_key_counter_possession")
  item:set_amount_savegame_variable("dungeon_1_small_key_counter_amount")
end


dungeon_1_small_key.lua:

function item:on_created()
  item:set_shadow("small")
  item:set_brandish_when_picked(false)
  item:set_sound_when_picked("picked_small_key")
end

function item:on_obtaining(variant, savegame_variable)

  local counter = item:get_game():get_item("dungeon_1_small_key_counter")
  counter:set_variant(1)
  counter:add_amount(1)
end


Still not tested, sorry. I will prepare a tutorial on this.
Title: Re: Small keys
Post by: Dragon_noir on May 20, 2015, 01:59:51 PM
Tested it, but it doesn't work :/

I also can't get the key counter to appear on screen.

I'll just wait for a tutorial .
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 02:07:51 PM
Is there an error message?
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 03:42:36 PM
In the meantime you can always reproduce what is done in Zelda Mystery of Solarus DX. At least we know it works :)
Title: Re: Small keys
Post by: Dragon_noir on May 20, 2015, 04:05:07 PM
No, i don't have an error message.

It works fine for 1 key.
But if I pick up 2 keys and open a door I have no keys left. It's like it doesn't save the amount of keys I have, and as I can't get the HUD to show the small keys counter, I don't really know what's happening.
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 04:12:41 PM
Can you send us your quest data?
Title: Re: Small keys
Post by: Dragon_noir on May 20, 2015, 04:20:06 PM
Sure, where do you want me to send it?
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 04:31:44 PM
As you want, you can host it with google drive or dropbox for example.
Title: Re: Small keys
Post by: Dragon_noir on May 20, 2015, 04:46:51 PM
https://drive.google.com/file/d/0B6qvF6HbdSMHWlFqeXJHR0VseUU/view?usp=sharing

Never used google drive before. i hope the link works .
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 05:19:13 PM
Thanks! I found the problem. We forgot to set the maximum amount of our counter, and by default the maximum is zero (which is probably stupid, and I will change that in Solarus 1.5).

Here is the updated code:

dungeon_1_small_key_counter.lua:

local item = ...

function item:on_created()
  item:set_savegame_variable("dungeon_1_small_key_counter_possession")
  item:set_amount_savegame_variable("dungeon_1_small_key_counter_amount")
  item:set_max_amount(999)
end


dungeon_1_small_key.lua:

function item:on_created()
  item:set_shadow("small")
  item:set_brandish_when_picked(false)
  item:set_sound_when_picked("picked_small_key")
end

function item:on_obtaining(variant, savegame_variable)

  local counter = item:get_game():get_item("dungeon_1_small_key_counter")
  counter:set_variant(1)
  counter:add_amount(1)
end


Also, in dungeon_1_small_key.lua, don't forget to remove the set_savegame_variable() line. It is the counter that saves its possession state, not each individual key.
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 05:19:22 PM
Now, to make the HUD, this is a completely different matter. You can use the same as ZSDX, except that you have to retrieve the counter value differently.

You can implement helper functions game:get_num_small_keys(), game:get_dungeon(), etc like in ZSDX.
In get_num_small_keys(), get the small key counter of the current dungeon with something like

local dungeon_number = game:get_dungeon()
local counter = game:get_item("dungeon_" .. dungeon_number .. "_small_key_counter")

and then the value is counter:get_amount().
Title: Re: Small keys
Post by: Dragon_noir on May 20, 2015, 07:10:09 PM
No, still doesn't work :(

If I don't use the line "item:set_savegame_variable()" in the dungeon_1_small_key.lua file, I get the error:

"Error: In create_door: bad argument #1 to ? (Bad field 'opening_condition' (equipment item 'dungeon_1_small_key' is not saved))"

As I've said in the beginning i'm just a beginner and I don't really know what I'm doing.

The HUD script for the key counter is almost the same as ZeldaDX
Title: Re: Small keys
Post by: Christopho on May 20, 2015, 07:39:00 PM
Your doors need to require the small key counter item, not the small key item. The code I pasted above works, I tested it on your data.
The small key item is a treasure whose only effect is to increment the small key counter item. The logic is that a door can be opened if small key counter > 0.

Items with counters are not trivial. I recommend you to watch the tutorial video (in French) about the bow and arrows because it works the same way. There is a bow item (the counter) and an arrow item (the one that increments the counter). I understand that it can be more confusing for small keys.

If you prefer, you can rename "small key counter" to "bunch of keys" (trousseau de clés en français), maybe it will be easier to undertand the difference.
Title: Re: Small keys
Post by: Dragon_noir on May 20, 2015, 11:11:38 PM
Yes! That was my error. I used the small key item instead of the counter :D.

One more question: How do I make it so that a map shows the key counter.

I can get it to show up when I set

"small_keys.visible = false" to "small_keys.visible =  true" in the file small_keys.lua (script/hud/small_keys.lua)

PS: Thanks for your patience ;)
Title: Re: Small keys
Post by: Christopho on May 21, 2015, 08:53:52 AM
But you don't want to set it visible all the time, you want it only in dungeons.

This visible property is set from the result of game:are_small_keys_enabled() in ZSDX. This function is defined in equipment.lua. It could look like this:


-- Returns whether a small key counter exists on the current map.
function game:are_small_keys_enabled()
  return game:get_small_keys_counter_item() ~= nil
end

-- Returns the item that stores the number
-- of small keys for the current map, or nil.
function game:get_small_keys_counter_item()

  local map = game:get_map()

  if map ~= nil then
    -- Are we in a dungeon?
    local dungeon_index = game:get_dungeon_index()
    if dungeon_index ~= nil then
      local item_name = "dungeon_" .. dungeon_index .. "_small_key_counter"
      return game:get_item(item_name)
    end
  end

  -- No small keys on this map.
  return nil
end

-- Returns whether the player has at least one small key.
-- Raises an error is small keys are not enabled in the current map.
function game:has_small_key()

  return game:get_num_small_keys() > 0
end

-- Returns the number of small keys of the player.
-- Raises an error is small keys are not enabled in the current map.
function game:get_num_small_keys()

  if not self:are_small_keys_enabled() then
    error("Small keys are not enabled in the current map")
  end

  local item = self:get_small_keys_counter_item()
  if item == nil then
    return 0
  end

  return item:get_amount()
end


In equipment.lua from ZSDX, replace all functions related to small keys by this code. Then you should not have to change anything in the HUD code.
Your small key counter item has to be named exactly dungeon_1_small_key_counter.
To make get_small_keys_counter_item() detect that you are in a dungeon, you have to set the world of your map to "dungeon_1".
Title: Re: Small keys
Post by: Dragon_noir on May 21, 2015, 12:09:45 PM
Doesn't work :(

I've looked around the code and i think there's something wrong within the function small_keys:check() . A variable never gets set to "true".

I've also added the dungeon.lua file to my data.
Title: Re: Small keys
Post by: Christopho on May 21, 2015, 05:59:59 PM
But did you even call dungeons.lua and equipment.lua at some point?
It does work, I just tested it ;)

You should really learn Lua to be able make your own scripts. I recommend this book: http://www.lua.org/pil/contents.html
Title: Re: Small keys
Post by: Dragon_noir on May 21, 2015, 06:51:28 PM
I got it to work :D

Thanks :)