Carrying custom entities

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

Previous topic - Next topic
September 21, 2015, 01:13:15 AM #15 Last Edit: September 22, 2015, 12:32:09 AM by Diarandor
I forgot to explain about this with details, sorry. The point is that, to show the hero with the carrying animations when carrying a custom entity, the only way is to create a new sprite in the editor (a carrying sprite) for the hero and change it. The stopped and walking animations for this new sprite must be the carrying_stopped and carrying_walking of the normal tunic (probably "tunic1" in your case).

The function to change tunics, from the normal one ("tunic1") to the carrying one ("tunic_carrying1") and vice-versa, is this one, that you have already pasted on your game_manager script, but you will need to modify it a bit to make it compatible with your tunic names:


local hero_tunic_sprites_id = {[1] = "tunic1", [2] = "tunic_carrying1"} -- Tunic names.
function hero_metatable:set_carrying(boolean)
  local i = 0; if boolean then i = 1 end
  self:set_tunic_sprite_id(hero_tunic_sprites_id[i])
end

(I have changed the code in the line where I wrote now "self:set_tunic_sprite_id( ... )". I had written "hero:set_tunic_sprite_id( ... )" instead of "self:set_tunic_sprite_id( ... )", which was not correct.)

If you have several tunics in your game, you need to modify that code above to make the function "hero:set_carrying(boolean)" to display the hero with carrying tunic or normal one. This function is automatically called from the generic_portable.lua script when you lift a custom entity, so don't worry too much about the details. Just make the function above change tunics as I explained, and modify it to adapt it to your tunic names.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 21, 2015, 02:17:03 AM #16 Last Edit: September 21, 2015, 02:23:31 AM by Diarandor
Also, I haven't explained yet the aim of this part of code:

    -- 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
        local x, y, layer = self:get_position()
        self.custom_carry:set_position(x, y+2, layer)
      end
    end

To make a custom entity follow the hero when carried, its position is changed when the event "hero:on_position_changed()" is called. When a custom entity has been lifted by the hero, a reference to that entity is stored in "hero.custom_carry" (this is automatically done in the generic_portable.lua script), so that the function above can move that entity position too.

Note that, by default, custom entities are drawn in Z-order (the creation order), which does not allow to draw the entity above the hero since the hero is drawn in Y-order (an entity with bigger Y-coordinate is drawn above the others with smaller Y-coordinate). In the generic_portable.lua entity, I chose Y-order to drawn a custom entity carried by the hero; and since we position the carried entity using "self.custom_carry:set_position(x, y+2, layer)" (see the function above), the carried entity will be drawn after the hero (above the hero). Obviously, the sprite of the carried entity is shifted with "drawable:set_xy(x,y)" to draw the carried entity in the correct position, which is done in the generic_portable.lua script.

This is a bit technical, but I did not find another workaround and probably there is not another solution to draw the custom entity above the hero (and in the same layer).

If you are already using the event "hero:on_position_changed()" you would need to combine the code above with yours to avoid overriding one function with the other.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 21, 2015, 02:57:35 AM #17 Last Edit: September 21, 2015, 03:04:05 AM by Diarandor
In the "game:on_command_pressed(command)" you have already added:

if attack_effect == "custom_carry" then
  -- THIS IS NEEDED FOR THE GENERIC_PORTABLE.LUA SCRIPT!!!!
  game:get_hero().custom_carry:throw(); return true
end

Add this line before the code above (I omited it by mistake):

local attack_effect = game:get_custom_command_effect("attack")

Just to make it more clear, you will have inside the function "game:on_command_pressed(command)" something like:

  -- Deal with attack command.
  if command == "attack" then
    local attack_effect = game:get_custom_command_effect("attack")
    if attack_effect == "custom_carry" then
      game:get_hero().custom_carry:throw(); return true
    end
    -- Maybe more code here (in case you had some code). DELETE THIS LINE
  end

The code above makes the hero throw the carried custom entity when pressing the attack button. You can modify the code to do it with the action button instead, or with both the attack and action buttons.
"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, 01:21:55 AM #18 Last Edit: September 22, 2015, 01:29:52 AM by wrightmat
What I guess I don't understand is why we need an entirely different tunic animation set just for this script? This will make implementing into other people's project much more difficult. Can't hero:set_carrying() just use hero:set_animation("carrying_stopped") that already exists in the default tunic?

On another note, I'm still not getting a HUD action icon or the ability to throw once the object is picked up (with no error). Actually, it appears that the action icon is broken entirely - it will "flip" when interacting with something, but doesn't show an actual icon.

I committed the changes thus far to my repository, so you can take a look at it if you'd like.

