Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - MetalZelda

#496
Quote from: Diarandor on November 05, 2015, 08:58:28 PM
Quote from: Diarandor on November 05, 2015, 03:42:23 AM
Another solution would be to allow the functions game:get/set_ability(...) of the engine to have "pushing" and "pulling" as parameters. Do you agree Christopho? I will open an issue for this in github, since this could be a useful feature.
This is the link of the issue on github, just to have it here too:
https://github.com/christopho/solarus/issues/788

I have thought that, when we fix the direction of the hero, maybe we should not forget to reset the variable hero.fixed_direction to nil when the hero changes map (to stop fixing the direction), just to avoid some possible problems. I just wanted to point out this small detail. (One must be always careful with these small details...  :()

Oh I did have check the github issue, thanks ^^
for the direction fix thing, the best solution is, when 1.5 would be here, to do a item:on_map_changed function, and disable the item right after being teleported, the value should reset itself since the sprite id would have been changed if I do like christopho did (with quest manager script) but with the "official" on_direction_changed.
#497
Your projects / Re: Zelda: Book of Mudora
November 05, 2015, 05:38:36 PM
This is amazing to see that your project is in constant evolution each update, al'right, time to play  :)
Chris, are you gonna continue BoM let's play ?
#498
Quote from: Diarandor on November 05, 2015, 02:20:58 PM
To save states or other info, you can use any entity of the engine, or even the game, because almost everything are Lua lists. In the same manner as you did with
Code (Lua) Select

hero.fixed_direction = direction

you can put a list like
Code (Lua) Select

hero.bow_info={}

or
Code (Lua) Select

game.bow_info={}

and store the bow variables inside.

(On the other hand, for the changes of animation to avoid changing tunic, I think I will wait for v1.5 to avoid workarounds with the sprite metatable,...).

Hmmm i'm gonna try your method, thanks.
For the bow having a lot of tunic sprites that shouldn't be a problem, since the old method (see OP) try to keep direction fixed even if the sprite id has changed, i'm gonna wait for 1.5 to be released then for the direction fix, in hope that it'll arrive before next year  :)
#499
Quote from: Diarandor on November 05, 2015, 03:02:45 AM
Hi!
@Username: I have read all your code and understand better now the input part you use. I realized you use savegame variables to save or get the state of the bow; but using savegame variables for this is probably not necessary; it would be better to use a normal variable instead

Hi

The fact that I use savegame variable for geting the state is because the item script is divided in 2 scripts : the item itself, and item_manager (the one that control the inputs), I did tried local and global variables, but they result in issues and freezes, so to counter this I did have take the savegame variable solutions, disabled the pause menu access during the item control sequence and reset every item savegame variable each time the game resets / is stopped. So they act as temporary in-game variable, and can be used in various other items scripts (to check if the item state is 0, otherwise start the put-away sequence and start the new item)

Quote from: Diarandor on November 05, 2015, 03:02:45 AM
I also noticed that you use lots of tunics instead of changing animation, for the bow. I would use only one sprite, used also for the stopped and walking animations, but changing the animation when necessary in the on_animation_changed event of the sprite metatable, in a similar way as we do with the direction (that should work if the frame number is not reseted when the animation changes, which I think is true).

I already thought about it, but since we can't change the default hero animation in 1.4.4, the solution was to make different tunic for each actions (shoot, moving without aiming, moving while aiming with or without arrows), and since hero's default animations must be "stopped" or "walking", this was the only solution available. I did tried with "hero/tunic1", but it instantly reset to stopped / walking animation when the animation finish, so a set_tunic_sprite_id was the only solution..

This is the sprite used, and as you might see, it take a lot of parameters (including moving, aiming, arming, shooting without any arrow, and same thing, but with arrows)



Quote from: Diarandor on November 05, 2015, 03:02:45 AM
This part of the sprite animation is not trivial at all, and will be easier when we can access to the sprite of the hero in v1.5. I will try to make my own script for this direction fix feature of the bow or shield, maybe this weekend if I get enough time.

I might give a look at the C++ side of on_direction_changed, that might be easier
But it looks like that what Christopho did with the LUA-sided script is that it is a mix with on_position_changed and on_obstacle_reached

Quote from: Diarandor on November 05, 2015, 03:42:23 AM
@Username:
I realized that there are several errors appearing in the black window during the gameplay in your last video. One of them is produced because you do not have a pushing animation in some of your bow sprites.
The important point is that this made me think that, even if we use only 1 sprite for all these animations, we could still have some problem: the hero could be able, maybe, of pushing or pulling blocks while walking while brandishing the bow (if the hero is facing the block, of course), which is not a nice behavior. (We would have the same problem with a scripted shield.)

I do not know how we can avoid this problem, because we cannot disable these features (that is from the engine part). Maybe the only workaround at present would be to use custom entities to make the blocks, which would be fully scripted. But still, if the hero grabs a wall while carrying a bow or shield, he would not move until the action command is released, which is bad.

Another solution would be to allow the functions game:get/set_ability(...) of the engine to have "pushing" and "pulling" as parameters. Do you agree Christopho? I will open an issue for this in github, since this could be a useful feature.

There is a error with the hammer which is easily fix-able and the error appearing while pausing is because I didn't appaired any world to the map, so there is nothing to draw.
Yes, this might be avoidable if there would be any game:set_ability(ability, true/false/nil/value), I think that this is useful, for custom abilities.
#500
Quote from: Diarandor on November 04, 2015, 10:38:03 PM
In your video, it's strange when the hero walks backwards without brandishing the bow... If that is not on purpose there must be something wrong in your code, but I don't know.

You mean when Direction Fix works ?
That was a test using the tunic animation set, i didn't put the direction fix code for the bow, but they do the same issue
I tried to replace the trigger by a temporary savegame variable, same thing occurs

If I test with the bow, the direction fix can be triggered but in a weird way (like the video), but if I press the item input, the direction fix is cancelled, even if the animation set is in the condition

this is the current code, a bit cleaned, but it works the same way too

Code (lua) Select
local function initialize_direction_fix()
local sprite_meta = sol.main.get_metatable("sprite")
function sprite_meta:on_direction_changed()
print("direction changed")
local game = sol.main.game
local hero = game:get_hero()
local tunic = game:get_ability("tunic")
  if  (self:get_animation_set() == "hero/item/bow/bow_arming_arrow_tunic"..tunic)     or
      (self:get_animation_set() == "hero/item/bow/bow_arming_no_arrow_tunic"..tunic)   or
  (self:get_animation_set() == "hero/item/bow/bow_moving_free_tunic"..tunic)       or
  (self:get_animation_set() == "hero/item/bow/bow_moving_no_arrow_tunic"..tunic)   or
      (self:get_animation_set() == "hero/item/bow/bow_moving_with_arrow_tunic"..tunic) or
      (self:get_animation_set() == "hero/item/bow/bow_shoot_tunic1"..tunic)            then
   print("direction is fix !")
       self:set_direction(hero.fixed_direction)
  end
end
end


Tried with Mystery of Solarus, didn't work at all
#502
Okay so now it works ... somehow, it need a tricky way to be triggered by spamming item & sword button, which is ... stange
And it is random

It works better when colliding with a wall, which make this very strange
#503
Quote from: Christopho on November 04, 2015, 01:05:03 PM
In my example I assume that you set hero.fixed_direction to an appropriate value whenever you want to fix the direction. It is up to you to do it.

Keep the self variable, not sprite_meta when calling a function. self is the sprite, sprite_meta is the metatable.

Tried to give a value at hero.fixed_direction when using the bow , same thing happen, it don't work
I might have some idea to fix this, but it looks like that fixed_direction always return nil
#504
hmmm, so I put it in quest_manager and initialized it and tested with tunic1, it doesn't fix direction, and I think that's maybe because hero.fixed_direction doesn't have any value to work with

And if I replace self:get_animation_set by sprite_meta;get_animation_set, I got an error

Error: In on_direction_changed: [string "scripts/quest_manager.lua"]:328: calling 'get_animation_set' on bad self (sol.sprite expected, got table)
#505
Ah I understand, again thanks for you help Diarantor and Christopho, but again, I'm not at home at the moment so i'll post feedbacks later about it ^^
#506
Quote from: Christopho on November 03, 2015, 12:39:06 PM
This is an interesting use case.
You are right, there is no good way to do it without direct access to the hero's sprites. There is an event sprite:on_direction_changed() that would solve the problem.
Sprites of the hero will be accessible in a future release (this is planned for 1.5): https://github.com/christopho/solarus/issues/669

Now... There might actually be a hacky workaround to access hero sprites in 1.4, using metatables. This is advanced stuff :)
The idea is to define the on_direction_changed() event on all sprites, and when this is the sprite of the hero, change its direction.
Something like:
Code (lua) Select

