Replace getpos() with get_pos()
[MineClone/MineClone2.git] / mods / PLAYER / mcl_playerplus / init.lua
blobf9022a3b79c94d7f9d3b1eee337666c0efb82b31
1 -- Internal player state
2 local mcl_playerplus_internal = {}
4 local armor_mod = minetest.get_modpath("3d_armor")
5 local def = {}
6 local time = 0
8 minetest.register_globalstep(function(dtime)
10 time = time + dtime
12 -- Update jump status immediately since we need this info in real time.
13 -- WARNING: This section is HACKY as hell since it is all just based on heuristics.
14 for _,player in pairs(minetest.get_connected_players()) do
15 local name = player:get_player_name()
16 if mcl_playerplus_internal[name].jump_cooldown > 0 then
17 mcl_playerplus_internal[name].jump_cooldown = mcl_playerplus_internal[name].jump_cooldown - dtime
18 end
19 if player:get_player_control().jump and mcl_playerplus_internal[name].jump_cooldown <= 0 then
21 local pos = player:get_pos()
23 local node_stand = mcl_playerinfo[name].node_stand
24 local node_stand_below = mcl_playerinfo[name].node_stand_below
25 local node_head = mcl_playerinfo[name].node_head
26 local node_feet = mcl_playerinfo[name].node_feet
27 if not node_stand or not node_stand_below or not node_head or not node_feet then
28 return
29 end
31 -- Cause buggy exhaustion for jumping
33 --[[ Checklist we check to know the player *actually* jumped:
34 * Not on or in liquid
35 * Not on or at climbable
36 * On walkable
37 * Not on disable_jump
38 FIXME: This code is pretty hacky and it is possible to miss some jumps or detect false
39 jumps because of delays, rounding errors, etc.
40 What this code *really* needs is some kind of jumping “callback” which this engine lacks
41 as of 0.4.15.
44 if minetest.get_item_group(node_feet, "liquid") == 0 and
45 minetest.get_item_group(node_stand, "liquid") == 0 and
46 not minetest.registered_nodes[node_feet].climbable and
47 not minetest.registered_nodes[node_stand].climbable and
48 (minetest.registered_nodes[node_stand].walkable or minetest.registered_nodes[node_stand_below].walkable)
49 and minetest.get_item_group(node_stand, "disable_jump") == 0
50 and minetest.get_item_group(node_stand_below, "disable_jump") == 0 then
51 -- Cause exhaustion for jumping
52 if mcl_sprint.is_sprinting(name) then
53 mcl_hunger.exhaust(name, mcl_hunger.EXHAUST_SPRINT_JUMP)
54 else
55 mcl_hunger.exhaust(name, mcl_hunger.EXHAUST_JUMP)
56 end
58 -- Reset cooldown timer
59 mcl_playerplus_internal[name].jump_cooldown = 0.45
60 end
61 end
62 end
64 -- Run the rest of the code every 0.5 seconds
65 if time < 0.5 then
66 return
67 end
69 -- reset time for next check
70 -- FIXME: Make sure a regular check interval applies
71 time = 0
73 -- check players
74 for _,player in pairs(minetest.get_connected_players()) do
75 -- who am I?
76 local name = player:get_player_name()
78 -- where am I?
79 local pos = player:get_pos()
81 -- what is around me?
82 local node_stand = mcl_playerinfo[name].node_stand
83 local node_stand_below = mcl_playerinfo[name].node_stand_below
84 local node_head = mcl_playerinfo[name].node_head
85 local node_feet = mcl_playerinfo[name].node_feet
86 if not node_stand or not node_stand_below or not node_head or not node_feet then
87 return
88 end
90 -- set defaults
91 def.speed = 1
93 -- Standing on soul sand? If so, walk slower
94 if node_stand == "mcl_nether:soul_sand" then
95 -- TODO: Tweak walk speed
96 -- TODO: Also slow down mobs
97 -- Slow down even more when soul sand is above certain block
98 if node_stand_below == "mcl_core:ice" or node_stand_below == "mcl_core:packed_ice" or node_stand_below == "mcl_core:slimeblock" or node_stand_below == "mcl_core:water_source" then
99 playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.1)
100 else
101 playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.4)
103 else
104 -- Reset speed decrease
105 playerphysics.remove_physics_factor(player, "speed", "mcl_playerplus:surface")
108 -- Is player suffocating inside node? (Only for solid full opaque cube type nodes
109 -- without group disable_suffocation=1)
110 local ndef = minetest.registered_nodes[node_head]
112 if (ndef.walkable == nil or ndef.walkable == true)
113 and (ndef.collision_box == nil or ndef.collision_box.type == "regular")
114 and (ndef.node_box == nil or ndef.node_box.type == "regular")
115 and (ndef.groups.disable_suffocation ~= 1)
116 and (ndef.groups.opaque == 1)
117 and (node_head ~= "ignore")
118 -- Check privilege, too
119 and (not minetest.check_player_privs(name, {noclip = true})) then
120 if player:get_hp() > 0 then
121 mcl_death_messages.player_damage(player, string.format("%s suffocated to death.", name))
122 player:set_hp(player:get_hp() - 1)
126 -- Am I near a cactus?
127 local near = minetest.find_node_near(pos, 1, "mcl_core:cactus")
128 if not near then
129 near = minetest.find_node_near({x=pos.x, y=pos.y-1, z=pos.z}, 1, "mcl_core:cactus")
131 if near then
132 -- Am I touching the cactus? If so, it hurts
133 local dist = vector.distance(pos, near)
134 local dist_feet = vector.distance({x=pos.x, y=pos.y-1, z=pos.z}, near)
135 if dist < 1.1 or dist_feet < 1.1 then
136 if player:get_hp() > 0 then
137 mcl_death_messages.player_damage(player, string.format("%s was prickled by a cactus.", name))
138 mcl_hunger.exhaust(name, mcl_hunger.EXHAUST_DAMAGE)
139 player:set_hp(player:get_hp() - 1)
144 --[[ Swimming: Cause exhaustion.
145 NOTE: As of 0.4.15, it only counts as swimming when you are with the feet inside the liquid!
146 Head alone does not count. We respect that for now. ]]
147 if minetest.get_item_group(node_feet, "liquid") ~= 0 or
148 minetest.get_item_group(node_stand, "liquid") ~= 0 then
149 local lastPos = mcl_playerplus_internal[name].lastPos
150 if lastPos then
151 local dist = vector.distance(lastPos, pos)
152 mcl_playerplus_internal[name].swimDistance = mcl_playerplus_internal[name].swimDistance + dist
153 if mcl_playerplus_internal[name].swimDistance >= 1 then
154 local superficial = math.floor(mcl_playerplus_internal[name].swimDistance)
155 mcl_hunger.exhaust(name, mcl_hunger.EXHAUST_SWIM * superficial)
156 mcl_playerplus_internal[name].swimDistance = mcl_playerplus_internal[name].swimDistance - superficial
162 -- Underwater: Spawn bubble particles
163 if minetest.get_item_group(node_head, "water") ~= 0 then
165 minetest.add_particlespawner({
166 amount = 10,
167 time = 0.15,
168 minpos = { x = -0.25, y = 0.3, z = -0.25 },
169 maxpos = { x = 0.25, y = 0.7, z = 0.75 },
170 attached = player,
171 minvel = {x = -0.2, y = 0, z = -0.2},
172 maxvel = {x = 0.5, y = 0, z = 0.5},
173 minacc = {x = -0.4, y = 4, z = -0.4},
174 maxacc = {x = 0.5, y = 1, z = 0.5},
175 minexptime = 0.3,
176 maxexptime = 0.8,
177 minsize = 0.7,
178 maxsize = 2.4,
179 texture = "mcl_particles_bubble.png"
183 -- Show positions of barriers when player is wielding a barrier
184 local wi = player:get_wielded_item():get_name()
185 if wi == "mcl_core:barrier" or wi == "mcl_core:realm_barrier" then
186 local pos = vector.round(player:get_pos())
187 local r = 8
188 local vm = minetest.get_voxel_manip()
189 local emin, emax = vm:read_from_map({x=pos.x-r, y=pos.y-r, z=pos.z-r}, {x=pos.x+r, y=pos.y+r, z=pos.z+r})
190 local area = VoxelArea:new{
191 MinEdge = emin,
192 MaxEdge = emax,
194 local data = vm:get_data()
195 for x=pos.x-r, pos.x+r do
196 for y=pos.y-r, pos.y+r do
197 for z=pos.z-r, pos.z+r do
198 local vi = area:indexp({x=x, y=y, z=z})
199 local nodename = minetest.get_name_from_content_id(data[vi])
200 local tex
201 if nodename == "mcl_core:barrier" then
202 tex = "mcl_core_barrier.png"
203 elseif nodename == "mcl_core:realm_barrier" then
204 tex = "mcl_core_barrier.png^[colorize:#FF00FF:127^[transformFX"
206 if tex then
207 minetest.add_particle({
208 pos = {x=x, y=y, z=z},
209 expirationtime = 1,
210 size = 8,
211 texture = tex,
212 playername = name
220 -- Update internal values
221 mcl_playerplus_internal[name].lastPos = pos
225 end)
227 -- set to blank on join (for 3rd party mods)
228 minetest.register_on_joinplayer(function(player)
229 local name = player:get_player_name()
231 mcl_playerplus_internal[name] = {
232 lastPos = nil,
233 swimDistance = 0,
234 jump_cooldown = -1, -- Cooldown timer for jumping, we need this to prevent the jump exhaustion to increase rapidly
236 end)
238 -- clear when player leaves
239 minetest.register_on_leaveplayer(function(player)
240 local name = player:get_player_name()
242 mcl_playerplus_internal[name] = nil
243 end)