incrementaltp: respect physics overrides
[waspsaliva.git] / clientmods / autofly / init.lua
blob337e29b238c20953acb7a1f6388c72a774bf4b65
1 -- autofly by cora
2 -- gui shit shamelessly stolen from advmarkers
3 -- https://git.minetest.land/luk3yx/advmarkers-csm
4 --[[
5 PATCHING MINETEST: (for autoaim)
6 in l_localplayer.h add:
7 static int l_set_yaw(lua_State *L);
8 static int l_set_pitch(lua_State *L);
10 in l_localplayer.cpp add:
11 int LuaLocalPlayer::l_set_yaw(lua_State *L)
13 LocalPlayer *player = getobject(L, 1);
14 f32 p = (float) luaL_checkinteger(L, 2);
15 player->setYaw(p);
16 g_game->cam_view.camera_yaw = p;
17 g_game->cam_view_target.camera_yaw = p;
18 player->setYaw(p);
19 return 0;
21 int LuaLocalPlayer::l_set_pitch(lua_State *L)
23 LocalPlayer *player = getobject(L, 1);
24 f32 p = (float) luaL_checkinteger(L, 2);
25 player->setPitch(p);
26 g_game->cam_view.camera_pitch = p;
27 g_game->cam_view_target.camera_pitch = p;
28 player->setPitch(p);
29 return 0;
31 in src/client/game.h, below class Game { public: add:
32 CameraOrientation cam_view = {0};
33 CameraOrientation cam_view_target = { 0 };
35 from src/client/game.cpp remove
36 CameraOrientation cam_view = {0};
37 CameraOrientation cam_view_target = { 0 };
39 --]]
41 -- Chat commands:
42 -- .wa x,y,z name - add waypoint with coords and name
43 -- .wah - quickadd this location (name will be time and date)
44 -- .wp - open the selection menu
45 -- .cls - remove hud
47 autofly = {}
48 wps={}
51 local landing_distance=5
52 local speed=0;
53 local ltime=0
55 local storage = minetest.get_mod_storage()
56 local oldpm=false
57 local lpos={x=0,y=0,z=0}
58 local info=minetest.get_server_info()
59 local stprefix="autofly-".. info['address'] .. '-'
60 --local stprefix="autofly-"
61 local hud_wps={}
62 autofly.flying=false
63 autofly.cruiseheight = 30
65 local modname = minetest.get_current_modname()
66 local modpath = minetest.get_modpath(modname)
67 dofile(modpath .. "/wpforms.lua")
68 dofile(modpath .. "/pathfly.lua")
70 local hud_wp
71 local hud_info
72 -- /COMMON
73 local pos_to_string = ws.pos_to_string
74 local string_to_pos = ws.string_to_pos
77 function autofly.get2ddst(pos1,pos2)
78 return vector.distance({x=pos1.x,y=0,z=pos1.z},{x=pos2.x,y=0,z=pos2.z})
79 end
81 local last_sprint = false
82 local hud_ah=nil
86 function autofly.update_ah()
87 local pos=vector.new(0,0,0)
88 local ppos=minetest.localplayer:get_pos()
89 local yaw=math.floor(minetest.localplayer:get_yaw())
91 local theta =(yaw * math.pi / 180)
92 pos.x= math.floor( 100 * math.cos(theta) )
93 pos.z= math.floor( 100 * math.sin(theta) )
94 pos=vector.add(ppos,pos)
95 pos.y=ppos.y
96 local nname=pos_to_string(pos).."\n"..yaw.."\n"..'__________________________________________________________________________________________________________________________________________________'
97 if hud_ah then
98 minetest.display_chat_message(pos.x..","..pos.z)
99 minetest.localplayer:hud_change(hud_ah, 'world_pos', pos)
100 minetest.localplayer:hud_change(hud_ah, 'name', nname)
101 else
102 hud_ah = minetest.localplayer:hud_add({
103 hud_elem_type = 'waypoint',
104 name = nname,
105 title = pos_to_string(pos),
106 text = '',
107 number = 0x00ff00,
108 world_pos = pos,
109 precision = 0,
110 width = 1000
114 minetest.register_globalstep(function()
116 if not minetest.localplayer then return end
117 -- autofly.update_ah()
118 end)
120 minetest.register_globalstep(function()
121 if not minetest.localplayer then return end
123 autofly.axissnap()
124 if minetest.settings:get_bool("autosprint") or (minetest.settings:get_bool("continuous_forward") and minetest.settings:get_bool("autofsprint")) then
125 core.set_keypress("special1", true)
126 last_sprint = true
127 elseif last_sprint then
128 core.set_keypress("special1", false)
129 last_sprint = false
131 if not autofly.flying then autofly.set_hud_info("")
132 else
133 autofly.set_hud_info("")
134 local pos = autofly.last_coords
135 if pos then
136 local dst = vector.distance(pos,minetest.localplayer:get_pos())
137 local etatime=-1
138 if not (speed == 0) then etatime = ws.round2(dst / speed / 60,2) end
139 autofly.etatime=etatime
140 autofly.set_hud_info(autofly.last_name .. "\n" .. pos_to_string(pos) .. "\n" .. "ETA" .. etatime .. " mins")
141 local pm=minetest.settings:get_bool('pitch_move')
142 local hdst=autofly.get2ddst(pos,minetest.localplayer:get_pos())
143 if pm then hdst=vector.distance(pos,ws.dircoord(0,0,0)) end
144 if autofly.flying and hdst < landing_distance then
145 autofly.arrived()
150 if not minetest.settings:get_bool("freecam") and autofly.flying and (minetest.settings:get_bool('afly_autoaim')) then
151 autofly.aim(autofly.last_coords)
154 if ( os.time() < ltime + 1 ) then return end
155 ltime=os.time()
156 if lpos then
157 local dst=vector.distance(minetest.localplayer:get_pos(),lpos)
158 speed=ws.round2(dst,1)
159 autofly.speed=speed
161 lpos=minetest.localplayer:get_pos()
162 autofly.cruise()
163 end)
165 function autofly.get_speed()
166 return speed
170 function autofly.set_hud_wp(pos, title)
171 if hud_wp then
172 minetest.localplayer:hud_remove(hud_wp)
174 pos = string_to_pos(pos)
175 hud_wp=nil
176 if not pos then return end
177 if not title then
178 title = pos.x .. ', ' .. pos.y .. ', ' .. pos.z
180 autofly.last_name=title
181 if hud_wp then
182 minetest.localplayer:hud_change(hud_wp, 'name', title)
183 minetest.localplayer:hud_change(hud_wp, 'world_pos', pos)
184 else
185 hud_wp = minetest.localplayer:hud_add({
186 hud_elem_type = 'waypoint',
187 name = title,
188 text = 'm',
189 number = 0x00ff00,
190 world_pos = pos
193 return true
196 local hud_info
197 function autofly.get_quad()
198 local lp=minetest.localplayer:get_pos()
199 local quad=""
201 if lp.z < 0 then quad="South"
202 else quad="North" end
204 if lp.x < 0 then quad=quad.."-west"
205 else quad=quad.."-east" end
207 return quad
210 function autofly.get_wdir()
211 local qd=autofly.get_quad()
217 function autofly.get_local_name()
218 local ww=autofly.getwps()
219 local lp=minetest.localplayer:get_pos()
220 local odst=500;
221 local rt=false
222 for k,v in pairs(ww) do
223 local lwp=autofly.get_waypoint(v)
224 if type(lwp) == 'table' then
225 local dst=vector.distance(lp,lwp)
226 if dst < 500 then
227 if dst < odst then
228 odst=dst
229 rt=v
234 if not rt then rt=autofly.get_quad() end
235 return rt
239 local function countents()
240 local obj = minetest.localplayer.get_nearby_objects(10000)
241 return #obj
245 function autofly.set_hud_info(text)
246 if not minetest.localplayer then return end
247 if type(text) ~= "string" then return end
248 local dir=ws.getdir()
249 local ddir=""
250 if dir == "north" then
251 ddir="north(+z)"
252 elseif dir == "east" then
253 ddir="east(+x)"
254 elseif dir == "south" then
255 ddir="south(-z)"
256 elseif dir == "west" then
257 ddir="west(-x)"
259 local lp=minetest.localplayer
260 local vspeed=lp:get_velocity()
261 local ttext=text.."\nSpeed: "..speed.."n/s\n"
262 ..ws.round2(vspeed.x,2) ..','
263 ..ws.round2(vspeed.y,2) ..','
264 ..ws.round2(vspeed.z,2) .."\n"
265 .."Yaw:"..ws.round2(lp:get_yaw(),2).."° Pitch:" ..ws.round2(lp:get_pitch(),2).."° "
266 if turtle then ttext=ttext..ddir end
267 if minetest.settings:get_bool('afly_shownames') then
268 ttext=ttext.."\n"..autofly.get_local_name() .."\nEntities: " .. countents()
270 if hud_info then
271 minetest.localplayer:hud_change(hud_info,'text',ttext)
272 else
273 hud_info = minetest.localplayer:hud_add({
274 hud_elem_type = 'text',
275 name = "Flight Info",
276 text = ttext,
277 number = 0x00ff00,
278 direction = 0,
279 position = {x=0,y=0.8},
280 alignment ={x=1,y=1},
281 offset = {x=0, y=0}
284 return true
287 function autofly.display(pos,name)
288 if name == nil then name=pos_to_string(pos) end
289 local pos=string_to_pos(pos)
290 autofly.set_hud_wp(pos, name)
291 return true
295 function autofly.display_waypoint(name)
296 local pos=name
297 if type(name) ~= 'table' then pos=autofly.get_waypoint(name) end
298 autofly.last_name = name
299 --autofly.last_coords = pos
300 autofly.set_hud_info(name)
301 autofly.aim(autofly.last_coords)
302 autofly.display(pos,name)
303 return true
306 function autofly.goto_waypoint(name)
307 local wp=autofly.get_waypoint(name)
308 autofly.goto(wp)
309 autofly.last_name=name
310 autofly.display_waypoint(autofly.last_name)
311 return true
314 function autofly.goto(pos)
315 minetest.settings:set_bool("free_move",true)
316 minetest.settings:set_bool("continuous_forward",true)
317 if minetest.settings:get_bool("afly_sprint") then
318 minetest.settings:set_bool("autofsprint",true)
319 minetest.settings:set_bool("autoeat_timed",true)
321 minetest.settings:set_bool("afly_autoaim",true)
322 autofly.last_coords = pos
323 autofly.last_name = minetest.pos_to_string(pos)
324 autofly.aim(autofly.last_coords)
325 autofly.flying=true
326 autofly.set_hud_wp(autofly.last_coords, autofly.last_name)
327 return true
330 function autofly.fly3d(pos)
331 minetest.settings:set_bool("pitch_move",true)
332 autofly.goto(pos)
335 function autofly.fly2d(pos)
336 minetest.settings:set_bool("pitch_move",false)
337 autofly.goto(pos)
340 function autofly.arrived()
341 if not autofly.flying then return end
342 minetest.settings:set("continuous_forward", "false")
343 minetest.settings:set_bool("autofsprint",false)
344 minetest.settings:set_bool("pitch_move",oldpm)
345 minetest.settings:set_bool("afly_autoaim",false)
346 minetest.settings:set_bool("autoeat_timed",false)
347 autofly.set_hud_info("Arrived!")
348 autofly.flying = false
349 minetest.sound_play({name = "default_alert", gain = 1.0})
352 local cruise_wason=false
353 local nfctr=0
356 function autofly.cruise()
357 if not minetest.settings:get_bool('afly_cruise') then
358 if cruise_wason then
359 cruise_wason=false
360 core.set_keypress("jump",false)
361 core.set_keypress("sneak",false)
363 return end
365 local lp=minetest.localplayer:get_pos()
366 local pos1 = vector.add(lp,{x=16,y=100,z=16})
367 local pos2 = vector.add(lp,{x=-16,y=-100,z=-16})
368 local nds=minetest.find_nodes_in_area_under_air(pos1, pos2, nlist.get_mclnodes())
369 local y=0
370 local found=false
373 for k,v in ipairs(nds) do
374 local nd = minetest.get_node_or_nil(v)
375 if nd ~= nil and nd.name ~= "air" then
376 if v.y > y then
377 y=v.y
378 found=true
382 if (autofly.cruiseheight ~= nil) then y=y+autofly.cruiseheight end
383 local diff = math.ceil(lp.y - y)
385 if not cruise_wason then --initially set the cruiseheight to the current value above ground
386 -- if not found then return end --wait with activation til a ground node has been found.
387 local clr,nnd=minetest.line_of_sight(lp,vector.add(lp,{x=1,y=-200,z=1}))
388 if not clr then diff = math.ceil(lp.y - nnd.y)
389 elseif not found then return end
390 if diff < 1 then autofly.cruiseheight = 20
391 else autofly.cruiseheight = diff end
393 cruise_wason=true
394 minetest.display_chat_message("cruise mode activated. target height set to " .. diff .. " nodes above ground.")
397 if not found then
398 if nfctr<20 then nfctr = nfctr + 1 return end
399 --minetest.display_chat_message("no nodes found for 20 iterations. lowering altitude.")
400 nfctr=0
401 minetest.settings:set_bool("free_move",false)
402 core.set_keypress("jump",false)
403 core.set_keypress("sneak",false)
404 return
407 local tolerance = 1
408 if diff < -tolerance then
409 minetest.settings:set_bool("free_move",true)
410 core.set_keypress("jump",true)
411 core.set_keypress("sneak",false)
412 --minetest.display_chat_message("too low: " .. y)
413 elseif diff > tolerance * 10 then
414 core.set_keypress("jump",false)
415 core.set_keypress("sneak",true)
416 minetest.settings:set_bool("free_move",false)
417 --minetest.display_chat_message("too high: " .. y)
418 elseif diff > tolerance then
419 core.set_keypress("jump",false)
420 core.set_keypress("sneak",true)
421 else
422 minetest.settings:set_bool("free_move",true)
423 core.set_keypress("jump",false)
424 core.set_keypress("sneak",false)
425 --minetest.display_chat_message("target height reached: " .. y)
431 function autofly.aim(tpos)
432 return ws.aim(tpos)
435 function autofly.autotp(tpname)
436 if minetest.localplayer == nil then autofly.autotp(tpname) end
437 local tpos=nil
438 if tpname == nil then
439 tpos = autofly.get_waypoint('AUTOTP')
440 elseif type(tpname) == "table" then
441 tpos = tpname
442 else
443 tpos=autofly.get_waypoint(tpname)
445 if tpos == nil then return end
446 local lp=minetest.localplayer
447 local dst=vector.distance(lp:get_pos(),tpos)
448 if (dst < 300) then
449 minetest.sound_play({name = "default_alert", gain = 3.0})
450 autofly.delete_waypoint('AUTOTP')
451 return true
453 autofly.set_waypoint(tpos,'AUTOTP')
454 local boat_found=false
455 for k, v in ipairs(lp.get_nearby_objects(4)) do
456 local txt = v:get_item_textures()
457 if ( txt:find('mcl_boats_texture')) then
458 boat_found=true
459 minetest.display_chat_message("boat found. entering and tping to "..minetest.pos_to_string(autofly.get_waypoint('AUTOTP')))
460 autofly.aim(vector.add(v:get_pos(),{x=0,y=-1.5,z=0}))
461 minetest.after("0.2",function()
462 minetest.interact("place") end)
463 minetest.after("1.5",function()
464 autofly.warpae('AUTOTP')
465 end)
466 return true
469 if not boat_found then
470 minetest.display_chat_message("no boat found. trying again in 5.")
471 minetest.after("5.0",function() autofly.autotp(tpname) end)
472 return end
477 autofly.register_transport('Fly3D',function(pos,name) autofly.fly3d(pos,name) end)
478 autofly.register_transport('Fly2D',function(pos,name) autofly.fly2d(pos,name) end)
479 autofly.register_transport('wrp',function(pos,name) autofly.warp(name) end)
480 --autofly.register_transport('atp',function(pos,name) autofly.autotp(name) end)
482 function autofly.axissnap()
483 if not minetest.settings:get_bool('afly_snap') then return end
484 if minetest.settings:get_bool("freecam") then return end
485 local y=minetest.localplayer:get_yaw()
486 local yy=nil
487 if ( y < 45 or y > 315 ) then
488 yy=0
489 elseif (y < 135) then
490 yy=90
491 elseif (y < 225 ) then
492 yy=180
493 elseif ( y < 315 ) then
494 yy=270
496 if yy ~= nil then
497 minetest.localplayer:set_yaw(yy)
501 minetest.register_on_death(function()
502 if minetest.localplayer then
503 local name = 'Death waypoint'
504 local pos = minetest.localplayer:get_pos()
505 autofly.last_coords = pos
506 autofly.last_name = name
507 autofly.set_waypoint(pos,name)
508 autofly.display(pos,name)
510 end)
512 local function get_dimension(pos)
513 if pos.y > -65 then return "overworld"
514 elseif pos.y > -8000 then return "void"
515 elseif pos.y > -27000 then return "end"
516 elseif pos.y >29000 then return "void"
517 elseif pos.y >31000 then return "nether"
518 else return "void"
522 function autofly.warp(name)
523 local pos=autofly.get_waypoint(name)
524 if pos then
525 if get_dimension(pos) == "void" then return false end
526 minetest.localplayer:set_pos(pos)
527 return true
530 function autofly.warpae(name)
531 local s, m = autofly.warp(name)
532 if s then
533 minetest.disconnect()
535 return true
538 function autofly.getwps()
539 local wp={}
540 for name, _ in pairs(storage:to_table().fields) do
541 if name:sub(1, string.len(stprefix)) == stprefix then
542 table.insert(wp, name:sub(string.len(stprefix)+1))
545 table.sort(wp)
546 return wp
551 function autofly.impfromsrv(srv,sel)
552 local srvstr="autofly-".. srv .. '-'
553 for name, _ in pairs(storage:to_table().fields) do
554 if name:sub(1, string.len(srvstr)) == srvstr then
555 local name=name:sub(string.len(srvstr)+1)
556 if not sel or ( sel and name:sub(1, string.len(sel)) == sel ) then
557 local pos=string_to_pos(storage:get_string(srvstr .. tostring(name)))
558 autofly.set_waypoint(pos,name)
562 return wp
565 function autofly.set_waypoint(pos, name)
566 pos = pos_to_string(pos)
567 if not pos then return end
568 storage:set_string(stprefix .. tostring(name), pos)
569 return true
572 function autofly.delete_waypoint(name)
573 storage:set_string(stprefix .. tostring(name), '')
576 function autofly.get_waypoint(name)
577 return string_to_pos(storage:get_string(stprefix .. tostring(name)))
580 function autofly.rename_waypoint(oldname, newname)
581 oldname, newname = tostring(oldname), tostring(newname)
582 local pos = autofly.get_waypoint(oldname)
583 if not pos or not autofly.set_waypoint(pos, newname) then return end
584 if oldname ~= newname then
585 autofly.delete_waypoint(oldname)
587 return true
589 local function log(level, message)
590 minetest.log(level, ('[%s] %s'):format(mod_name, message))
592 function autofly.dumptolog()
593 local wp=autofly.getwps()
594 for name, _ in pairs(wp) do
595 --local lname=name:sub(string.len(stprefix)+1)
596 -- local ppos=string_to_pos(storage:get_string(tostring(name)))
597 if ppos then
598 log('action',name .. ' :: ')
603 minetest.after("5.0",function()
604 if autofly.get_waypoint('AUTOTP') ~= nil then autofly.autotp(nil) end
605 end)
608 math.randomseed(os.time())
610 local randflying = false
612 minetest.register_globalstep(function()
613 if randflying and not autofly.flying then
614 local x = math.random(-31000, 31000)
615 local y = math.random(2000, 31000)
616 local z = math.random(-31000, 31000)
618 autofly.goto({x = x, y = y, z = z})
620 end)
622 local function randfly()
623 if not randflying then
624 randflying = true
625 local lp = minetest.localplayer:get_pos()
626 autofly.goto(turtle.coord(lp.x, 6000, lp.z))
627 else
628 randflying = false
629 autofly.arrived()
635 minetest.register_chatcommand('waypoints', {
636 params = '',
637 description = 'Open the autofly GUI',
638 func = function(param) autofly.display_formspec() end
641 ws.register_chatcommand_alias('waypoints','wp', 'wps', 'waypoint')
643 -- Add a waypoint
644 minetest.register_chatcommand('add_waypoint', {
645 params = '<pos / "here" / "there"> <name>',
646 description = 'Adds a waypoint.',
647 func = function(param)
648 local s, e = param:find(' ')
649 if not s or not e then
650 return false, 'Invalid syntax! See .help add_mrkr for more info.'
652 local pos = param:sub(1, s - 1)
653 local name = param:sub(e + 1)
654 if not pos then
655 return false, err
657 if not name or #name < 1 then
658 return false, 'Invalid name!'
660 return autofly.set_waypoint(pos, name), 'Done!'
663 ws.register_chatcommand_alias('add_waypoint','wa', 'add_wp')
666 minetest.register_chatcommand('add_waypoint_here', {
667 params = 'name',
668 description = 'marks the current position',
669 func = function(param)
670 local name = os.date("%Y-%m-%d %H:%M:%S")
671 local pos = minetest.localplayer:get_pos()
672 return autofly.set_waypoint(pos, name), 'Done!'
675 ws.register_chatcommand_alias('add_waypoint_here', 'wah', 'add_wph')
677 minetest.register_chatcommand('clear_waypoint', {
678 params = '',
679 description = 'Hides the displayed waypoint.',
680 func = function(param)
681 if autofly.flying then autofly.flying=false end
682 if hud_wp then
683 minetest.localplayer:hud_remove(hud_wp)
684 hud_wp = nil
685 return true, 'Hidden the currently displayed waypoint.'
686 elseif not minetest.localplayer.hud_add then
687 minetest.run_server_chatcommand('clrmrkr')
688 return
689 elseif not hud_wp then
690 return false, 'No waypoint is currently being displayed!'
692 for k,v in wps do
693 minetest.localplayer:hud_remove(v)
694 table.remove(k)
697 end,
699 ws.register_chatcommand_alias('clear_waypoint', 'cwp','cls')
701 minetest.register_chatcommand('autotp', {
702 params = 'position',
703 description = 'autotp',
704 func = function(param)
705 autofly.autotp(minetest.string_to_pos(param))
708 ws.register_chatcommand_alias('autotp', 'atp')
710 minetest.register_chatcommand('wpdisplay', {
711 params = 'position name',
712 description = 'display waypoint',
713 func = function(pos,name)
714 autofly.display(pos,name)
717 ws.register_chatcommand_alias('wpdisplay', 'wpd')
721 minetest.register_chatcommand("randfly", {
722 description = "Randomly fly up high (toggle).",
723 func = randfly
727 minetest.register_cheat("Aim", "Autofly", "afly_autoaim")
728 minetest.register_cheat("AxisSnap", "Autofly", "afly_snap")
729 minetest.register_cheat("Cruise", "Autofly", "afly_cruise")
730 minetest.register_cheat("Sprint", "Autofly", "afly_sprint")
731 minetest.register_cheat("ShowNames", "Autofly", "afly_shownames")
732 minetest.register_cheat("Waypoints", "Autofly", autofly.display_formspec)