local sprite_meta = sol.main.get_metatable("sprite")
function sprite_meta:on_direction_changed()
  if self:get_animation_set() == "hero/tunic1" then
    local game = sol.main.game
    if game ~= nil then
      local hero = game:get_hero()
      if hero ~= nil and hero.fixed_direction ~= nil and self:get_direction() ~= hero.fixed_direction then
        self:set_direction(hero.fixed_direction)
      end
    end
  end
end

Not tested... Metatables are something global to all instances, so this code should be done at global initialization time, outside of any game or hero (in my games, it goes in scripts/quest_manager.lua). So I am assuming that the current game, if any, is stored globally in sol.main.game. I am also assuming that the direction you want to fix is stored in hero.fixed_direction. You get the idea :) It should work while waiting for 1.5.

I'd test your solution when i'll be at home, so you recommand to programm the function in quest_manager ?
#507
Quote from: Diarandor on November 03, 2015, 01:45:50 AM
I agree, it is very strange what happens. I have a conjecture of what could be the problem, but I am not sure at all.

When you change direction very quickly while moving the hero, maybe the direction of the hero is changing before changing position sometimes, so the direction is updated a bit late, which could be the cause of the problem, but I am not sure of this. I would try to define the event:

function hero:on_movement _changed()
  hero:set_direction(direction)
