Differ between ground treasures and chest treasures?

Started by the bread, August 21, 2015, 03:35:30 PM

Previous topic - Next topic
When a kind of rupee is picked for the first time, I want my rupee system to show a message that informs the player about how much it is worth. I have tried to implement it like this:
Code ( lua) Select

local item = ...

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

function item:on_obtaining(variant)
  local amounts = {1,5,10,20,50,100}
  local colors = {"green","blue","yellow","red","violet","orange"}
  local game = self:get_game()
  game:add_money(amounts[variant])
  local rupee_obtained = colors[variant] .. "_rupee_obtained"
  if not game:get_value(rupee_obtained) then
    game:set_value(rupee_obtained,true)
    if not (colors[variant] == "green") then
      local dialog_id = "_treasure.rupee." .. variant
      game:start_dialog(dialog_id)
    end
  end
end


This works fine for rupees that are lying around on the ground. However, when the first rupee of a color comes from a chest the game crashes because the same dialog is called twice (once by the engine, once by the item script in on_obtaining). Is there exist a way to get the origin of an item? I didn't find anything in the documentation but maybe there's a workaround? Any completely different solution is of course welcome as well ;)

It is a bug of the engine if it tries to show a dialog when you are already doing so.
You could do self:set_brandish_when_picked(true) initially, and do self:set_brandish_when_picked(false) from on_obtaining.

The only problem is that you apparently don't want a dialog for green rupees. So you can do one anyway, waiting for me to fix the engine bug. Otherwise you need to implement green rupees as a different item.

I don't really understand how this should work. Calling set_brandish_when_picked(false) in on_obtaining() doesn't affect the currently obtained rupee. So if I set the brandish to false in on_obtaining, unknown kinds of rupees won't be brandished anymore. The exception for green rupees is not really necessary, by the way.


I've got an idea for another workaround. It would be like this:
1.) set_brandish_when_picked(false) is called in the on_created function and keeps this state
2.) When obtaining a variant of a rupee that hasn't been obtained yet, hero:start_treasure is called, causing the hero to brandish the treasure, no matter how the treasure is obtained.
3.) Change a global value to indicate that a treasure was created by hero:start_treasure. This is necessary because otherwise there would be an endless loop (on_obtaining starts a treasure that has an on_obtaining function that starts a treasure...)
4.) The old treasure has to be deleted so that the same treasure is not obtained twice (and the obtaining dialog is not called by the engine causing the same error as before)

This is my idea. However, I do not yet know how to do 4.)
I am not sure whether it is possible to delete a treasure when the on_obtaining function is called (in fact, I doubt it). An other way would be not to delete the treasure but
1.) Prevent rupees being added for the first treasure and
2.) Prevent the dialog being called automatically by the engine for the first treasure when the rupee comes from a chest.

Number one could be done quite easily (using the global variable from 3. to add the rupees only for the second treasure if there is any) but again, I don't have any idea how to prevent the dialog or whether this is even possible.
I know that this idea is kind of a dirty hack :-[ Well, it's just meant to be a solution until the bug is fixed in the engine. Hopefully it works ;D

Another ugly hack is to test the state of the hero. If hero:get_state() == "freezed" in on_obtaining, then the treasure probably comes from a chest.

Another idea: maybe you can have two rupee item scripts. One that you only use in chests, and the other one that you use for pickables, enemies and destructibles.

Thanks for making so much thoughts on this problem :D
The check for hero:get_state() == "freezed" didn't work. I think it's because only one single state can be saved and "freezed" is overwritten by "treasure". However, when I tried hero:get_state() == "treasure" instead it worked perfectly fine although it was just a wild guess. Is the "treasure" state only set for brandished treasures?

Yes, the "treasure" state corresponds to brandishing a treasure. This is a good solution then :)