Carrying custom entities

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

Previous topic - Next topic
I have created this post just to talk about the scripts I made to allow carrying custom entities (not working correctly yet), just in case someone is interested. A conversation about this was started here:
http://forum.solarus-games.org/index.php/topic,297.0.html
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Ok! I'll check Christopher's log later on to see what changes are gonna be implemented in 1.4.3. So far the program is amazing and ideas are pouring in so quickly it's overwhelming. So I can't wait to see what he'll continue implementing in future releases.

Hi! My scripts are now working perfectly with Solarus bugfix 1.4.3, thanks to Christopho. (The shadows of my custom entities of type generic_portable, which can be carried, are now removed without crash after falling on the ground.) Some of you could use these scripts as a workaround until the day that the engine will allow to carry custom entities (if you are successful in understanding my code to modify and simplify it, which is not easy).

I have updated my repository with some new scripts and updated old ones in: https://github.com/Diarandor/
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."


August 15, 2015, 07:51:13 PM #4 Last Edit: August 15, 2015, 07:52:58 PM by Diarandor
However, my code is still not very clean and some functions are missing (to allow carry items to another map, for instance, but I am working on it). Another problem is that I have several scripts interacting (one of them is the one I use to switch between the three main heroes), so the code is a bit spread and not very usable for other people, unless you modify it a lot. Currently, I am improving/simplifying the code, and making the scripts more independent, so maybe other people could use the script. (If I get something more useful for others, I will add it to the LibSolarusMudora repository.)
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Hi! I want to make this script usable for other people, so I'm gonna simplify my script (which has unnecessary features for other people). I'd like to put it in the libsolarus-mudora repository when it is ready, so other quest makers can use it for their games.

@wrightmat :
Are you interested in these scripts to carry custom entities? If so and you have some free time, I ask for your help, mainly as a tester, but also to improve the explanation comments of the scripts (which may be a bit unclear at present) and give some suggestions to improve the code. If you agree, I will send you a simplified version of it as soon as I can (a simplified version of the one of my repository), maybe this week. I will explain to you what needs to be done to make it work. We can talk by email if you prefer.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

I might be able to use it in my game - I was thinking about swapping out one of my minibosses for Smasher from Link's Awakening, that would require picking up a large metal ball and throwing it at the enemy to do damage.

Even if I don't use it for my game, I'm happy to test and provide whatever feedback I can!

Cool. I will notify you when I have it ready, in a few days (it's almost ready but I need to make a few more changes in my code).
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

September 19, 2015, 01:19:10 AM #8 Last Edit: September 19, 2015, 01:21:23 AM by Diarandor
I have added you as a collaborator in my repository (I think I did it correctly but not sure), its here:
https://github.com/Diarandor/portable_entities

First, add these scripts to your data scripts folder:
1) collision_test_manager.lua
2) custom_interactions.lua
3) save_between_maps.lua
and the following to the (custom) entities scripts folder:
4) generic_portable.lua

The script (4) is the main one. As first step, create a custom entity in the map editor with this script in some map (and put some 16x16 sprite on it). It is necessary to create an animation set for the hero to make him carry the entity.

We need to add some things to your game_manager script (see the notes in my game_manager script in the repository to know where to add these parts of code). Add these lines:

-- First

sol.main.load_file("scripts/custom_interactions.lua")(game)
sol.main.load_file("scripts/collision_test_manager.lua")(game)

-- Second

    -- 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
    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
      hero:set_tunic_sprite_id(hero_tunic_sprites_id[i])
    end

--Third (this will be harder). In the event "function game:on_command_pressed(command)", add the two parts of code I say in the code:

        local action_effect = game:get_custom_command_effect("action")
        -- Custom action effects.
        if action_effect and game:get_interaction_entity() then
         game:get_hero().custom_interaction:on_custom_interaction(); return true
        end

and

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


You will get some errors at first. I will help you to solve them and make it work. (Note that I had some parts of the code mixed with other scripts so we may have some problems at present.) Let me know what you get in the error.txt.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

The custom_interactions.lua is used to detect the entity and notify the hud that the hero can lift the entity (we may need to add something to the hud script). It works adding a collision test created with collision_test_manager.lua (this script allows to add/remove only one collision test, which is useful to remove the lifting-detection collision test after the entity has been lifted and add it again when the entity has fallen to the ground).