end

If we are lucky this code might solve the problem...

Otherwise, I don't have any idea of how to solve it or what is producing the problem.

Edit: if we had an event hero:on_direction_changed(), we could use it to change the direction of the hero in that event, which would be the best solution. But there is no such event I think. Also, it is not possible yet to get the hero tunic sprite to define its event on_direction_changed, but it will probably be possible in a future version of solarus, which would allow to solve the problem too.

My theory about this is that on_using need a frame to be triggered by the engine, and since the movement update recall on_using each time an input has changed this might be that, but I don't know how I might fix this.
I don't know much.

Putting on_position and on_obstable in item manager didn't solve this

hero:on_movement_changed() doesn't do a thing, even if I hero is declared as map:get_entity()
#508
Quote from: Diarandor on November 02, 2015, 10:37:28 PM
Ok, I understand now what you are doing. Very interesting to make the hero walk sideways. I don't know what is producing the problem without knowing the rest of the code of the script. This could also be a problem of the engine reseting the direction of the hero.

the code is kinda messy but here you go

the bow item script
Code (lua) Select

function item:on_finished() -- we are destroying the item, reset the hero
local map = game:get_map()
local hero = map:get_hero()
  game:set_ability("tunic", game:get_value("item_saved_tunic"))
  game:set_ability("sword", game:get_value("item_saved_sword"))
  game:set_ability("shield", game:get_value("item_saved_shield"))
  game:set_command_keyboard_binding("action", game:get_value("item_saved_action"))
  game:set_value("bow_state", 0)
  hero:set_walking_speed(88)
  game:set_pause_allowed(true)
  self:set_finished()
end

local function store_equipment()
    local tunic = game:get_ability("tunic")
    game:set_ability("tunic", 1)
    local sword = game:get_ability("sword")
    game:set_ability("sword", 0)
    local shield = game:get_ability("shield")
    game:set_ability("shield", 0)
