flight.lua 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. local flight_secs = minetest.settings:get("ethereal.flightpotion_duration") or (5 * 60)
  2. local timer_check = 5 -- seconds per check
  3. local S = ethereal.intllib
  4. local is_50 = minetest.has_feature("object_use_texture_alpha")
  5. local function get_timer(user)
  6. if not user then return end
  7. if is_50 then
  8. local meta = user:get_meta()
  9. if not meta then return "" end
  10. return meta:get_string("ethereal:fly_timer") or ""
  11. else
  12. return user:get_attribute("ethereal:fly_timer") or ""
  13. end
  14. end
  15. local function has_fly(name)
  16. return minetest.get_player_privs(name).fly
  17. end
  18. local function set_timer(user, timer)
  19. if is_50 then
  20. local meta = user:get_meta() ; if not meta then return end
  21. meta:set_string("ethereal:fly_timer", timer)
  22. else
  23. user:set_attribute("ethereal:fly_timer", timer)
  24. end
  25. end
  26. local function set_flight(user, set)
  27. local name = user and user:get_player_name() ; if not name then return end
  28. local privs = minetest.get_player_privs(name)
  29. privs.fly = set
  30. minetest.set_player_privs(name, privs)
  31. -- when flight removed set timer to temp position
  32. if set ~= true then
  33. set_timer(user, "-99")
  34. end
  35. end
  36. -- after function
  37. local function ethereal_set_flight(user)
  38. local name = user and user:get_player_name() ; if not name then return end
  39. local timer = tonumber(get_timer(user)) or 0
  40. -- if timer ran out then remove 'fly' privelage
  41. if timer <= 0 and timer ~= -99 then
  42. set_flight(user, nil)
  43. return
  44. end
  45. local privs = minetest.get_player_privs(name)
  46. -- have we already applied 'fly' privelage?
  47. if not privs.fly then
  48. set_flight(user, true)
  49. end
  50. -- handle timer
  51. timer = timer - timer_check
  52. -- show expiration message and play sound
  53. if timer <= 10 then
  54. minetest.chat_send_player(name,
  55. minetest.get_color_escape_sequence("#ff5500")
  56. .. S("Flight timer about to expire!"))
  57. minetest.sound_play("default_dig_dig_immediate",
  58. {to_player = name, gain = 1.0}, true)
  59. end
  60. -- set updated timer
  61. set_timer(user, timer)
  62. -- restart checks
  63. minetest.after(timer_check, function()
  64. ethereal_set_flight(user)
  65. end)
  66. end
  67. -- on join / leave
  68. minetest.register_on_joinplayer(function(player)
  69. -- wait 2 seconds before doing flight checks on player
  70. minetest.after(2.0, function(player)
  71. -- get player name and timer
  72. local name = player and player:get_player_name() ; if not name then return end
  73. local timer = get_timer(player)
  74. -- if timer is blank and player can already fly then default and return
  75. if timer == "" and has_fly(name) then
  76. set_timer(player, "-99")
  77. return
  78. end
  79. timer = tonumber(timer) or 0
  80. -- if timer is set to default then return
  81. if timer == -99 then
  82. return
  83. end
  84. -- if we got this far and player is flying then start countdown check
  85. if has_fly(name) then
  86. minetest.after(timer_check, function()
  87. ethereal_set_flight(player)
  88. end)
  89. end
  90. end, player)
  91. end)
  92. -- potion item
  93. minetest.register_node("ethereal:flight_potion", {
  94. description = S("Flight Potion"),
  95. drawtype = "plantlike",
  96. tiles = {"ethereal_flight_potion.png"},
  97. inventory_image = "ethereal_flight_potion.png",
  98. wield_image = "ethereal_flight_potion.png",
  99. paramtype = "light",
  100. sunlight_propagates = true,
  101. walkable = false,
  102. selection_box = {
  103. type = "fixed",
  104. fixed = {-0.2, -0.37, -0.2, 0.2, 0.31, 0.2}
  105. },
  106. groups = {dig_immediate = 3},
  107. sounds = default.node_sound_glass_defaults(),
  108. on_use = function(itemstack, user, pointed_thing)
  109. -- get privs
  110. local name = user:get_player_name()
  111. local privs = minetest.get_player_privs(name)
  112. local timer = get_timer(user)
  113. if privs.fly then
  114. local msg = timer
  115. if timer == "" or timer == "-99" then
  116. msg = S("unlimited")
  117. end
  118. minetest.chat_send_player(name,
  119. minetest.get_color_escape_sequence("#ffff00")
  120. .. S("Flight already granted, @1 seconds left!", msg))
  121. return
  122. end
  123. -- set flight timer
  124. set_timer(user, flight_secs)
  125. -- show time remaining
  126. minetest.chat_send_player(name,
  127. minetest.get_color_escape_sequence("#1eff00")
  128. .. S("Flight granted, you have @1 seconds!", flight_secs))
  129. -- start check
  130. ethereal_set_flight(user)
  131. -- take item
  132. itemstack:take_item()
  133. -- return empty bottle
  134. local inv = user:get_inventory()
  135. if inv:room_for_item("main", {name = "vessels:glass_bottle"}) then
  136. user:get_inventory():add_item("main", "vessels:glass_bottle")
  137. else
  138. minetest.add_item(user:get_pos(), {name = "vessels:glass_bottle"})
  139. end
  140. return itemstack
  141. end
  142. })
  143. -- recipe
  144. minetest.register_craft({
  145. output = "ethereal:flight_potion",
  146. recipe = {
  147. {"ethereal:etherium_dust", "ethereal:etherium_dust", "ethereal:etherium_dust"},
  148. {"ethereal:etherium_dust", "ethereal:fire_dust", "ethereal:etherium_dust"},
  149. {"ethereal:etherium_dust", "vessels:glass_bottle", "ethereal:etherium_dust"}
  150. }
  151. })