123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- -- Cloaking system for players.
- -- Note: admin has special invisibility system in gdac_invis directory.
- if not minetest.global_exists("cloaking") then cloaking = {} end
- cloaking.modpath = minetest.get_modpath("cloaking")
- cloaking.players = cloaking.players or {}
- -- Localize for speed.
- local math_random = math.random
- local vector_round = vector.round
- local vector_add = vector.add
- function cloaking.spawn_wisp(pos)
- local minp = vector_add(pos, -5)
- local maxp = vector_add(pos, 5)
- local positions = minetest.find_nodes_in_area(minp, maxp, "air")
- if #positions > 0 then
- local p = positions[math_random(1, #positions)]
- pm.spawn_random_wisp(p)
- end
- end
- function cloaking.particle_effect(pos)
- local particles = {
- amount = 100,
- time = 1.1,
- minpos = vector.add(pos, {x=-0.1, y=-0.1, z=-0.1}),
- maxpos = vector.add(pos, {x=0.1, y=0.1, z=0.1}),
- minvel = vector.new(-3.5, -3.5, -3.5),
- maxvel = vector.new(3.5, 3.5, 3.5),
- minacc = {x=0, y=0, z=0},
- maxacc = {x=0, y=0, z=0},
- minexptime = 1.5,
- maxexptime = 2.0,
- minsize = 0.5,
- maxsize = 1.0,
- collisiondetection = false,
- collision_removal = false,
- vertical = false,
- texture = "nether_particle_anim1.png",
- animation = {
- type = "vertical_frames",
- aspect_w = 7,
- aspect_h = 7,
- -- Disabled for now due to causing older clients to hang.
- --length = -1,
- length = 0.3,
- },
- glow = 14,
- }
- minetest.add_particlespawner(particles)
- end
- function cloaking.hud_effect(pname)
- local pref = minetest.get_player_by_name(pname)
- if pref then
- if cloaking.is_cloaked(pname) then
- --minetest.chat_send_all('testing')
- local color = "white"
- local pdata = cloaking.players[pname]
- if pdata.decloak_timer > 0 then
- color = "red"
- end
- local pos = pref:get_pos()
- local r = 10
- local particles = {
- amount = 300,
- time = 1.1,
- --minpos = vector.add(pos, {x=-0.1, y=-0.1, z=-0.1}),
- --maxpos = vector.add(pos, {x=0.1, y=0.1, z=0.1}),
- minpos = {x=-r, y=-r/2, z=-r},
- maxpos = {x=r, y=r/2, z=r},
- minvel = vector.new(0, -1.5, 0),
- maxvel = vector.new(0, 1.5, 0),
- minacc = {x=0, y=0, z=0},
- maxacc = {x=0, y=0, z=0},
- minexptime = 1.5,
- maxexptime = 2.0,
- minsize = 1.0,
- maxsize = 1.0,
- collisiondetection = false,
- collision_removal = false,
- vertical = false,
- texture = "nether_particle_anim3.png" ..
- "^[colorize:" .. color .. ":alpha",
- animation = {
- type = "vertical_frames",
- aspect_w = 7,
- aspect_h = 7,
- -- Disabled for now due to causing older clients to hang.
- --length = -1,
- length = 1,
- },
- glow = 14,
- attached = pref,
- playername = pname,
- }
- -- Cannot use the overriden version of minetest.add_particlespawner()
- -- because sending multiple attached particle-spawners to different players
- -- is broken.
- utility.original_add_particlespawner(particles)
- minetest.after(1, cloaking.hud_effect, pname)
- end
- end
- end
- function cloaking.do_scan(pname)
- -- If player is cloaked, check for reasons to disable the cloak.
- if cloaking.players[pname] then
- local pref = minetest.get_player_by_name(pname)
- if pref then
- local pos = pref:get_pos()
- local pdata = cloaking.players[pname]
- local player_count = 0
- local mob_count = 0
- -- If there are nearby entities, disable the cloak.
- local objs = minetest.get_objects_inside_radius(pos, 5)
- for i = 1, #objs, 1 do
- if objs[i]:is_player() and objs[i]:get_hp() > 0 then
- if not gdac.player_is_admin(objs[i]) then
- player_count = player_count + 1
- end
- else
- local ent = objs[i]:get_luaentity()
- if ent and ent.mob then
- mob_count = mob_count + 1
- end
- end
- end
- local cursta = sprint.get_stamina(pref)
- -- There will always be at least one player (themselves).
- if player_count > 1 or mob_count > 0 or
- cursta <= (SPRINT_STAMINA * 0.1) then
- pdata.decloak_timer = pdata.decloak_timer + 1
- else
- if pdata.decloak_timer > 0 then
- pdata.decloak_timer = pdata.decloak_timer - 1
- end
- end
- -- Decloak if problem persists too long or totally out of energy.
- if pdata.decloak_timer > 7 or cursta == 0 then
- cloaking.toggle_cloak(pname)
- end
- -- Randomly sometimes spawn wisps. Your cloaking device works by partly
- -- moving you into a parallel dimension. Unfortunately that means stuff
- -- from the other side sometimes gets through ....
- if math_random(1, 1000) == 1 then
- cloaking.spawn_wisp(vector_round(pos))
- end
- end
- end
- -- If cloak still enabled for this player, then check again in 1 second.
- if cloaking.players[pname] then
- minetest.after(1, cloaking.do_scan, pname)
- end
- end
- function cloaking.is_cloaked(pname)
- if cloaking.players[pname] then
- return true
- end
- return false
- end
- function cloaking.disable_if_enabled(pname, combat)
- if cloaking.is_cloaked(pname) then
- cloaking.toggle_cloak(pname)
- -- If the cloak is violently broken due to combat, remaining energy is used
- -- up at once.
- if combat then
- local pref = minetest.get_player_by_name(pname)
- if pref then
- sprint.set_stamina(pref, 0)
- end
- end
- end
- end
- function cloaking.toggle_cloak(pname)
- local player = minetest.get_player_by_name(pname)
- if not player or not player:is_player() then
- return
- end
- if gdac_invis.is_invisible(pname) then
- minetest.chat_send_player(pname, "# Server: You are using the admin invisibility system! Invisibility mode will be disabled, first.")
- minetest.chat_send_player(pname, "# Server: The delay involved in switching invisibility systems may allow you to be briefly seen.")
- gdac_invis.toggle_invisibility(pname, "")
- end
- if not cloaking.players[pname] then
- if sprint.get_stamina(player) < (SPRINT_STAMINA / 2) then
- minetest.chat_send_player(pname, "# Server: Cloak requires minimum 50% energy to activate.")
- return
- end
- -- Enable cloak.
- cloaking.players[pname] = {
- decloak_timer = 0,
- }
- player_labels.disable_nametag(pname)
- -- Notify so health gauges can be removed.
- gauges.on_teleport()
- pova.set_modifier(player, "properties", {
- visual_size = {x=0, y=0},
- is_visible = false,
- pointable = false,
- show_on_minimap = false,
- }, "cloak")
- cloaking.particle_effect(utility.get_middle_pos(player:get_pos()))
- minetest.chat_send_player(pname, "# Server: Cloak activated.")
- -- Enable scanning for reasons to cancel the cloak.
- minetest.after(1, cloaking.do_scan, pname)
- minetest.after(1, cloaking.hud_effect, pname)
- else
- -- Disable cloak.
- cloaking.players[pname] = nil
- player_labels.enable_nametag(pname)
- -- Restore player properties.
- pova.remove_modifier(player, "properties", "cloak")
- cloaking.particle_effect(utility.get_middle_pos(player:get_pos()))
- minetest.chat_send_player(pname, "# Server: Cloak offline.")
- end
- end
- -- Disable cloak if player dies.
- function cloaking.on_dieplayer(player, reason)
- local pname = player:get_player_name()
- if cloaking.is_cloaked(pname) then
- -- Ensure cloak is disabled *after* player is dead (and bones spawned), not before!
- minetest.after(0, cloaking.toggle_cloak, pname)
- end
- end
- -- Cleanup player info on leave game.
- function cloaking.on_leaveplayer(player, timeout)
- local pname = player:get_player_name()
- cloaking.players[pname] = nil
- end
- if not cloaking.registered then
- minetest.register_on_dieplayer(function(...)
- cloaking.on_dieplayer(...)
- end)
- minetest.register_on_leaveplayer(function(...)
- cloaking.on_leaveplayer(...)
- end)
- local c = "cloaking:core"
- local f = cloaking.modpath .. "/init.lua"
- reload.register_file(c, f, false)
- cloaking.registered = true
- end
|