local kb_action_key = game:get_command_keyboard_binding("action")
game:set_command_keyboard_binding("action", nil)
    game:set_value("item_saved_tunic", tunic)
    game:set_value("item_saved_sword", sword)
    game:set_value("item_saved_shield", shield)
game:set_value("item_saved_action", kb_action_key)
end

-- now, we have pressed it's input, tell the game what to do

function item:on_using()
  local map = game:get_map()
  local hero = map:get_hero()
  local direction_fix = game:get_value("direction_fix") -- first trying to fix the recheck issue then extend the on_position_changed with this condition
  local direction = hero:get_direction()
  local is_cutscene = game:get_value("is_cutscene") -- check if we are in a cutscene, for some special stuffs
 
function hero:on_position_changed()
hero:set_direction(direction)
end

function hero:on_obstacle_reached()
  hero:set_direction(direction)
end

  local bow_state = game:get_value("bow_state")
  local can_fire = game:get_value("can_shoot")
   
function hero:on_position_changed()
hero:set_direction(direction)
end

  if bow_state == 0 then
    game:set_value("item_using", true) -- return if we're using the item
hero:freeze()
game:set_value("direction_fix", true)
store_equipment()
sol.audio.play_sound("common/bars_dungeon")
sol.audio.play_sound("common/item_show")
hero:set_tunic_sprite_id("hero/item/bow/bow_shoot_tunic1")
      sol.timer.start(100, function()
    hero:set_walking_speed(40)
hero:unfreeze()
game:set_value("bow_state", 1)
game:set_pause_allowed(false)
hero:set_tunic_sprite_id("hero/item/bow/bow_moving_free_tunic1")
  end)
  elseif bow_state == 1 then
  if key == "c" and bow_state == 1 and can_fire == false and not game:is_suspended() and not is_cutscene then
    hero:freeze()
sol.audio.play_sound("common/item_show")
hero:set_tunic_sprite_id("hero/item/bow/bow_shoot_tunic1")
      sol.timer.start(100, function()
    hero:set_walking_speed(88)
hero:set_tunic_sprite_id("hero/tunic" .. game:get_value("item_saved_tunic"))
        game:set_ability("tunic", game:get_value("item_saved_tunic"))
        game:set_ability("sword", game:get_value("item_saved_sword"))
        game:set_ability("shield", game:get_value("item_saved_shield"))
game:set_command_keyboard_binding("action", game:get_value("item_saved_action"))
game:set_value("bow_state", 0)
hero:unfreeze()
game:get_item("bow"):set_finished()
  end)
end
end

function shoot_arrow()
      sol.audio.play_sound("/items/bow/shoot")
      self:remove_amount(1)
      local x, y = hero:get_center_position()
      local _, _, layer = hero:get_position()
      local arrow = map:create_custom_entity({
        x = x,
        y = y,
        layer = layer,
        direction = hero:get_direction(),
        model = "arrow",
      })
      arrow:set_force(self:get_force())
      arrow:set_sprite_id(self:get_arrow_sprite_id())
      arrow:go()
end

end


And the parallel script (for input update : item_manager) : check input state when using items by reading it's state, called when a item have a value > 0

code cleaned for the bow, but the same issue happend with the hookshot

Code (lua) Select


function game:on_key_pressed(key)
local map = game:get_map()
local hero = map:get_hero()
-- get the item state
-- can_fire is used by the bow, hookshot and boomerang
local can_fire = game:get_value("can_shoot")
local direction = hero:get_direction()
local direction_fix = game:get_value("direction_fix")
local is_cutscene = game:get_value("is_cutscene")

local bow_state = game:get_value("bow_state")

-- Bow and Arrow
if key == "c" and bow_state == 1 and can_fire == false and not game:is_suspended() and not is_cutscene then -- this one don't need key_press, it just check if the sword button is pressed and then end the bow
    hero:freeze()