Using "hero:set_animation("carrying_stopped")" won't work because the engine will automatically change to the "walking" animation when you walk and not the "carrying_walking", and the same with "stopped".
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Another thing you will need: the sprites for the shadow of the thrown entity (I am not using the default one), and also the sprites to destroy the entity when falling on holes/water/lava (a falling effect or a splash). I have put them in
https://github.com/Diarandor/portable_entities/tree/master/sprites/things
Copy the files ground_effects.dat and ground_effects.png to your sprite folder (you can change them later for your own sprites).

(The sprite for the shadow is created in the function "entity:on_throw()" and for the other effects in the function "entity:check_on_ground()". You may need this if you change your sprites name/folder.)
"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, 01:32:17 AM #21 Last Edit: September 22, 2015, 01:45:03 AM by Diarandor
It is very strange that the hud icon flips and shows nothing. What I get is the word "lift" written in the hud. Can you try to lift the entity and throw it?

EDIT: I have put the hud.lua, action_icon.lua and attack_icon.lua scripts in my repository. If the hud is still not working, try to use temporarily my scripts and tell me what you get.
"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, 01:44:38 AM #22 Last Edit: September 22, 2015, 01:47:49 AM by wrightmat
I can lift it, but not throw it.

It turns out that both effects_indexes[attack_icon.effect_displayed] and effects_indexes[action_icon.effect_displayed] are nil when there should be an effect attached to them. Maybe this is being overwritten somewhere?

EDIT: set_custom_command_effect() is called at several points, but I don't see that function anywhere in your repository or the code you posted. That might be the culprit?

Yes, that may be the problem. I have this in the game_manager.lua script:
  local custom_command_effects = {}
  -- Returns the current customized effect of the action or attack command.
  -- nil means the built-in effect.
  function game:get_custom_command_effect(command)
    return custom_command_effects[command]
  end
  -- Overrides the effect of the action or attack command.
  -- Set the effect to nil to restore the built-in effect.
  function game:set_custom_command_effect(command, effect)
    custom_command_effects[command] = effect
  end

I thought you had it, but I think I was wrong. You will need it to paste it in the game manager.
"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, 02:11:03 AM #24 Last Edit: September 22, 2015, 02:14:37 AM by wrightmat
My attack icon is back, but I still have no action icon and still can't throw the object.

On an unrelated note, I can successfully change the walking animation of the hero while carrying (using my existing tunic1.dat) by changing the animation here:

  function hero_metatable:on_position_changed()
    if self.custom_carry then
      self:set_animation("carrying_walking")
      local x, y, layer = self:get_position()
      self.custom_carry:set_position(x, y+2, layer)
    end
  end

Now to just figure out where to change the stopped animation!

September 22, 2015, 02:17:27 AM #25 Last Edit: September 22, 2015, 02:21:17 AM by Diarandor
I didn't thought on changing the animation in that event (I thought that the animation would be restarted to the initial frame when the hero changes position). If that works then we will not need to create the new carrying sprite for the hero. That's a great improvement, thanks!!!

EDIT: Ok, as you say it will not be so easy because we still have problems with the stopped animation which is changed by the engine. So maybe we are not getting rid of the new tunic after all...  :o

EDIT2: I didn't say it, but with the code I use, the item is thrown with the attack button (I keep the action button to allow talking while carrying something). Have you tried to throw the item with the attack button?
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

So I missed it, get/set_custom_command_effects is in my scripts/hud/hud.lua file (similar file to zsdx). The difference is the line if self.hud ~= nil then before the command is added. Leaving this in gives me my attack icon back, taking it out takes it away. It doesn't seem to change the action icon.

EDIT: Yes, I've tried to throw with both the attack and action button. Plus my attack icon doesn't change to indicate anything but my sword.

September 22, 2015, 02:27:04 AM #27 Last Edit: September 22, 2015, 02:36:35 AM by Diarandor
Try to use my hud scripts temporarily (hud, action_icon and attack_icon), I put them in https://github.com/Diarandor/portable_entities/tree/master/scripts/hud
Just to see if it works. There may be some differences in the code of these three scripts.

EDIT: we have a problem with the hud. That may be what is obstructing the throw of the entity. But part of the problem could also be in the function "on_command_pressed()". Maybe this code is not nested correctly there:


  if command == "attack" then
      local attack_effect = game:get_custom_command_effect("attack")
      if attack_effect == "custom_carry" then
        game:get_hero().custom_carry:throw(); return true
      end
  end

This bunch of code is what starts the throwing function of the carried entity (in generic_portable.lua). Maybe it's not being executed that part of code, but I am not sure.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Or maybe the best solution is that you create a github repository and put the data there and I will try to find what is not working. Sorry for the trouble.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Sound missing: "item_fall". I changed it to "throw" for now.

After the throw is complete (the item has landed) the hero freezes, with no error message.