items.lua 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. --------------------------------------------------------------------------------
  2. -- Special item that lets you revive a dead player in-place, provided they have
  3. -- not pressed the "respawn" button. Remember gents, there's no such thing as
  4. -- "dead". There's only "mostly dead" and "mostly dead" means "slightly alive"!
  5. local function scepter_revive_player(tref, tname, pname, pos)
  6. if pos then
  7. rc.notify_realm_update(tref, pos)
  8. tref:set_pos(pos)
  9. end
  10. preload_tp.spawn_spinup_particles(tref:get_pos(), 1)
  11. ambiance.sound_play("nether_portal_usual", tref:get_pos(), 1.0, 30)
  12. local hp_max = pova.get_active_modifier(tref, "properties").hp_max
  13. tref:set_hp(hp_max, {reason="revive"})
  14. minetest.close_formspec(tname, "") -- Close the respawn formspec.
  15. ambiance.sound_play("default_cool_lava", tref:get_pos(), 1.0, 32)
  16. minetest.chat_send_player(pname, "# Server: You revived <" .. rename.gpn(tname) .. ">.")
  17. minetest.chat_send_player(tname, "# Server: You were revived by <" .. rename.gpn(pname) .. ">.")
  18. end
  19. local function scepter_hit_bones(itemstack, user, pt)
  20. --minetest.log('scepter hit bones')
  21. -- Collect information.
  22. local pname = user:get_player_name()
  23. local pos = pt.under
  24. local node = minetest.get_node(pos)
  25. local meta = minetest.get_meta(pos)
  26. local owner = meta:get_string("owner")
  27. local tref = minetest.get_player_by_name(owner)
  28. local bones_death_time = tonumber(meta:get_string("death_time")) or 0
  29. ambiance.sound_play("nether_extract_blood", pos, 1.0, 30)
  30. -- Player must be logged in.
  31. if not tref or not tref:is_player() then
  32. --minetest.log('ghost not logged in')
  33. return
  34. end
  35. -- Player must be dead.
  36. if tref:get_hp() > 0 then
  37. --minetest.log('ghost not dead')
  38. return
  39. end
  40. local tname = tref:get_player_name()
  41. local player_meta = tref:get_meta()
  42. local player_death_time = tonumber(player_meta:get_string("last_death_time")) or 0
  43. local player_bones_time = tonumber(player_meta:get_string("last_bones_time")) or 0
  44. local player_bones_pos = minetest.string_to_pos(player_meta:get_string("last_bones_pos"))
  45. local player_respawn_time = tonumber(player_meta:get_string("last_respawn_time")) or 0
  46. -- Determine if player can be revived from these bones.
  47. -- Time must be valid.
  48. if bones_death_time == 0 or player_death_time == 0 or player_bones_time == 0 then
  49. --minetest.log('times not valid')
  50. return
  51. end
  52. -- Player's last bones position must be known.
  53. if not player_bones_pos then
  54. --minetest.log('bone pos not valid')
  55. return
  56. end
  57. -- Bones time must match player's last death time.
  58. if bones_death_time ~= player_death_time then
  59. --minetest.log('death times don\'t match')
  60. return
  61. end
  62. -- Bones position must match player's last bones position.
  63. if not vector.equals(pos, player_bones_pos) then
  64. --minetest.log('bone positions don\'t match')
  65. return
  66. end
  67. -- Player's last respawn must be prior to their last death time.
  68. if player_respawn_time >= player_death_time then
  69. --minetest.log('respawn time too soon')
  70. return
  71. end
  72. -- Player's last bones time must match their last death time.
  73. if player_bones_time ~= player_death_time then
  74. --minetest.log('bones time doesn\'t match death time')
  75. return
  76. end
  77. -- Player's last respawn must be older than these bones.
  78. if player_respawn_time >= bones_death_time then
  79. --minetest.log('player respawned already')
  80. return
  81. end
  82. -- Everything looks in order. Revive player.
  83. scepter_revive_player(tref, tname, pname, pos)
  84. end
  85. local function scepter_hit_player(itemstack, user, pt)
  86. local pname = user:get_player_name()
  87. local tref = pt.ref
  88. ambiance.sound_play("nether_extract_blood", tref:get_pos(), 1.0, 30)
  89. local hp = tref:get_hp()
  90. local tname = tref:get_player_name()
  91. if hp <= 0 and pname ~= tname then
  92. -- Target is another player and player is dead. Revive player.
  93. -- This will bypass the respawn code, and player should revive in place.
  94. scepter_revive_player(tref, tname, pname)
  95. end
  96. end
  97. function stoneworld.oerkki_scepter(itemstack, user, pt)
  98. if user and user:is_player() then
  99. if pt.type == "node" and minetest.get_node(pt.under).name == "bones:bones" then
  100. scepter_hit_bones(itemstack, user, pt)
  101. elseif pt.type == "object" and pt.ref and pt.ref:is_player() then
  102. scepter_hit_player(itemstack, user, pt, nil)
  103. end
  104. end
  105. end
  106. -- They say the elite oerkki used it when they wanted to interrogate a prisoner
  107. -- harshly. But it can be repurposed for teamwork assistance.
  108. minetest.register_tool("stoneworld:oerkki_scepter", {
  109. description = "Interrogation Prod",
  110. inventory_image = "stoneworld_oerkki_staff.png",
  111. -- Tools with dual-use functions MUST put the secondary use in this callback,
  112. -- otherwise normal punches do not work!
  113. on_place = stoneworld.oerkki_scepter,
  114. on_secondary_use = stoneworld.oerkki_scepter,
  115. -- Using it on a live player? >:)
  116. -- Damage info is stored by sysdmg.
  117. tool_capabilities = {
  118. full_punch_interval = 3.0,
  119. },
  120. })
  121. -- Not craftable. Item is loot ONLY.
  122. --------------------------------------------------------------------------------