[Solved] Create a custom switch

Started by SyF, April 05, 2017, 03:40:30 PM

Previous topic - Next topic
April 05, 2017, 03:40:30 PM Last Edit: April 06, 2017, 09:47:46 AM by SyF
Hi everyone,
I would like to create a custom switch. In fact, I have an idea but I prefer ask if there is a better way to script it.
This is my idea: The hero throws a boomerang and activate the switch (which keeps the item). After the switch animation, the boomerang returns to the hero and something happens (for example, opening a door).

I already create a custom entity for the switch and it works when I throw my boomerang. Now, I need to indicate in the game that this custom entity is a switch, because I want to use the function "switch:on_activated" and the other.

Does someone have an idea ?

----------------------------------------------------
Switch code :
Code (lua) Select

local entity = ...

function entity:on_created()
  entity:set_size(32, 24)
  entity:set_origin(16, 21)
  entity:set_traversable_by(false)
  entity:set_drawn_in_y_order(true)
end

entity:add_collision_test("touching", function(entity, other_entity)

  local type = other_entity:get_type()
  local switch_state = entity:get_sprite():get_animation()
    local check = type == "boomerang" and switch_state == "stop_off"

  if check then
    entity:get_sprite():set_animation("activated")
    sol.timer.start(1000, function()
      sol.audio.play_sound("secret")
      entity:get_sprite():set_animation("stop_on")
      entity:clear_collision_tests()
      end)
  end
end)

States :
  # stop_off : the switch is not activated
  # activated : the switch is beins activated (loop animation)
  # stop_on : the switch is activated and unusable

Boomerang code:
Code (lua) Select

local item = ...

function item:on_created()
  item:set_savegame_variable("possession_boomerang")
  item:set_assignable(true)
end

function item:on_using()
  local hero = item:get_map():get_hero()
  hero:start_boomerang(64,160,"boomerang","entities/boomerang")
end


switch:on_activated() won't be called by the engine ever because your entity is of type "custom_entity" and not "switch".
But in your entity:add_collision_test callback, you can manually call a function of your choice if it exists. You can call it on_activated, just like for built-in switches, or something different.
Code (lua) Select

sol.timer.start(1000, function()
  sol.audio.play_sound("secret")
  if entity.on_activated ~= nil then
    entity:on_activated()
  end
  ...
[code]
As you can see, switches could actually be reimplemented in Lua as custom entities.

April 05, 2017, 09:51:00 PM #2 Last Edit: April 07, 2017, 03:28:21 AM by Zefk
@Christopho
That is interesting, so a simple step switch would be like this:

Code ( lua) Select
local hero = map:get_hero()

--Create on_activated
sol.timer.start(500, function()
  if entity.on_activated ~= nil then
    entity:on_activated()
return true
  end
end)

--if hero's position is equal to entity's position, then hero is damaged when stepping on entity.
function entity:on_activated()
local x1,y1 = hero:get_position()
local x2,y2 = entity:get_position()
print("Entity: "..x2..","..y2)
print("Hero: "..x1..","..y1)
  if x1 == x2 and y1 == y2 then
    sol.audio.play_sound("secret")
    hero:start_hurt(240,277,6)
  end
end


Although, it will be hard to get the hero exactly on the point without doing some manual range calculations.

Code ( lua) Select
--if hero's position is equal to entity's position, then hero is damaged when stepping on entity.
function entity:on_activated()
local x1,y1 = hero:get_position()
print("Hero: "..x1..","..y1)
  if (x1 > 240 and x1 < 256) and (y1 > 272 and y1 < 288) then
    sol.audio.play_sound("secret")
    hero:start_hurt(240,277,6)
  end
end


The easiest way to do this is by using the overlap function.

Code ( lua) Select
function entity:on_activated()
  if hero:overlaps(entity) then
    sol.audio.play_sound("secret")
    hero:start_hurt(240,277,6)
  end
end

Ahah okay  ;D
Thanks you Christopho and Zefk !

April 07, 2017, 01:00:05 AM #4 Last Edit: April 07, 2017, 03:29:43 AM by Zefk
I edited my example above to be a working example, but it only works for the exact point and it might be some time before the hero walks on that exact point unless you manually calculate the range.


It might be easier to use the overlap function because there is no need for calculations.

Code ( lua) Select
sol.timer.start(400, function()
  if entity.on_activated ~= nil then
    entity:on_activated()
return true
  end
end)

function entity:on_activated()
  if hero:overlaps(entity) then
    sol.audio.play_sound("secret")
    hero:start_hurt(240,277,6)
  end
end