We will deal later with the save_between_maps.lua (not so important for now), which will allow to save position in a map for what I call independent entities. Forget about this script for now.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

I followed the instructions you posted here exactly, so keep that in mind as we debug :)

Look like you'll definitely need to add something to the HUD - I picked the object up and the action icon disappeared from the HUD and I was not able to throw it.  Here's each error line and the line it references:

Error: In on_animation_finished: [string "scripts/hud/action_icon.lua"]:65: attempt to perform arithmetic on a nil value
    self.icon_region_y = 24 * effects_indexes[self.effect_displayed]

Error: In on_animation_finished: [string "scripts/hud/attack_icon.lua"]:63: attempt to perform arithmetic on a nil value
      self.icon_region_y = 24 * effects_indexes[self.effect_displayed]

Error: In hero animation callback: [string "scripts/quest_manager.lua"]:163: attempt to index global 'hero' (a nil value)
    hero():set_tunic_sprite_id(hero_tunic_sprites_id)        changed to:
    self:get_game():get_hero():set_tunic_sprite_id(hero_tunic_sprites_id)

September 20, 2015, 04:58:38 PM #11 Last Edit: September 20, 2015, 05:01:55 PM by Diarandor
-The last error was my fault (I had that part of code in my hero_manager.lua script, to choose the tunic depending on the hero I had, and I didn't test the simplified new code which was new and untested). It should work with your change.

-For the two first errors, first try with the code I have in my scripts:
in the action_icon.lua I have this function:

  function action_icon:compute_icon_region_y()

    local y
    if action_icon.effect_displayed ~= nil then
      -- Create an icon with the name of the current effect.
      local effects_indexes = {
        ["validate"] = 1,
        ["next"] = 2,
        ["info"] = 3,
        ["return"] = 4,
        ["look"] = 5,
        ["open"] = 6,
        ["action"] = 7,
        ["lift"] = 8,
        ["throw"] = 9,
        ["grab"] = 10,
        ["stop"] = 11,
        ["speak"] = 12,
        ["change"] = 13,
        ["swim"] = 14,
["talk"] = 12,
["custom_lift"] = 8,
["custom_carry"] = nil,
        ["custom_jump"] = nil,
      }
      if effects_indexes[action_icon.effect_displayed] ~= nil then
        action_icon.icon_region_y = 24 * effects_indexes[action_icon.effect_displayed]
      end
    end
  end

and in the attack_icon.lua I have this function like this:

  function attack_icon:compute_icon_region_y()

    if attack_icon.effect_displayed ~= nil or not game:is_dialog_enabled() then
      if attack_icon.effect_displayed == nil then
        -- Show an empty icon.
        attack_icon.icon_region_y = 0
      elseif attack_icon.effect_displayed == "sword" then
        -- Create an icon with the current sword.
        attack_icon.icon_region_y = 96 + 24 * attack_icon.sword_displayed
      elseif attack_icon.effect_displayed ~= nil then
        -- Create an icon with the name of the current effect.
        local effects_indexes = {
          ["save"] = 1,
          ["return"] = 2,
          ["validate"] = 3,
          ["skip"] = 4,
  ["custom_carry"] = 5,
          ["custom_jump"] = nil,
        }
        if effects_indexes[attack_icon.effect_displayed] ~= nil then
          attack_icon.icon_region_y = 24 * effects_indexes[attack_icon.effect_displayed]
        end
      end
    end
  end


Tell me what you get with these new changes when you have time to test again. We are getting close to make it work (when we make the hud work, the rest will be a piece of cake).
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Now the hero disappears.


Error: Cannot find quest file 'sprites/tunic1.dat'
Fatal: Invalid direction 2 for sprite 'tunic1' in animation 'stopped_with_shield'
Error: In hero animation callback: [string "scripts/quest_manager.lua"]:163: Internal error: Invalid direction 2 for sprite 'tunic1' in animation 'stopped_with_shield'
Fatal: Invalid direction 3 for sprite 'tunic1' in animation 'stopped_with_shield'


I believe that should be 'sprites/hero/tunic1.dat' (at least in my quest is would be), but I'm not sure where in the code it's referring.

Yes, you right. Just change the tunic of the hero to the new tunic (used for lifting custom entities).
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

I don't understand - I need a whole new tunic for this? I didn't see anything in the repository.