Carrying custom entities

Started by Diarandor, July 27, 2015, 05:07:47 AM

Previous topic - Next topic
September 22, 2015, 02:50:26 AM #30 Last Edit: September 22, 2015, 02:56:54 AM by Diarandor
"item_fall" is the sound for the bounces (you can use the one of the bomb, I think it is "bomb").
The hero is frozen in the throw function (in generic_portable.lua) and unfrozen when the throwing animation of the hero has finished. Something is not working correctly. The unfreeze is called in as this callback:

  hero:set_animation("throw", function()
    hero:set_animation("stopped"); hero:set_invincible(false); hero:unfreeze()
  end)

so maybe the problem is that the "throw" animation has not finished (does it have an end?).

EDIT: Ok, the problem is that there is not a default throw animation (I created one for my heroes but there is not one for Link). Just create one, and the code may work then.

EDIT 2: the "throw" animation has to be in the normal tunic ("tunic1"), not the carrying one.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

I have added some sounds to my repository: item_fall.ogg, falling_on_hole.ogg and splash.ogg.
You can use them (I created them so they are free to use).
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

I had already changed the "throw" animation in that line to my "grabbing" animation, which has only 1 frame but does not loop. I thought that should end right away, is that not the case? Do I need an animation with more than one frame?

The grabbing animation has frame delay 0 and only one frame, so maybe it has no ending, but I am not sure at all. Try to use an animation with nonzero frame delay, several frames (and without loop, obviously). That could work.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

I just did a timer instead, for my purposes. The throw now completes correctly and control is returned to the player.

On the plus side, everything seems to work with the HUD scripts you provided!!!

For my game, I intend to add back my custom HUD elements to the new script first. Then I'd like to modify the script to utilize the action button instead of the attack button. And finally, I hope to figure out how to change the carrying stopped animation :)

September 22, 2015, 03:18:27 AM #35 Last Edit: September 22, 2015, 03:26:26 AM by Diarandor
That's good news. I will explain to you other day how to customize generic_portable entities without modifying the generic_portable.lua script. So that you can have a different bouncing sound for different portable entities, etc. I use the script generic_portable.lua as a base script for all very different portable entities, so it is important not to modify it (maybe not so important if you use only one type of those entities in your game). I will also explain how to use the save_between_maps.lua script (not so hard as what we have done) to save position of some of these entities when left in some map (this could be used to simulate the metal ball of Link's awakening). But that's all for today.

Anyway, have you thrown the entity to a hole, water or lava? Just test it and tell me if it works.

EDIT: do not carry the entity to other map or you will get a crash. I will explain how to make that work too, don't worry (that's also part of the save_between_maps.lua script). We have finished for today.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

I realized that, since you have already added the save_between_maps.lua script to your game_manager script, maybe it's already working the feature that allows carrying the custom entity to another map.  ;D
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Sounds great - thanks!

I had tried to move to another map carrying the object, and it did crash. It appears that throwing onto holes and such does work.

One question - is there a way to have the entity actually be thrown? Right now the hero essentially drops the object at his feet, but it'd like to get some distance.

To use the carrying stopped animation, I think that the only solution is to use the second tunic (the carrying one). For each different tunic you will need to create another one for the carrying animations. You would only need to modify a bit the function "hero_metatable:set_carrying(boolean)" to make it compatible with the three tunics of Link, which is really easy.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 22, 2015, 04:05:14 AM #39 Last Edit: September 22, 2015, 04:11:30 AM by Diarandor
Quote from: wrightmat on September 22, 2015, 03:55:25 AM
Sounds great - thanks!

I had tried to move to another map carrying the object, and it did crash. It appears that throwing onto holes and such does work.

One question - is there a way to have the entity actually be thrown? Right now the hero essentially drops the object at his feet, but it'd like to get some distance.

-Ok, we will have to solve the crash you have, do you get some error?
-Yes. When I throw the entity while walking, the entity does not fall on the hero's foot, it is thrown away instead in the direction of the hero. But you need the hero to be walking. In that case, the entity is thrown in the direction of the hero. Isn't that working correctly? Or you mean that you want it to be always thrown away? In that case, you would need to make a very small change in the entity:throw() function of generic_portable.lua. You would need to change the line:

