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?
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:
-- 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)
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()
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
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
Quote from: 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.
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! :)
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
Quote from: 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()
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.
Here's how I achieved this.
In main.lua, within the sol.main:start_savegame(game) function:
-- ♡ 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().
-- ♡ 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.