Solarus-Games English Forum

Solarus => Development => Topic started by: Zaidyer on February 14, 2017, 10:53:12 PM

Title: Separator_on_activated direction4
Post by: Zaidyer on February 14, 2017, 10:53:12 PM
I'm trying to force the player to get moved into a room after a separator has finished scrolling towards South.

Code (lua) Select
function sub_separator_h:on_activated(3)
-- slide down.
  local hero = self:get_game():get_hero()
  sol.audio.play_sound("explosion")
 
  -- Create movement.
  local dir = 3
    hero:freeze()
  local m = sol.movement.create("straight")
  m:set_speed(90)
  m:set_angle(dir*math.pi/2)
  m:set_max_distance(32)
  m:start(hero)
  function m:on_obstacle_reached()
    hero:unfreeze()
  end
  function m:on_finished()
    hero:unfreeze()
  end
end


But it causes this error:

QuoteError: Failed to load script 'maps/testlevel': [string "maps/testlevel.lua"]:41: <name> or '...' expected near '3'
Line 41 is the beginning of the script here. The documentation for Separators suggests "on_activated(direction4)" only needs a number referring to the proper direction (in this case South), but I don't know how to write it so it won't throw this error.
Title: Re: Separator_on_activated direction4
Post by: Diarandor on February 14, 2017, 11:35:05 PM
The "direction4" parameter has to be a variable, not a value. (The value is stored in that variable when the engine automatically calls the event.) That is why you get the error.
Title: Re: Separator_on_activated direction4
Post by: YoshiMario2000 on February 14, 2017, 11:44:45 PM
Like Diarandor said, direction4 is a variable, here is how to use it. (This was typed before Diarandor's post had appeared.)

The function of separators "on_activated(direction4)" The information in the brackets are defined when they are called and should be stored in a variable like so:
Code (lua) Select
function generic_separator:on_activated(direction4)
  if direction4 == 3 then
  -- Your code here
  end
end

The reason this works is because when the engine calls this function, it stores the argument that you may need for a script in the variable.

However, one cannot have what they want the call back to be done like so,
Code (lua) Select
function generic_separator:on_activated(3)
  --Your code here
end

This does not work as putting the number three in the variable slot will produce an error as that slot is not for defining what you want that information to be, but rather for a variable that may change.
Title: Re: Separator_on_activated direction4
Post by: Diarandor on February 14, 2017, 11:59:42 PM
Sorry, I was too quick. :-X
But you explained it much better. :)
Title: Re: Separator_on_activated direction4
Post by: Zaidyer on February 19, 2017, 02:27:16 AM
I've integrated my door slider into separator_manager.lua so that it can be used in dungeons.

But something unexpected is happening. With this addition, enemies prefixed with auto_enemy are no longer reset. They're simply erased. Strangely, everything else is reset just fine.

Code (lua) Select
-- This script restores entities when there are separators in a map.
-- When taking separators prefixed by "auto_separator", the following entities are restored:
-- - Enemies prefixed by "auto_enemy".
-- - Destructibles prefixed by "auto_destructible".
-- - Blocks prefixed by "auto_block".
--
-- Usage from a map script:
-- local separator_manager = require("maps/lib/separator_manager.lua")
-- separator_manager:manage_map(map)
-- If you prefer, you can also enable it automatically on all maps from game:on_map_changed().

local separator_manager = {}

