Make collision adjustment configurable
[minetest_teletool.git] / init.lua
blob227fe01ef3b396cef4eae4216a386f6d15c5d470
1 if (minetest.get_modpath("intllib")) then
2 dofile(minetest.get_modpath("intllib").."/intllib.lua")
3 S = intllib.Getter(minetest.get_current_modname())
4 else
5 S = function ( s ) return s end
6 end
8 teletool = {}
10 --[[ Load settings, apply default settings ]]
11 teletool.settings = {}
12 teletool.settings.avoid_collisions = true
13 teletool.settings.adjust_head = true
14 local avoid_collisions = minetest.setting_getbool("teletool_avoid_collisions")
15 if avoid_collisions ~= nil then
16 teletool.settings.avoid_collision = avoid_collisions
17 end
18 local adjust_head = minetest.setting_getbool("teletool_adjust_head")
19 if adjust_head ~= nil then
20 teletool.settings.adjust_head = adjust_head
21 end
24 function teletool.teleport(player, pointed_thing)
25 local pos = pointed_thing.above
26 local src = player:getpos()
27 local dest = {x=pos.x, y=math.ceil(pos.y)-0.5, z=pos.z}
28 local over = {x=dest.x, y=dest.y+1, z=dest.z}
29 local destnode = minetest.get_node({x=dest.x, y=math.ceil(dest.y), z=dest.z})
30 local overnode = minetest.get_node({x=over.x, y=math.ceil(over.y), z=over.z})
32 if teletool.settings.adjust_head then
33 -- This trick prevents the player's head to spawn in a walkable node if the player clicked on the lower side of a node
34 -- NOTE: This piece of code must be updated as soon the collision boxes of players become configurable
35 if minetest.registered_nodes[overnode.name].walkable then
36 dest.y = dest.y - 1
37 end
38 end
40 if teletool.settings.avoid_collisions then
41 -- The destination must be collision free
42 destnode = minetest.get_node({x=dest.x, y=math.ceil(dest.y), z=dest.z})
43 if minetest.registered_nodes[destnode.name].walkable then
44 return false
45 end
46 end
48 minetest.add_particlespawner({
49 amount = 25,
50 time = 0.1,
51 minpos = {x=src.x-0.4, y=src.y+0.25, z=src.z-0.4},
52 maxpos = {x=src.x+0.4, y=src.y+0.75, z=src.z+0.4},
53 minvel = {x=-0.1, y=-0.1, z=-0.1},
54 maxvel = {x=0, y=0.1, z=0},
55 minexptime=1,
56 maxexptime=1.5,
57 minsize=1,
58 maxsize=1.25,
59 texture = "teletool_particle_departure.png",
61 minetest.sound_play( {name="teletool_teleport1", gain=1}, {pos=src, max_hear_distance=12})
63 player:setpos(dest)
64 minetest.add_particlespawner({
65 amount = 25,
66 time = 0.1,
67 minpos = {x=dest.x-0.4, y=dest.y+0.25, z=dest.z-0.4},
68 maxpos = {x=dest.x+0.4, y=dest.y+0.75, z=dest.z+0.4},
69 minvel = {x=0, y=-0.1, z=0},
70 maxvel = {x=0.1, y=0.1, z=0.1},
71 minexptime=1,
72 maxexptime=1.5,
73 minsize=1,
74 maxsize=1.25,
75 texture = "teletool_particle_arrival.png",
77 minetest.after(0.5, function(dest) minetest.sound_play( {name="teletool_teleport2", gain=1}, {pos=dest, max_hear_distance=12}) end, dest)
79 return true
80 end
82 minetest.register_tool("teletool:teletool_infinite", {
83 description = S("infinite point teleporter"),
84 range = 20.0,
85 tool_capabilities = {},
86 wield_image = "teletool_teletool_infinite.png",
87 inventory_image = "teletool_teletool_infinite.png",
88 on_use = function(itemstack, user, pointed_thing)
89 local failure = false
90 if(pointed_thing.type == "node") then
91 failure = not teletool.teleport(user, pointed_thing)
92 else
93 failure = true
94 end
95 if failure then
96 minetest.sound_play( {name="teletool_fail", gain=0.5}, {pos=user:getpos(), max_hear_distance=4})
97 end
98 return itemstack
99 end,
103 if(minetest.get_modpath("technic")) then
104 technic.register_power_tool("teletool:teletool_technic", 50000)
106 minetest.register_tool("teletool:teletool_technic", {
107 description = S("electronic point teleporter"),
108 range = 20.0,
109 tool_capabilities = {},
110 wield_image = "teletool_teletool_technic.png",
111 inventory_image = "teletool_teletool_technic.png",
112 on_use = function(itemstack, user, pointed_thing)
113 local failure = false
114 if(pointed_thing.type == "node") then
115 local meta = minetest.deserialize(itemstack:get_metadata())
116 if not meta or not meta.charge then
117 failure = true
118 elseif meta.charge >= 1000 then
119 meta.charge = meta.charge - 1000
120 failure = not teletool.teleport(user, pointed_thing)
121 if not failure then
122 technic.set_RE_wear(itemstack, meta.charge, 50000)
123 itemstack:set_metadata(minetest.serialize(meta))
125 else
126 failure = true
128 else
129 failure = true
131 if failure then
132 minetest.sound_play( {name="teletool_fail", gain=0.5}, {pos=user:getpos(), max_hear_distance=4})
134 return itemstack
135 end,
137 -- Technic data
138 wear_represents = "technic_RE_charge",
139 on_refill = technic.refill_RE_charge
143 if(minetest.get_modpath("mana") ~= nil) then
144 minetest.register_tool("teletool:teletool_mana", {
145 description = S("magical point teleporter"),
146 range = 20.0,
147 tool_capabilities = {},
148 wield_image = "teletool_teletool_mana.png",
149 inventory_image = "teletool_teletool_mana.png",
150 on_use = function(itemstack, user, pointed_thing)
151 local failure = false
152 if(pointed_thing.type == "node") then
153 if(mana.subtract(user:get_player_name(), 20)) then
154 failure = not teletool.teleport(user, pointed_thing)
155 else
156 failure = true
158 else
159 failure = true
161 if failure then
162 minetest.sound_play( {name="teletool_fail", gain=0.5}, {pos=user:getpos(), max_hear_distance=4})
164 return itemstack
165 end,
169 if(minetest.get_modpath("default") ~= nil and minetest.get_modpath("technic") ~= nil) then
170 minetest.register_craft({
171 output = "teletool:teletool_technic",
172 recipe = {
173 {"", "default:mese_crystal", ""},
174 {"technic:stainless_steel_ingot", "technic:red_energy_crystal", "technic:stainless_steel_ingot"},
175 {"technic:stainless_steel_ingot", "technic:battery", "technic:stainless_steel_ingot"}
180 minetest.register_alias("teletool:teletool", "teletool:teletool_infinite")