local dx, dy = 0, 0; if animation == "walking" then dx, dy = math.cos(direction*math.pi/2), -math.sin(direction*math.pi/2) end

with the following instead:

local dx, dy = math.cos(direction*math.pi/2), -math.sin(direction*math.pi/2)


EDIT: Ok, I just figured out what's happening. The point is that you are changing the animation when walking in the hero_metatable:on_position_changed(), and I am not doing that, because I use the second tunic and the animation I have is the walking one. That's why you cannot throw it away.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

If you want the entity to fall away when walking and on hero's foot when stopped, you have two solutions:
-The first one is to do what I do: use the second tunic, and that's all.
-The second solution: modify the entity:throw() function and write:

local dx, dy = 0, 0; if animation == "carrying_walking" then dx, dy = math.cos(direction*math.pi/2), -math.sin(direction*math.pi/2) end

instead of

local dx, dy = 0, 0; if animation == "walking" then dx, dy = math.cos(direction*math.pi/2), -math.sin(direction*math.pi/2) end

But with the second solution you will still have the problem that the carrying_stopped animation is not used!!!
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Yeah, that makes sense and the change worked. I'll figure out the carrying_stopped thing eventually :)

No error on the crash, but I'll look at it more tomorrow.

I think I know why you get a crash, which could be due to that another piece of code is needed to create again the carried entity in the new map and allow to use the save_between_maps.lua script. (We will need to use the events map:on_created() and map:on_finished() for that purpose.) When you have time I will explain how.

I know you have your things to do and you are working very hard in your game, so take your time and you will tell me when we can continue debugging this. There is no haste.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 23, 2015, 02:07:58 AM #43 Last Edit: September 23, 2015, 02:50:51 AM by wrightmat
I can work on it whenever. I'm reconsidering using it in my game (because I'm thinking of using a different miniboss), but will happily continue to work out the bugs!

I've almost gotten the carrying tunic problem fixed! The approach I have now almost entirely works, but the engine momentarily switched to the regular stopped_with_shield animation for a split second, which looks a little weird. There may still be a way to get around this, but I haven't figured it out yet.


local function initialize_hero()
  -- Modify metatable of hero to make carried entities follow him with hero:on_position_changed().
  local hero_metatable = sol.main.get_metatable("hero")
  function hero_metatable:on_position_changed()
    if self.custom_carry then
      sol.timer.start(self, 10, function()
        if self:get_animation() == "stopped" or self:get_animation() == "stopped_with_shield" then self:set_animation("carrying_stopped") end
      end)
      self:set_animation("carrying_walking")
      local x, y, layer = self:get_position()
      self.custom_carry:set_position(x, y+2, layer)
    end
  end

  function hero_metatable:set_carrying(boolean)
    if boolean then self:set_animation("carrying_stopped") end
  end
end

This code is not exactly what I have. It is simpler but untested.

If a custom_entity is close to the border of the map, the custom_command_action (used for "custom_lift") may be not reseted to nil when the hero changes map. To avoid this, I use the line "game:set_custom_command_effect("action", nil)" in this code.

Also, we notify the save_between_maps.lua script to create a custom entity being carried if there is some. (So here we are loading the already saved information in the previous map.)


  -- Function called when the player goes to another map.
  function game:on_map_changed(map) 
    -- Notify the HUD and hero manager(some HUD elements need to know that).
    hud:on_map_changed(map)
    game:set_custom_command_effect("action", nil) -- Reset. To avoid problems with custom_interactions.lua.
    game.save_between_maps:load_map(map) -- Create saved and carried entities.
  end


On the other hand, in some part of the game manager (maybe in game:on_started()) you must use this code, to save the carried custom entities and reload them in the new map.  (So here we are saving some information to reload it in the next map.)


  local map_metatable = sol.main.get_metatable("map")
  function map_metatable:on_finished()
    game.save_between_maps:save_map(self)
  end


Tell me which errors you get with this.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."