init.lua 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. -- Author: MustTest/BluebirdGreycoat51/GoldFireUn
  2. -- License: MIT
  3. if not minetest.global_exists("bone_mark") then bone_mark = {} end
  4. bone_mark.modpath = minetest.get_modpath("bone_mark")
  5. bone_mark.players = bone_mark.players or {}
  6. local STEP_TIME = 3.5
  7. local BONE_NEAR_DIST = 3
  8. local BONE_FAR_DIST = 100
  9. local CORPSE_MISSING_TIME = 120
  10. function bone_mark.add_corpse(pos, pname)
  11. bone_mark.players[pname] = bone_mark.players[pname] or {}
  12. local t = bone_mark.players[pname]
  13. t[#t + 1] = {
  14. pos = vector.round(pos),
  15. shown = false,
  16. hud = nil,
  17. remove = false,
  18. timer = 0,
  19. }
  20. end
  21. local function keep_mark(t)
  22. if not t.remove then
  23. return true
  24. end
  25. end
  26. function bone_mark.notify_hud_update_needed(pname)
  27. step_timer = STEP_TIME
  28. local pdata = bone_mark.players[pname]
  29. if pdata then
  30. -- pref should *usually* never be nil, but check for it anyway for edge cases.
  31. local pref = minetest.get_player_by_name(pname)
  32. if pref then
  33. for index, mdata in ipairs(pdata) do
  34. if mdata.hud then pref:hud_remove(mdata.hud) end
  35. mdata.hud = nil
  36. mdata.shown = false
  37. end
  38. end
  39. end
  40. end
  41. local step_timer = 0
  42. function bone_mark.on_globalstep(dtime)
  43. step_timer = step_timer + dtime
  44. if step_timer < STEP_TIME then return end
  45. step_timer = 0
  46. for pname, pdata in pairs(bone_mark.players) do
  47. -- pdata is an array.
  48. for index, mdata in ipairs(pdata) do
  49. -- pref should never be nil, because we remove player's data from the main
  50. -- player-table when they leave the game. Check anyway for edge cases.
  51. local pref = minetest.get_player_by_name(pname)
  52. if not pref then
  53. goto continue
  54. end
  55. local ppos = pref:get_pos()
  56. local node = minetest.get_node_or_nil(mdata.pos)
  57. local message = "Corpse"
  58. if node and node.name ~= "bones:bones" then
  59. message = "Corpse Missing"
  60. mdata.timer = (mdata.timer or 0) + STEP_TIME
  61. -- Missing bones HUD element timeout.
  62. if mdata.timer > CORPSE_MISSING_TIME then
  63. if mdata.hud then pref:hud_remove(mdata.hud) end
  64. mdata.hud = nil
  65. mdata.remove = true
  66. end
  67. -- Update HUD element right away.
  68. if not mdata.corpse_gone then
  69. if mdata.hud then pref:hud_remove(mdata.hud) end
  70. mdata.hud = nil
  71. mdata.shown = false
  72. mdata.corpse_gone = true
  73. end
  74. end
  75. local far_dist = BONE_FAR_DIST
  76. if passport.player_has_key(pname, pref) then
  77. far_dist = BONE_FAR_DIST * 10
  78. end
  79. local same_realm = rc.same_realm(mdata.pos, ppos)
  80. if not mdata.remove then
  81. local dist = vector.distance(ppos, mdata.pos)
  82. if not mdata.shown then
  83. if dist > BONE_NEAR_DIST and dist <= far_dist and same_realm then
  84. -- Show waypoint if player in range.
  85. -- Just in case, but this probably shouldn't happen.
  86. if mdata.hud then pref:hud_remove(mdata.hud) end
  87. -- http://www.shodor.org/~efarrow/trunk/html/rgbint.html
  88. local number = "6368886"
  89. local precision = 0
  90. if passport.player_has_key(pname, pref) then
  91. precision = 10
  92. end
  93. mdata.hud = pref:hud_add({
  94. hud_elem_type = "waypoint",
  95. name = message,
  96. number = number,
  97. world_pos = mdata.pos,
  98. precision = precision,
  99. })
  100. mdata.shown = true
  101. end
  102. elseif mdata.shown then
  103. -- Hide waypoint when player too far or too near.
  104. if dist > far_dist or not same_realm then
  105. if mdata.hud then pref:hud_remove(mdata.hud) end
  106. mdata.hud = nil
  107. mdata.shown = false
  108. elseif dist < BONE_NEAR_DIST and pref:get_hp() > 0 then
  109. -- Remove waypoint when player near enough and NOT dead.
  110. -- Need the HP check because otherwise waypoint would be removed
  111. -- right away if player doesn't press respawn quickly enough.
  112. if mdata.hud then pref:hud_remove(mdata.hud) end
  113. mdata.hud = nil
  114. mdata.remove = true
  115. end
  116. end
  117. end -- If not to be removed.
  118. ::continue::
  119. end
  120. -- Get rid of dead ones.
  121. utility.array_remove(pdata, keep_mark)
  122. end
  123. end
  124. function bone_mark.on_leaveplayer(pref)
  125. local pname = pref:get_player_name()
  126. bone_mark.players[pname] = nil
  127. end
  128. if not bone_mark.registered then
  129. minetest.register_globalstep(function(...)
  130. return bone_mark.on_globalstep(...)
  131. end)
  132. minetest.register_on_leaveplayer(function(...)
  133. return bone_mark.on_leaveplayer(...)
  134. end)
  135. local c = "bone_mark:core"
  136. local f = bone_mark.modpath .. "/init.lua"
  137. reload.register_file(c, f, false)
  138. bone_mark.registered = true
  139. end