Author Topic: Enemies slowing down as they take damage?  (Read 94 times)

Max

  • Full Member
  • ***
  • Posts: 137
    • View Profile
Enemies slowing down as they take damage?
« on: July 18, 2018, 08:01:22 pm »
So, I'm designing a boss who basically runs away from the hero, but I have a really weird problem. Every time he takes damage, he gets a bit slower until he stops moving altogether.

Here's the part of the script that controls his movement:

Code: Lua
  1. function enemy:check_hero()
  2.   --teleport
  3. --  if enemy:get_distance(hero) < 75 and can_teleport == true then enemy:teleport() end --the boss teleports if you get too close
  4.  
  5.   if not teleporting then --teleporting has a movement and we don't want the movements to conflict
  6.     local hero_angle = enemy:get_angle(hero) --gets angle toward hero
  7.     local mov_angle = hero_angle + math.pi --the angle opposite of the hero
  8.     enemy:stop_movement()
  9.     local m = sol.movement.create("straight")
  10.     m:set_angle(mov_angle)
  11.     m:set_speed(80)
  12.     m:set_max_distance(0)
  13.     m:set_smooth(true)
  14.     m:start(enemy)
  15.   end
  16.   sol.timer.start(100, function() enemy:check_hero() end)
  17. end
  18.  

I figure that has got to be that part of the script that's causing the slowdown, but I can post the whole thing at the bottom of this post. Anyway, anybody have any idea what might be causing this? In the mean time, I'm going to try using some movement other than straight and see if that helps things.

UPDATE: it does not help things. Here's what I changed the movement to:

Code: Lua
  1. function enemy:check_hero()
  2.   --teleport
  3. --  if enemy:get_distance(hero) < 75 and can_teleport == true then enemy:teleport() end --the boss teleports if you get too close
  4.  
  5.   if not teleporting then --teleporting has a movement and we don't want the movements to conflict
  6.     local dir_hero = enemy:get_direction8_to(hero)
  7.     dir_hero = (dir_hero + 4) if dir_hero > 7 then dir_hero = dir_hero - 8 end
  8.     enemy:stop_movement()
  9.     local m = sol.movement.create("path")
  10.     m:set_path({dir_hero})
  11.     m:set_loop()
  12.     m:set_speed(75)
  13.     m:start(enemy)
  14.  
  15.   end
  16.   sol.timer.start(100, function() enemy:check_hero() end)
  17. end
  18.  

This does not prevent him from slowing down, and it also makes him get stuck on like, any corner. The diagonal walls don't seem to work like I'd expect them to, pushing the enemy around. But his slowing down every time he takes damage is the main thing. This hasn't happened with any other enemy.



The whole script:
Code: Lua
  1. local enemy = ...
  2. local game = enemy:get_game()
  3. local map = enemy:get_map()
  4. local hero = map:get_hero()
  5. local sprite
  6. local teleporting = false
  7. local can_teleport = true
  8. local teleport_frequency = 10000
  9.  
  10. function enemy:on_created()
  11.   sprite = enemy:create_sprite("enemies/" .. enemy:get_breed())
  12.   enemy:set_life(100)
  13.   enemy:set_damage(1)
  14.   enemy:set_attack_consequence("explosion", "protected")
  15.   enemy:set_hurt_style("boss")
  16. end
  17.  
  18. function enemy:on_restarted()
  19.   enemy:check_hero()
  20. end
  21.  
  22. function enemy:on_movement_changed(movement)
  23.   local direction4 = movement:get_direction4()
  24.   local sprite = self:get_sprite()
  25.   sprite:set_direction(direction4)
  26. end
  27.  
  28. function enemy:check_hero()
  29.   --teleport
  30. --  if enemy:get_distance(hero) < 75 and can_teleport == true then enemy:teleport() end --the boss teleports if you get too close
  31.  
  32.   if not teleporting then --teleporting has a movement and we don't want the movements to conflict
  33.     local hero_angle = enemy:get_angle(hero) --gets angle toward hero
  34.     local mov_angle = hero_angle + math.pi --the angle opposite of the hero
  35.     enemy:stop_movement()
  36.     local m = sol.movement.create("straight")
  37.     m:set_angle(mov_angle)
  38.     m:set_speed(80)
  39.     m:set_max_distance(1)
  40.     m:set_smooth(true)
  41.     m:start(enemy)
  42.   end
  43.   sol.timer.start(100, function() enemy:check_hero() end)
  44. end
  45.  
  46. function enemy:teleport()
  47.   enemy:set_attack_consequence("sword", "protected") --while he's preparing to teleport, he's invincible
  48.   enemy:set_attack_consequence("arrow", "protected")
  49.   teleporting = true
  50.   can_teleport = false --we don't want him to teleport again right away
  51.   sol.timer.start(teleport_frequency, function() can_teleport = true end) --when he can teleport again (in 10 seconds)
  52.   enemy:stop_movement()
  53.   sprite:set_animation("charging", function()
  54.     local x, y, layer = enemy:get_position()
  55.     map:create_explosion({ x = x, y = y, layer = layer})
  56.     sol.audio.play_sound("explosion")
  57.     sprite:set_animation("teleporting")
  58.     local t = sol.movement.create("straight")
  59.     local telang = enemy:get_angle(480, 240)
  60.     t:set_angle(telang)
  61.     t:set_speed(200)
  62.     t:set_smooth()
  63.     t:set_max_distance(180)
  64.     t:start(enemy)
  65.     sol.timer.start(1500, function()
  66.       x, y, layer = enemy:get_position()
  67.       map:create_explosion({ x = x, y = y, layer = layer})
  68.       sol.audio.play_sound("explosion")
  69.       enemy:set_attack_consequence("sword", 1)
  70.       enemy:set_attack_consequence("arrow", 1)
  71.       sprite:set_animation("walking")
  72.       enemy:check_hero()
  73.       teleporting = false
  74.     end) --end of after teleporting timer
  75.  
  76.   end) --end of after charging animation
  77. end
  78.  
