Solarus Forum

Solarus => Development => Topic started by: Porksteak on June 19, 2017, 04:12:22 pm

Title: Item command held on item?
Post by: Porksteak on June 19, 2017, 04:12:22 pm
Hi I wanted to try and make some kind of energy blast attack that gets stronger the longer you hold it. Is there a way in the item to check if the specific item key that the item is assigned to is being held down?
Title: Re: Item command held on item?
Post by: YoshiMario2000 on June 19, 2017, 07:09:01 pm
What you'll probably want to do is create a timer (or a set of timers) that count for how long you want the difference of time between the instances of charge.

So doing something like this:
Code: ( lua) [Select]
-- At beinging of code
local timer = nil

--  Code before timers
local function start_timer()
  timer = sol.timer.start(item, 1000, function()
    --code relating to when timer reaches max time
  end) -- This timer lasts 1 sec and belongs to "context" item if defined. To increase the time, change the 2nd value to desired time in milliseconds.

end

local function end_timer()
  local time_remaining = timer:get_remaining_time()
  --code relating to translating time into charge
  --I.E. Total charge value / (time_remaining * -1)
  --return charge_strength
end


See http://www.solarus-games.org/doc/latest/lua_api_timer.html (http://www.solarus-games.org/doc/latest/lua_api_timer.html) for more details relating to timers.

For checking if the item is being held down, I would look to these sets of events: http://www.solarus-games.org/doc/latest/lua_api_game.html#lua_api_game_on_key_pressed (http://www.solarus-games.org/doc/latest/lua_api_game.html#lua_api_game_on_key_pressed)
Title: Re: Item command held on item?
Post by: Porksteak on June 20, 2017, 05:20:58 pm
I started the item, but I can't get the command released function to work so the hero stays frozen

This is function:on_using()
Code: ( lua) [Select]
function item:on_using()
local map = game:get_map()
local hero = game:get_hero()

local direction = hero:get_direction()




  if game:is_command_pressed("item_1") or game:is_command_pressed("item_2") then
  state = 1
      if blastlevel < 4 then
    timer = sol.timer.start(2000, function()
      blastlevel = blastlevel + 1
    return true
    end)
  end
  end



    if game:get_item_assigned(2) == "blast" and not game:is_command_pressed("item_2") and state == 1 then
      game:simulate_command_released("item_2")
    end

    if game:get_item_assigned(1) == "blast" and not game:is_command_pressed("item_1") and state == 1 then
      game:simulate_command_released("item_1")
    end


end


function game:on_command_released(command)
  if command == "item_1" or "item_2" then
    timer:stop()
    hero:unfreeze()
    item:fire_blast()
  end
end
Title: Re: Item command held on item?
Post by: MetalZelda on June 21, 2017, 12:34:22 pm
To make the hero controllable just call item:set_fiinished()

But, you might want to control the hero and having the item to work. I would link a menu to this item and control everrything from this menu, you will have access to on_command_pressed / released.

That's what I do for my bow, hookshot and other stuffs
Title: Re: Item command held on item?
Post by: Diarandor on June 21, 2017, 04:48:59 pm
To make the hero controllable just call item:set_fiinished()

But, you might want to control the hero and having the item to work.

You can directly unfreeze the hero (which allows to control him) before calling item:set_finished(), which is probably what he needs. This is what I use for my "custom jump", which allows to control the hero during the jump. But don't forget to call item:set_finished() when you finish using the item! :)
Title: Re: Item command held on item?
Post by: Porksteak on June 28, 2017, 04:25:46 am
Yeah, but the problem is the unfreeze() is in the on_command_released function, but when the key is released nothing happens and the hero stays frozen
Title: Re: Item command held on item?
Post by: Diarandor on June 28, 2017, 09:36:51 am
I started the item, but I can't get the command released function to work so the hero stays frozen

This is function:on_using()
Code: ( lua) [Select]
function item:on_using()
local map = game:get_map()
local hero = game:get_hero()

local direction = hero:get_direction()




  if game:is_command_pressed("item_1") or game:is_command_pressed("item_2") then
  state = 1
      if blastlevel < 4 then
    timer = sol.timer.start(2000, function()
      blastlevel = blastlevel + 1
    return true
    end)
  end
  end



    if game:get_item_assigned(2) == "blast" and not game:is_command_pressed("item_2") and state == 1 then
      game:simulate_command_released("item_2")
    end

    if game:get_item_assigned(1) == "blast" and not game:is_command_pressed("item_1") and state == 1 then
      game:simulate_command_released("item_1")
    end


end


function game:on_command_released(command)
  if command == "item_1" or "item_2" then
    timer:stop()
    hero:unfreeze()
    item:fire_blast()
  end
end

Are you aware of the fact that defining "game" events inside an item script is a bad idea and that one event definition will override other previous definitions of that event in other scripts? I am talking about game.on_command_released.
Title: Re: Item command held on item?
Post by: alexgleason on September 25, 2018, 08:51:16 pm
Here's how I achieved this.

In main.lua, within the sol.main:start_savegame(game) function:

Code: (lua) [Select]
-- ♡ Copying is an act of love. Please copy and share.

-- Returns an item for item_ command strings
function get_item_for_command(command)

  local slot = tonumber(string.match(command, "^item_([12])$"))

  if slot then
    local item = game:get_item_assigned(slot)
    return item
  else
    return nil
  end
end


function game:on_command_pressed(command)

  -- Handle items with item:on_command_pressed()
  local item = get_item_for_command(command)
  if item and item.on_command_pressed ~= nil then
    item:on_command_pressed(command)
    return true
  else
    -- Fall back to item:on_using()
    return false
  end

end

function game:on_command_released(command)

  -- Handle items with item:on_command_released()
  local item = get_item_for_command(command)
  if item and item.on_command_released ~= nil then
    item:on_command_released(command)
    return true
  else
    return false
  end

end

Then within the item itself, simply implement item:on_command_pressed() and item:on_command_released().

Code: ( lua) [Select]
-- ♡ Copying is an act of love. Please copy and share.

function item:on_command_pressed(command)
  print(string.format("%s command pressed", item:get_name()))
end

function item:on_command_released(command)
  print(string.format("%s command released", item:get_name()))
end

In this case, item:on_using() is never called. If you choose not to implement item:on_command_pressed() for a particular item, it will fall back to item:on_using().

I'm a bit afraid I've missed something which I'll discover later, but this works in normal circumstances.