one enemy works, but two not...

Started by Yosha, October 01, 2015, 09:37:49 AM

Previous topic - Next topic
Hello, I have a problem with an enemy I made. I 've done a Skulltula (like in OoT) falling from the ceiling, turning, etc... and after many days of coding, I finished it. It works as I would, but when I adding a second Skulltula, both of them doesn't work! I had the same problem when I made custom wizzrobe (before the release of ROTH, otherwise I didn't lost my time on it) and I've solved it somehow, but I don't remember how today! I think it's a problem with "self", but not sure! Here is the code. (And if it can help some dev to make a skulltula!)
Code ( lua) Select
local enemy = ...

-- Skulltula :

local fallen = false
local vulnerable = false

local shadow_x, shadow_y, shadow_z = enemy:get_position()
local m = sol.movement.create("straight")

local angle = math.pi/2
local angle_inverse = 3*math.pi/2

function enemy:on_created()
   self:set_life(4)
     self:set_damage(2)
     self:set_optimization_distance(160)
     self:set_size(16, 16)
     self:set_origin(8, 13)
   self:set_can_attack(false)
   self:set_pushed_back_when_hurt(false)
   self:set_attack_consequence("sword", "custom")
     self:set_attack_consequence("hookshot", "ignored")
     self:set_attack_consequence("boomerang", "ignored")
   self:set_attack_consequence("explosion", "ignored")
   self:set_obstacle_behavior("flying")
      self:set_layer_independent_collisions(true)
   sprite = self:create_sprite("enemies/skulltula")   
end

function enemy:on_restarted()
   if not fallen then
          sprite:set_animation("shadow")
      self:check_hero()
   else
      self:turning()   
     end     
end

function enemy:check_hero()
     local hero = self:get_map():get_entity("hero")
     local x, y, z = self:get_position()
     local hero_x, hero_y, hero_z = hero:get_position()
     
   if self:get_distance(hero) <= 32 then
      local direction = self:get_direction4_to(hero)
        sprite:set_direction(direction)
      if direction == 0 then
         angle = 2*math.pi/2
         angle_inverse = 0
      end
      if direction == 1 then
         angle = 3*math.pi/2
         angle_inverse = math.pi/2
      end
      if direction == 2 then
         angle = 0
         angle_inverse = 2*math.pi/2
      end
      if direction == 3 then
         angle = math.pi/2
         angle_inverse = 3*math.pi/2
      end
      self:falling()   
   end

     sol.timer.stop_all(self)
     sol.timer.start(self, 500, function() self:check_hero() end)
end

function enemy:falling()
   sol.audio.play_sound("jump")   
   sprite:set_animation("walking")
   self:set_position(shadow_x, shadow_y - 120, 2)
   self:set_can_attack(true)
   m:set_speed(320)
   m:set_angle(3*math.pi/2)
   m:set_max_distance(120)
   m:start(self)   
end

function enemy:on_movement_finished()
   if fallen == false then
      fallen = true
      self:set_position(shadow_x, shadow_y, shadow_z)
      self:restart()
   end   
end

function enemy:turn_anim()
   if vulnerable == false then
      sprite:set_animation("vulnerable")
      vulnerable = true
   else
      sprite:set_animation("walking")
      vulnerable = false
   end
end

function enemy:turning()
   sol.timer.start(self, 2000, function()          -- Shaking
      if vulnerable == false then   
         sprite:set_animation("shaking") 
      else
         sprite:set_animation("vulnerable_shaking")
      end
      sol.timer.start(self, 2000, function()       -- Turning
         self:turn_anim()
           sol.timer.start(self, 2000, function() self:turning() end)
      end)
   end)
end

function enemy:on_custom_attack_received(attack, sprite)
   if fallen == true then
      m:set_angle(angle)
      m:set_speed(128)
            m:start(self)
      sol.timer.start(self, 200, function()
         m:set_angle(angle_inverse)
         sol.timer.start(self, 400, function()
            m:set_angle(angle)
            sol.timer.start(self, 200, function() m:stop() end)
         end)
      end)
      if vulnerable == false then
         sol.audio.play_sound("sword_tapping")   
      else
         sprite:set_animation("hurt")
         sol.audio.play_sound("enemy_hurt")
         self:remove_life(1)   
         sol.timer.start(self, 200, function() self:turn_anim() end)
      end
   end
end

You forgot to declare sprite as a local variable to the script. Therefore, it is a global variable shared by all skulltulas.

Bugs that appear as soon as there are two instances of the same script are typically this kind of error.

Ok! I knew it was just a little mistake like that, but I didn't figure what! What a dumb I am ! Well, thank you for this help and another question : what do you think about the code, is there a way to improve it, or I just let it like that ?

Hard to say, it is quite long, but nothing shocked me when reading it quickly :)