« Last Edit: July 18, 2018, 08:10:32 pm by Max »

Christopho

  • Administrator
  • Hero Member
  • *****
  • Posts: 1123
    • View Profile
Re: Enemies slowing down as they take damage?
« Reply #1 on: July 18, 2018, 09:42:34 pm »
Your timer has no explicit context:
Code: Lua
  1. sol.timer.start(100, function() enemy:check_hero() end)
  2.  
So by default, it belongs to the map. Which means that every time the enemy is hurt, the timer is *not* canceled (as it would be if the context was the enemy), so after the enemy restarts a new timer is created and the previous ones are still active. So check_hero is called more and more often, and apparently that stops and restarts a movement all the time.

Use the enemy as context:
Code: Lua
  1. sol.timer.start(enemy, 100, function() enemy:check_hero() end)
  2.  

Unrelated remark: you can return true in the timer callback to repeat it automatically instead of creating a new timer. This will simplify the code. (I guess you used an old ZSDX enemy script that was written before this feature (< Solarus 1.2) :)).
« Last Edit: July 18, 2018, 09:44:06 pm by Christopho »

Max

  • Full Member
  • ***
  • Posts: 137
    • View Profile
Re: Enemies slowing down as they take damage?
« Reply #2 on: July 18, 2018, 11:03:54 pm »
Oh, duh! Thanks, I totally forgot about context. I'll try that as soon as I get home.

Max

  • Full Member
  • ***
  • Posts: 137
    • View Profile
Re: Enemies slowing down as they take damage?
« Reply #3 on: July 19, 2018, 08:27:47 am »
That worked! Thanks, Christopho. I'll post the code for anyone interested in an enemy that runs away from you, and/or teleports via explosions. The only problem is that they hardcore get stuck in corners, even sloped corners. I'll have to figure out a workaround for this. Maybe once I have him tossing bombs at the hero, the dodging you'd have to do to avoid damage would cause the hero to move in such a way that he wouldn't get stuck, but I don't know.

Code: Lua
  1. local enemy = ...
  2. local game = enemy:get_game()
  3. local map = enemy:get_map()
  4. local hero = map:get_hero()
  5. local sprite
  6. local teleporting = false
  7. local can_teleport = true
  8. local teleport_frequency = 10000
  9.  
  10. function enemy:on_created()
  11.   sprite = enemy:create_sprite("enemies/" .. enemy:get_breed())
  12.   enemy:set_life(100)
  13.   enemy:set_damage(1)
  14.   enemy:set_attack_consequence("explosion", "protected")
  15.   enemy:set_hurt_style("boss")
  16. end
  17.  
  18. function enemy:on_restarted()
  19.   enemy:check_hero()
  20. end
  21.  
  22. function enemy:on_movement_changed(movement)
  23.   local direction4 = movement:get_direction4()
  24.   local sprite = self:get_sprite()
  25.   sprite:set_direction(direction4)
  26. end
  27.  
  28. function enemy:check_hero()
  29.   --teleport
  30.   if enemy:get_distance(hero) < 75 and can_teleport == true then enemy:teleport() end --the boss teleports if you get too close
  31.  
  32.   if not teleporting then --teleporting has a movement and we don't want the movements to conflict
  33.     local hero_angle = enemy:get_angle(hero) --gets angle toward hero
  34.     local mov_angle = hero_angle + math.pi --the angle opposite of the hero
  35.     enemy:stop_movement()
  36.     local m = sol.movement.create("straight")
  37.     m:set_angle(mov_angle)
  38.     m:set_speed(80)
  39.     m:set_max_distance(0)
  40.     m:set_smooth(true)
  41.     m:start(enemy)
  42.   end
  43.   sol.timer.start(enemy, 100, function() enemy:check_hero() end)
  44. end
  45.  
  46. function enemy:teleport()
  47.   enemy:set_attack_consequence("sword", "protected") --while he's preparing to teleport, he's invincible
  48.   enemy:set_attack_consequence("arrow", "protected")
  49.   teleporting = true
  50.   can_teleport = false --we don't want him to teleport again right away
  51.   sol.timer.start(map, teleport_frequency, function() can_teleport = true end) --when he can teleport again (in 10 seconds)
  52.   enemy:stop_movement()
  53.   sprite:set_animation("teleport_charge", function()
  54.     local x, y, layer = enemy:get_position()
  55.     map:create_explosion({ x = x, y = y, layer = layer})
  56.     sol.audio.play_sound("explosion")
  57.     sprite:set_animation("teleporting")
  58.     local t = sol.movement.create("straight")
  59.     local telang = enemy:get_angle(480, 240)
  60.     t:set_angle(telang)
  61.     t:set_speed(200)
  62.     t:set_smooth()
  63.     t:set_max_distance(180)
  64.     t:start(enemy)
  65.     sol.timer.start(enemy, 1500, function()
  66.       x, y, layer = enemy:get_position()
  67.       map:create_explosion({ x = x, y = y, layer = layer})
  68.       sol.audio.play_sound("explosion")
  69.       enemy:set_attack_consequence("sword", 1)
  70.       enemy:set_attack_consequence("arrow", 1)
  71.       sprite:set_animation("walking")
  72.       enemy:check_hero()
  73.       teleporting = false
  74.     end) --end of after teleporting timer
  75.  
  76.   end) --end of after charging animation
  77. end
  78.  
  79.