function separator_manager:manage_map(map)

  local enemy_places = {}
  local destructible_places = {}
  local game = map:get_game()
  local zelda = map:get_entity("zelda")

  -- Function called when a separator was just taken.
  local function separator_on_activated(separator)

    local hero = map:get_hero()

    -- Enemies.
    for _, enemy_place in ipairs(enemy_places) do
      local enemy = enemy_place.enemy

      -- First remove any enemy.
      if enemy:exists() then
        enemy:remove()
      end

      -- Re-create enemies in the new active region.
      if enemy:is_in_same_region(hero) then
        local old_enemy = enemy_place.enemy
        local enemy = map:create_enemy({
          x = enemy_place.x,
          y = enemy_place.y,
          layer = enemy_place.layer,
          breed = enemy_place.breed,
          direction = enemy_place.direction,
          name = enemy_place.name,
        })
        enemy:set_treasure(unpack(enemy_place.treasure))
        enemy.on_dead = old_enemy.on_dead  -- For door_manager.
        enemy_place.enemy = enemy
      end
    end

    -- Blocks.
    for block in map:get_entities("auto_block") do
      -- Reset blocks in regions no longer visible.
      if not block:is_in_same_region(hero) then
        block:reset()
      end
    end

  end

  -- Function called when a separator is being taken.
  local function separator_on_activating(separator)


    local hero = map:get_hero()

    -- Enemies.
    if not map.used_separator then
      -- First separator: remove enemies from other regions like on_activated() does.
      -- Because on_activated() was not called when the map started.
      for _, enemy_place in ipairs(enemy_places) do
        local enemy = enemy_place.enemy
        if enemy:exists() and not enemy:is_in_same_region(hero) then
          enemy:remove()
        end
      end
    end

    -- Destructibles.
    for _, destructible_place in ipairs(destructible_places) do
      local destructible = destructible_place.destructible

      if not destructible:exists() then
        -- Re-create destructibles in all regions except the active one.
        if not destructible:is_in_same_region(hero) then
          local destructible = map:create_destructible({
            x = destructible_place.x,
            y = destructible_place.y,
            layer = destructible_place.layer,
            name = destructible_place.name,
            sprite = destructible_place.sprite,
            destruction_sound = destructible_place.destruction_sound,
            weight = destructible_place.weight,
            can_be_cut = destructible_place.can_be_cut,
            can_explode = destructible_place.can_explode,
            can_regenerate = destructible_place.can_regenerate,
            damage_on_enemies = destructible_place.damage_on_enemies,
            ground = destructible_place.ground,
          })
          -- We don't recreate the treasure.
          destructible_place.destructible = destructible
        end
      end
    end
  end


  for separator in map:get_entities("auto_separator") do
    separator.on_activating = separator_on_activating
    separator.on_activated = separator_on_activated

    --door slider
    function separator:on_activated(direction4)
        if direction4 == 0 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 0
          hero:freeze()
          local m2 = sol.movement.create("straight")
          m2:set_speed(90)
          m2:set_angle(dir*math.pi/2)
          m2:set_max_distance(32)
          m2:start(hero)
          hero:set_animation(heroanim)
          function m2:on_obstacle_reached()
            hero:unfreeze()
          end
          function m2:on_finished()
            hero:unfreeze()
          end
        end
        if direction4 == 1 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 1
          hero:freeze()
          local m2 = sol.movement.create("straight")
          m2:set_speed(90)
          m2:set_angle(dir*math.pi/2)
          m2:set_max_distance(24)
          m2:start(hero)
          hero:set_animation(heroanim)
          function m2:on_obstacle_reached()
            hero:unfreeze()
          end
          function m2:on_finished()
            hero:unfreeze()
          end
        end
        if direction4 == 2 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 2
          hero:freeze()
          local m2 = sol.movement.create("straight")
          m2:set_speed(90)
          m2:set_angle(dir*math.pi/2)
          m2:set_max_distance(32)
          m2:start(hero)
          hero:set_animation(heroanim)
          function m2:on_obstacle_reached()
            hero:unfreeze()
          end
          function m2:on_finished()
            hero:unfreeze()
          end
        end
        if direction4 == 3 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 3
          hero:freeze()
          local m = sol.movement.create("straight")
          m:set_speed(500)
          m:set_angle(dir*math.pi/2)
          m:set_max_distance(32)
          m:start(hero)
          hero:set_animation(heroanim)
          function m:on_obstacle_reached()
            hero:unfreeze()
          end
          function m:on_finished()
            local dir = 3
            local m2 = sol.movement.create("straight")
            m2:set_speed(90)
            m2:set_angle(dir*math.pi/2)
            m2:set_max_distance(16)
            m2:start(hero)
            hero:set_animation(heroanim)
            function m2:on_obstacle_reached()
              hero:unfreeze()
            end
            function m2:on_finished()
              hero:unfreeze()
            end
          end
        end
    end

  end

  for separator in map:get_entities("sub_separator") do

    --door slider
    function separator:on_activated(direction4)
        if direction4 == 0 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 0
          hero:freeze()
          local m2 = sol.movement.create("straight")
          m2:set_speed(90)
          m2:set_angle(dir*math.pi/2)
          m2:set_max_distance(32)
          m2:start(hero)
          hero:set_animation(heroanim)
          function m2:on_obstacle_reached()
            hero:unfreeze()
          end
          function m2:on_finished()
            hero:unfreeze()
          end
        end
        if direction4 == 1 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 1
          hero:freeze()
          local m2 = sol.movement.create("straight")
          m2:set_speed(90)
          m2:set_angle(dir*math.pi/2)
          m2:set_max_distance(24)
          m2:start(hero)
          hero:set_animation(heroanim)
          function m2:on_obstacle_reached()
            hero:unfreeze()
          end
          function m2:on_finished()
            hero:unfreeze()
          end
        end
        if direction4 == 2 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 2
          hero:freeze()
          local m2 = sol.movement.create("straight")
          m2:set_speed(90)
          m2:set_angle(dir*math.pi/2)
          m2:set_max_distance(32)
          m2:start(hero)
          hero:set_animation(heroanim)
          function m2:on_obstacle_reached()
            hero:unfreeze()
          end
          function m2:on_finished()
            hero:unfreeze()
          end
        end
        if direction4 == 3 then
          local hero = self:get_game():get_hero()
          local heroanim = hero:get_animation()
          hero:set_animation(heroanim)
          local dir = 3
          hero:freeze()
          local m = sol.movement.create("straight")
          m:set_speed(500)
          m:set_angle(dir*math.pi/2)
          m:set_max_distance(32)
          m:start(hero)
          hero:set_animation(heroanim)
          function m:on_obstacle_reached()
            hero:unfreeze()
          end
          function m:on_finished()
            local dir = 3
            local m2 = sol.movement.create("straight")
            m2:set_speed(90)
            m2:set_angle(dir*math.pi/2)
            m2:set_max_distance(16)
            m2:start(hero)
            hero:set_animation(heroanim)
            function m2:on_obstacle_reached()
              hero:unfreeze()
            end
            function m2:on_finished()
              hero:unfreeze()
            end
          end
        end
    end
  end

  -- Store the position and properties of enemies.
  for enemy in map:get_entities("auto_enemy") do
    local x, y, layer = enemy:get_position()
    enemy_places[#enemy_places + 1] = {
      x = x,
      y = y,
      layer = layer,
      breed = enemy:get_breed(),
      direction = enemy:get_sprite():get_direction(),
      name = enemy:get_name(),
      treasure = { enemy:get_treasure() },
      enemy = enemy,
    }
  end

  local function get_destructible_sprite_name(destructible)
    -- TODO the engine should have a destructible:get_sprite() method.
    -- As a temporary workaround we use the one of custom entity, fortunately
    -- it happens to work for all types of entities.
    local sprite = sol.main.get_metatable("custom_entity").get_sprite(destructible)
    return sprite ~= nil and sprite:get_animation_set() or ""
  end

  -- Store the position and properties of destructibles.
  for destructible in map:get_entities("auto_destructible") do
    local x, y, layer = destructible:get_position()
    destructible_places[#destructible_places + 1] = {
      x = x,
      y = y,
      layer = layer,
      name = destructible:get_name(),
      treasure = { destructible:get_treasure() },
      sprite = get_destructible_sprite_name(destructible),
      destruction_sound = destructible:get_destruction_sound(),
      weight = destructible:get_weight(),
      can_be_cut = destructible:get_can_be_cut(),
      can_explode = destructible:get_can_explode(),
      can_regenerate = destructible:get_can_regenerate(),
      damage_on_enemies = destructible:get_damage_on_enemies(),
      ground = destructible:get_modified_ground(),
      destructible = destructible,
    }
  end

end

return separator_manager