sol.audio.play_sound("common/item_show")
hero:set_tunic_sprite_id("hero/item/bow/bow_shoot_tunic1")
      sol.timer.start(100, function()
    hero:set_walking_speed(88)
hero:set_tunic_sprite_id("hero/tunic" .. game:get_value("item_saved_tunic"))
        game:set_ability("tunic", game:get_value("item_saved_tunic"))
        game:set_ability("sword", game:get_value("item_saved_sword"))
        game:set_ability("shield", game:get_value("item_saved_shield"))
game:set_command_keyboard_binding("action", game:get_value("item_saved_action"))
game:set_value("bow_state", 0)
hero:unfreeze()
game:set_pause_allowed(true)
game:get_item("bow"):set_finished()
  end)
 
elseif key == item_assign_key and game:get_item("bow"):get_amount() == 0 and bow_state == 1 and not game:is_suspended() and not is_cutscene then -- Link don't have arrow
    game:set_pause_allowed(false)
    hero:set_tunic_sprite_id("hero/item/bow/bow_arming_no_arrow_tunic1")
  sol.timer.start(50, function()
        sol.audio.play_sound("/items/bow/arming")
    hero:set_tunic_sprite_id("hero/item/bow/bow_moving_no_arrow_tunic1")
    hero:unfreeze()
    game:set_value("can_shoot", true)
    hero:set_walking_speed(28)
  end)
elseif key == item_assign_key and game:get_item("bow"):get_amount() > 0 and bow_state == 1 and not game:is_suspended() and not is_cutscene then -- Link have arrows
    game:set_pause_allowed(false)
hero:set_tunic_sprite_id("hero/item/bow/bow_arming_arrow_tunic1")
  sol.timer.start(50, function()
sol.audio.play_sound("/items/bow/arming")
hero:set_tunic_sprite_id("hero/item/bow/bow_moving_with_arrow_tunic1")
hero:unfreeze()
game:set_value("can_shoot", true)
hero:set_walking_speed(28)
  end)
 
end


function game:on_key_released(key)
local map = game:get_map()
local hero = map:get_hero()
local can_fire = game:get_value("can_shoot")
local direction = hero:get_direction()
local direction_fix = game:get_value("direction_fix")
local is_cutscene = game:get_value("is_cutscene")

local bow_state = game:get_value("bow_state")

-- Bow and Arrows
if key == "x" and bow_state == 1 and game:get_item("bow"):get_amount() == 0 and can_fire == true and not game:is_suspended() and not is_cutscene then
hero:set_tunic_sprite_id("hero/item/bow/bow_shoot_tunic1")
sol.audio.play_sound("/items/bow/no_arrows_shoot")
hero:freeze()
-- can't shoot arrows, but reset to state 1
sol.timer.start(100, function()
    game:set_value("bow_state", 1)
game:set_value("can_shoot", false)
hero:set_walking_speed(40)
hero:set_tunic_sprite_id("hero/item/bow/bow_moving_free_tunic1")
hero:unfreeze()
end)
elseif key == "x" and bow_state == 1 and game:get_item("bow"):get_amount() > 0 and can_fire == true and not game:is_suspended() and not is_cutscene then
hero:set_tunic_sprite_id("hero/item/bow/bow_shoot_tunic1")
shoot_arrow()
hero:freeze()
sol.timer.start(100, function()
game:set_value("bow_state", 1)
game:set_value("can_shoot", false)
hero:unfreeze()
hero:set_walking_speed(40)
hero:set_tunic_sprite_id("hero/item/bow/bow_moving_free_tunic1")
end)

end
end


This is strange, the sword charging doesn't do this, so this is not engine-related i though
#510
Quote from: Diarandor on November 02, 2015, 09:40:50 PM
The event on_position_changed is called every time the position of the hero has changed, so you are changing the direction each time the hero moves. Why? What are you trying to do?

I'm trying to replicate RPG Maker's Direction Fix function especially for some items and functions, it keep the hero "saved" direction and apply this saved direction even if he didn't go to this direction