How to give a custom item the ability to "cut" a destructible

Started by oHInsane, January 23, 2017, 12:09:05 AM

Previous topic - Next topic
Hi,

My learning is on a good way thanks to your various helps.

I have another question.

I have created a rake, but I need it the ability to cut a brush (a destructible with can_be_cut set to true).
The rake will eventually deal damage to enemy and cut thoses brushes.

I'm also trying to learn more about usable items this way, here is the code of my item "rake"





-- rateau.lua
local item = ...
local game = item:get_game()

function item:on_using()
  -- some code
  local entities_touched = { }
  rateau:set_origin(4, 5)
  rateau:add_collision_test("overlapping", function(rateau, entity)
  local nom_entite = entity:get_name()
  if(nom_entite == "plantation")then
    local sprite = "entities/bush_green"
      entity:create_sprite(sprite)
      entity:set_animation("destroy")
  end 
-- some code

So my idea is basically to detect if a collision is occuring between my "rateau" (rake) and the bush.
If the collided entity goes by the "plantation" name, then i want to start the bush destroyed sprite animation.

So with this code i have this error:
Error: In collision callback: [string "items/rateau.lua"]:39: attempt to call method 'create_sprite' (a nil value)

If I understand correctly it means my entity can't use the create_sprite animation.

I think i miss the methodology of doing this type of stuff. For the moment i'm thinking like this:
1) test colllision
2) get the entity that is collided
3) start the cut animation if it's a brush.

But It raises questions: the callbacck from the collision test is allowing me to access the "targeted entity". But how do I test if it's a destructible brush. I can test the "destructible" part with the get_type() function (instead of get_name() which force me to list and give one unique name for each damned brush on the map).
And why do I have an error on the create_sprite() function when i try to start the destroy animation of the brush.

Thanks



-Maybe we should ask Christopho to add a new function "destructible:cut()". Otherwise, you should remove the destructible and create a custom entity to simulate the cutting animation.
-You get an error because the function "create_sprite" is not defined for all types of entities (only enemies and custom entities have that function).
-Don't use the name to detect bushes, that is a very bad way to do that. You can get the associated sprite and check if its "id" is the one of a bush. If you want to do this for all cuttable destructibles (also for non-bushes), then just check if they have the property of being cuttable with "get_can_be_cut()".

Edit: as a workaround you can define the function "cut()" for the destructible metatable, so that all your bushes can be cut with that function. You can create a custom entity or something similar to show the cutting animation.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Quote from: Diarandor on January 23, 2017, 03:38:34 AM
-Maybe we should ask Christopho to add a new function "destructible:cut()". Otherwise, you should remove the destructible and create a custom entity to simulate the cutting animation.
-You get an error because the function "create_sprite" is not defined for all types of entities (only enemies and custom entities have that function).
-Don't use the name to detect bushes, that is a very bad way to do that. You can get the associated sprite and check if its "id" is the one of a bush. If you want to do this for all cuttable destructibles (also for non-bushes), then just check if they have the property of being cuttable with "get_can_be_cut()".

Edit: as a workaround you can define the function "cut()" for the destructible metatable, so that all your bushes can be cut with that function. You can create a custom entity or something similar to show the cutting animation.

I agree, but it can be simpler.

"plantation" is a name, but I do guess that every entity with the name plantation share the same animation set, which can be simpler, just calling entity:get_sprite():set_animation(destroy) and then erase the entity is a simpler thing I did for the custom sword I'm currently working on.

Thanks for your answers, it solved my problem.

My final code is:



  rateau:add_collision_test("overlapping", function(rateau, entity)
  if( entity:get_sprite()~=nil) then
   
    local nom_sprite = entity:get_sprite():get_animation()
    if(nom_sprite == "on_ground")then
        local coords_x, coords_y, coords_layer = entity:get_position()
        local brush_explosed = map:create_custom_entity{
          x = coords_x,
          y = coords_y,
          layer = layer,
          width = 8,
          height = 8,
          direction = 0,
        }   
        -- on affiche l'animation de destruction     
        local brush_sprite= brush_explosed:create_sprite("entities/bush_green")
        brush_sprite:set_animation("destroy")
        -- on remove le sprite du brush
        entity:remove()

    end 
  end


I'll check later how i want this item to interact with ennemies and other entites but for the moment, it's usable as it is.

Yes, MetalZelda is right, that is much simpler. I would call the line "entity:remove()" in the event "on_animation_finished" of the sprite (or in a timer) because otherwise the animation will not be shown, which I think is what happens with your current code. The only difference of doing this without a custom entity is that the falling leaves will not be traversable (I prefer to make them traversable, that is why I recommended the other way), but this are just subtle details.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."