Compare commits
12 Commits
cd67eb2d19
...
071fe93cf5
Author | SHA1 | Date | |
---|---|---|---|
071fe93cf5 | |||
49a878aa03 | |||
3e304e3e5d | |||
8fc1f596d2 | |||
2c708abd88 | |||
f4a297eb30 | |||
c2f339c0a4 | |||
6f837e9e44 | |||
cd48ef801f | |||
e923729c9c | |||
fd357093e5 | |||
3c2618437a |
5
.gitattributes
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Exclusions for release export
|
||||
.* export-ignore
|
13
.github/workflows/luacheck.yml
vendored
@ -1,13 +1,10 @@
|
||||
name: luacheck
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
luacheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: apt
|
||||
run: sudo apt-get install -y luarocks
|
||||
- name: luacheck install
|
||||
run: luarocks install --local luacheck
|
||||
- name: luacheck run
|
||||
run: $HOME/.luarocks/bin/luacheck ./
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Luacheck
|
||||
uses: lunarmodules/luacheck@master
|
||||
|
10
.luacheckrc
@ -1,15 +1,13 @@
|
||||
globals = {
|
||||
"areas",
|
||||
"hangglider",
|
||||
"areas"
|
||||
}
|
||||
|
||||
read_globals = {
|
||||
-- Minetest
|
||||
"minetest",
|
||||
"vector", "ItemStack",
|
||||
|
||||
-- Mod deps
|
||||
"wardzones",
|
||||
"minetestd",
|
||||
"player_monoids"
|
||||
"player_monoids",
|
||||
"pova",
|
||||
"unifieddyes",
|
||||
}
|
||||
|
33
README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Hang Glider [hangglider]
|
||||
|
||||
[](https://github.com/mt-mods/hangglider/actions)
|
||||
[](https://content.minetest.net/packages/mt-mods/hangglider/)
|
||||
|
||||
Adds a functional hang glider for exploring. Also works as a parachute to save yourself when falling.
|
||||
|
||||
Rewritten and improved fork of https://notabug.org/Piezo_/minetest-hangglider.
|
||||
|
||||

|
||||
|
||||
## Usage
|
||||
|
||||
To deploy the hang glider, hold the item in your hand and use it (left-click). The same action also closes the hang glider when it's deployed.
|
||||
|
||||
While deployed you can glide around just like walking in the air. Your decent will be slowed until you land on a safe node, which can be any solid node, or a safe liquid like water. Upon landing the hang glider will automatically close.
|
||||
|
||||
## Coloring
|
||||
|
||||
You can color the hang glider by crafting it with any dye. Also supports all `unifieddyes` colors.
|
||||
|
||||
Note that the color will only be visible on the item if you are using Minetest 5.8.0 or above.
|
||||
|
||||
|
||||
## Repairing
|
||||
|
||||
The hang glider will wear out every time you use it. The hang glider can be repaired by crafting it with wool or paper, or any other method used to repair tools.
|
||||
|
||||
## Area Flak
|
||||
|
||||
If the `areas` mod is installed, airspace restrictions can be added to areas using the `/area_flak` command.
|
||||
|
||||
When using a hang glider in an area with flak enabled, you will get shot down a few seconds after entering the area, this reduces your HP to 1 and destroys your hang glider.
|
138
crafts.lua
Normal file
@ -0,0 +1,138 @@
|
||||
|
||||
local S = hangglider.translator
|
||||
|
||||
local has_unifieddyes = minetest.get_modpath("unifieddyes")
|
||||
|
||||
local dye_colors = {
|
||||
white = "ffffff",
|
||||
grey = "888888",
|
||||
dark_grey = "444444",
|
||||
black = "111111",
|
||||
violet = "8000ff",
|
||||
blue = "0000ff",
|
||||
cyan = "00ffff",
|
||||
dark_green = "005900",
|
||||
green = "00ff00",
|
||||
yellow = "ffff00",
|
||||
brown = "592c00",
|
||||
orange = "ff7f00",
|
||||
red = "ff0000",
|
||||
magenta = "ff00ff",
|
||||
pink = "ff7f9f",
|
||||
}
|
||||
|
||||
local translated_colors = {
|
||||
white = S("White"),
|
||||
grey = S("Grey"),
|
||||
dark_grey = S("Dark_grey"),
|
||||
black = S("Black"),
|
||||
violet = S("Violet"),
|
||||
blue = S("Blue"),
|
||||
cyan = S("Cyan"),
|
||||
dark_green = S("Dark_green"),
|
||||
green = S("Green"),
|
||||
yellow = S("Yellow"),
|
||||
brown = S("Brown"),
|
||||
orange = S("Orange"),
|
||||
red = S("Red"),
|
||||
magenta = S("Magenta"),
|
||||
pink = S("Pink"),
|
||||
}
|
||||
|
||||
local function get_dye_color(name)
|
||||
local color
|
||||
if has_unifieddyes then
|
||||
color = unifieddyes.get_color_from_dye_name(name)
|
||||
end
|
||||
if not color then
|
||||
color = string.match(name, "^dye:(.+)$")
|
||||
if color then
|
||||
color = dye_colors[color]
|
||||
end
|
||||
end
|
||||
return color
|
||||
end
|
||||
|
||||
local function get_color_name(name)
|
||||
name = string.gsub(name, "^dye:", "")
|
||||
return translated_colors[name]
|
||||
end
|
||||
|
||||
local function get_color_name_from_color(color)
|
||||
for name, color_hex in pairs(dye_colors) do
|
||||
if color == color_hex then
|
||||
return translated_colors[name]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This recipe is just a placeholder
|
||||
do
|
||||
local item = ItemStack("hangglider:hangglider")
|
||||
item:get_meta():set_string("description", S("Colored Glider"))
|
||||
minetest.register_craft({
|
||||
output = item:to_string(),
|
||||
recipe = {"hangglider:hangglider", "group:dye"},
|
||||
type = "shapeless",
|
||||
})
|
||||
end
|
||||
|
||||
-- This is what actually creates the colored hangglider
|
||||
minetest.register_on_craft(function(crafted_item, _, old_craft_grid)
|
||||
if crafted_item:get_name() ~= "hangglider:hangglider" then
|
||||
return
|
||||
end
|
||||
local wear, color, color_name
|
||||
for _,stack in ipairs(old_craft_grid) do
|
||||
local name = stack:get_name()
|
||||
if name == "hangglider:hangglider" then
|
||||
wear = stack:get_wear()
|
||||
color = stack:get_meta():get("hangglider_color")
|
||||
color_name = get_color_name_from_color(color)
|
||||
elseif minetest.get_item_group(name, "dye") ~= 0 then
|
||||
color = get_dye_color(name)
|
||||
color_name = get_color_name(name)
|
||||
elseif "wool:white" == stack:get_name()
|
||||
or "default:paper" == stack:get_name()
|
||||
then
|
||||
wear = 0
|
||||
end
|
||||
end
|
||||
if wear and color and color_name then
|
||||
if color == "ffffff" then
|
||||
return ItemStack({name = "hangglider:hangglider", wear = wear})
|
||||
end
|
||||
local meta = crafted_item:get_meta()
|
||||
meta:set_string("description", S("@1 Glider", color_name))
|
||||
meta:set_string("inventory_image", "hangglider_item.png^(hangglider_color.png^[multiply:#"..color..")")
|
||||
meta:set_string("hangglider_color", color)
|
||||
crafted_item:set_wear(wear)
|
||||
return crafted_item
|
||||
end
|
||||
end)
|
||||
|
||||
-- Repairing
|
||||
minetest.register_craft({
|
||||
output = "hangglider:hangglider",
|
||||
recipe = {
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
{"default:paper", "hangglider:hangglider", "default:paper"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "hangglider:hangglider",
|
||||
recipe = {
|
||||
{"hangglider:hangglider", "wool:white"},
|
||||
},
|
||||
})
|
||||
|
||||
-- Main craft
|
||||
minetest.register_craft({
|
||||
output = "hangglider:hangglider",
|
||||
recipe = {
|
||||
{"wool:white", "wool:white", "wool:white"},
|
||||
{"default:stick", "", "default:stick"},
|
||||
{"", "default:stick", ""},
|
||||
}
|
||||
})
|
525
init.lua
@ -1,361 +1,260 @@
|
||||
-- Hangglider mod for Minetest
|
||||
-- Original code by Piezo_ (orderofthefourthwall@gmail.com)
|
||||
-- 2018-11-14
|
||||
|
||||
-- Modifications by David G (kestral246@gmail.com)
|
||||
-- 2018-11-24
|
||||
-- For Minetest 5.x, glider's set_attach needs to be offset by 1 node
|
||||
-- Switch to alternate commented line below with correct offset.
|
||||
-- Additional tuning of parameters.
|
||||
-- Commented out debug hud display code, prefixed with "--debug:".
|
||||
hangglider = {
|
||||
translator = minetest.get_translator('hangglider'),
|
||||
}
|
||||
local S = hangglider.translator
|
||||
|
||||
-- 2018-11-22
|
||||
-- Give visual indication that hangglider is equiped.
|
||||
-- Display simple overlay with blurred struts when equiped.
|
||||
-- Issue: don't know how to disable overlay in third person view.
|
||||
-- Also Unequip hangglider when landing on water.
|
||||
-- Attempt to linearize parabolic flight path.
|
||||
-- Start gravity stronger, but gradually reduce it as descent velocity increases.
|
||||
-- Don't use airstopper when equipped from the ground (descent velocity is low).
|
||||
-- Slightly increase flight speed to 1.25.
|
||||
-- Unequip/equip cycling mid-flight should not fly farther than continuous flight.
|
||||
-- When equipping mid-air (descent velocity higher), use airstopper but increase descent slope afterwards.
|
||||
-- Create airbreak flag so all equips mid-flight use faster descent.
|
||||
-- Reset airbreak flag only when land (canExist goes false).
|
||||
-- Issue: it wouldn't reset if land in water, use fly, and launch from air, before I added test for water,
|
||||
-- not sure if there are other such cases.
|
||||
-- Temporarily add hud debug display to show descent velocity, gravity override, and airbreak flag.
|
||||
-- Still in process of tuning all the parameters.
|
||||
local has_player_monoids = minetest.get_modpath("player_monoids")
|
||||
local has_pova = minetest.get_modpath("pova")
|
||||
local has_areas = minetest.get_modpath("areas")
|
||||
|
||||
local enable_hud_overlay = minetest.settings:get_bool("hangglider.enable_hud_overlay", true)
|
||||
local enable_flak = has_areas and minetest.settings:get_bool("hangglider.enable_flak", true)
|
||||
local flak_warning_time = tonumber(minetest.settings:get("hangglider.flak_warning_time")) or 2
|
||||
local hangglider_uses = tonumber(minetest.settings:get("hangglider.uses")) or 250
|
||||
|
||||
-- Modifications by Piezo_
|
||||
-- 2018-11-25
|
||||
-- hud overlay and debug can be enabled/disabled
|
||||
-- Added blender-rendered overlay for struts using the actual model.
|
||||
-- Reduced airbreak penalty severity
|
||||
-- gave glider limited durability.
|
||||
-- Improved gravity adjustment function.
|
||||
-- Changed airbreaking process
|
||||
-- Removed airbreak penalty, as any 'advantage' seems minimal after new adjustments
|
||||
-- Removed airbreak until minetest devs are smart enough to implement better serverside players.
|
||||
-- Simplified liquid check.
|
||||
local flak_warning = S("You have entered restricted airspace!@n"
|
||||
.. "You will be shot down in @1 seconds by anti-aircraft guns!",
|
||||
flak_warning_time)
|
||||
|
||||
-- Modifications by gpcf
|
||||
-- 2018-12-09
|
||||
-- get shot down while flying over protected areas marked as no-fly-zones (flak, from German Flugabwehrkanone)
|
||||
-- set these areas with the /area_flak command
|
||||
local hanggliding_players = {}
|
||||
local hud_overlay_ids = {}
|
||||
|
||||
-- Modifications by SpaghettiToastBook
|
||||
-- 2018-12-29
|
||||
-- Physics overrides use player_monoids mod if available
|
||||
|
||||
-- Modifications by SwissalpS
|
||||
-- 2022-05-16
|
||||
-- Add Z-index to theoretically be behind hotbar and practically behind other HUDs
|
||||
|
||||
local HUD_Overlay = true --show glider struts as overlay on HUD
|
||||
local debug = false --show debug info in top-center of hud
|
||||
local moveModelUp = false
|
||||
if tonumber(string.sub(minetest.get_version().string, 1, 1)) and
|
||||
tonumber(string.sub(minetest.get_version().string, 1, 1)) > 4 then
|
||||
moveModelUp = true
|
||||
end
|
||||
hangglider = {} --Make this global, so other mods can tell if hangglider exists.
|
||||
hangglider.use = {}
|
||||
if HUD_Overlay then
|
||||
hangglider.id = {} -- hud id for displaying overlay with struts
|
||||
end
|
||||
if debug then hangglider.debug = {} end -- hud id for debug data
|
||||
--hangglider.airbreak = {} -- true if falling fast when equip
|
||||
--[[
|
||||
minetest.register_entity("hangglider:airstopper", { --A one-instant entity that catches the player and stops them.
|
||||
is_visible = false,
|
||||
physical = false,
|
||||
immortal = true,
|
||||
attach = nil,
|
||||
on_step = function(self, _)
|
||||
local canExist = false
|
||||
if self.attach then
|
||||
local player = self.attach
|
||||
if player:is_player() then
|
||||
local pname = player:get_player_name()
|
||||
canExist = true
|
||||
if player:get_player_velocity().y < 0.5 and player:get_player_velocity().y > -0.5 then
|
||||
--Let go when the player actually stops, as that's the whole point.
|
||||
if hangglider.use[pname] then
|
||||
if moveModelUp then
|
||||
minetest.add_entity(player:get_pos(), "hangglider:glider"):set_attach(player, "", {x=0,y=10,z=0}, {x=0,y=0,z=0})
|
||||
else
|
||||
minetest.add_entity(player:get_pos(), "hangglider:glider"):set_attach(player, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
end
|
||||
end
|
||||
canExist = false
|
||||
end
|
||||
end
|
||||
if not canExist then
|
||||
player:set_detach()
|
||||
end
|
||||
end
|
||||
if not canExist then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
})]]
|
||||
|
||||
if minetest.global_exists("areas") then
|
||||
hangglider.flak = true
|
||||
-- chat command definition essentially copied from areas mod.
|
||||
minetest.register_chatcommand("area_flak",{
|
||||
params = "<ID>",
|
||||
description = "Toggle airspace restrictions for area <ID>",
|
||||
if enable_flak then
|
||||
minetest.register_chatcommand("area_flak", {
|
||||
params = S("<ID>"),
|
||||
description = S("Toggle airspace restrictions for area <ID>."),
|
||||
func = function(name, param)
|
||||
local id = tonumber(param)
|
||||
if not id then
|
||||
return false, "Invalid usage, see /help area_flak."
|
||||
return false, S("Invalid usage, see /help area_flak.")
|
||||
end
|
||||
|
||||
if not areas:isAreaOwner(id, name) then
|
||||
return false, "Area "..id.." does not exist"
|
||||
.." or is not owned by you."
|
||||
return false, S("Area @1 does not exist or is not owned by you.", id)
|
||||
end
|
||||
local open = not areas.areas[id].flak
|
||||
-- Save false as nil to avoid inflating the DB.
|
||||
areas.areas[id].flak = open or nil
|
||||
areas:save()
|
||||
return true, ("Area's airspace %s."):format(open and "closed" or "opened")
|
||||
return true, S("Area @1 airspace is @2.", id,
|
||||
open and S("closed") or S("opened"))
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
hangglider.can_fly = function (pname, pos)
|
||||
-- Checks if the player will get shot down at the position
|
||||
if areas and hangglider.flak then
|
||||
local flak = false
|
||||
local owners = {}
|
||||
for _, area in pairs(areas:getAreasAtPos(pos)) do
|
||||
if area.flak then
|
||||
flak = true
|
||||
end
|
||||
owners[area.owner] = true
|
||||
local function set_hud_overlay(player, name, image)
|
||||
if not enable_hud_overlay then
|
||||
return
|
||||
end
|
||||
if not hud_overlay_ids[name] then
|
||||
hud_overlay_ids[name] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
text = image,
|
||||
position = {x = 0, y = 0},
|
||||
scale = {x = -100, y = -100},
|
||||
alignment = {x = 1, y = 1},
|
||||
offset = {x = 0, y = 0},
|
||||
z_index = -150
|
||||
})
|
||||
else
|
||||
player:hud_change(hud_overlay_ids[name], "text", image)
|
||||
end
|
||||
end
|
||||
|
||||
local function set_physics_overrides(player, overrides)
|
||||
if has_player_monoids then
|
||||
for name, value in pairs(overrides) do
|
||||
player_monoids[name]:add_change(player, value, "hangglider:glider")
|
||||
end
|
||||
if flak and not owners[pname] then
|
||||
return false
|
||||
elseif has_pova then
|
||||
pova.add_override(player:get_player_name(), "hangglider:glider",
|
||||
{jump = 0, speed = overrides.speed, gravity = overrides.gravity})
|
||||
pova.do_override(player)
|
||||
else
|
||||
player:set_physics_override(overrides)
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_physics_overrides(player)
|
||||
if has_player_monoids then
|
||||
for _, name in pairs({"jump", "speed", "gravity"}) do
|
||||
player_monoids[name]:del_change(player, "hangglider:glider")
|
||||
end
|
||||
elseif has_pova then
|
||||
pova.del_override(player:get_player_name(), "hangglider:glider")
|
||||
pova.do_override(player)
|
||||
else
|
||||
player:set_physics_override({jump = 1, speed = 1, gravity = 1})
|
||||
end
|
||||
end
|
||||
|
||||
local function can_fly(pos, name)
|
||||
if not enable_flak then
|
||||
return true
|
||||
end
|
||||
local flak = false
|
||||
local owners = {}
|
||||
for _, area in pairs(areas:getAreasAtPos(pos)) do
|
||||
if area.flak then
|
||||
flak = true
|
||||
end
|
||||
owners[area.owner] = true
|
||||
end
|
||||
if flak and not owners[name] then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
hangglider.shot_sound = function (pos)
|
||||
local function safe_node_below(pos)
|
||||
local node = minetest.get_node_or_nil(vector.new(pos.x, pos.y - 0.5, pos.z))
|
||||
if not node then
|
||||
return false
|
||||
end
|
||||
local def = minetest.registered_nodes[node.name]
|
||||
if def and (def.walkable or (def.liquidtype ~= "none" and def.damage_per_second <= 0)) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function shoot_flak_sound(pos)
|
||||
minetest.sound_play("hangglider_flak_shot", {
|
||||
pos = pos,
|
||||
max_hear_distance = 30,
|
||||
gain = 10.0,
|
||||
})
|
||||
}, true)
|
||||
end
|
||||
|
||||
local physics_attrs = {"jump", "speed", "gravity"}
|
||||
local function apply_physics_override(player, overrides)
|
||||
if minetest.get_modpath("player_monoids") then
|
||||
for _, attr in pairs(physics_attrs) do
|
||||
if overrides[attr] then
|
||||
player_monoids[attr]:add_change(player, overrides[attr], "hangglider:glider")
|
||||
end
|
||||
end
|
||||
else
|
||||
player:set_physics_override(overrides)
|
||||
end
|
||||
local function hangglider_step(self, dtime)
|
||||
local gliding = false
|
||||
local player = self.object:get_attach("parent")
|
||||
if player then
|
||||
local pos = player:get_pos()
|
||||
local name = player:get_player_name()
|
||||
if hanggliding_players[name] then
|
||||
if not safe_node_below(pos) then
|
||||
gliding = true
|
||||
local vel = player:get_velocity().y
|
||||
if vel < 0 and vel > -3 then
|
||||
set_physics_overrides(player, {
|
||||
speed = math.abs(vel / 2.0) + 1.0,
|
||||
gravity = (vel + 3) / 20,
|
||||
})
|
||||
elseif vel <= -3 then
|
||||
set_physics_overrides(player, {
|
||||
speed = 2.5,
|
||||
gravity = -0.1,
|
||||
})
|
||||
if vel < -5 then
|
||||
-- Extra airbrake when falling too fast
|
||||
player:add_velocity(vector.new(0, math.min(5, math.abs(vel / 10.0)), 0))
|
||||
end
|
||||
else -- vel > 0
|
||||
set_physics_overrides(player, {
|
||||
speed = 1.0,
|
||||
gravity = 0.25,
|
||||
})
|
||||
end
|
||||
end
|
||||
if not can_fly(pos, name) then
|
||||
if not self.flak_timer then
|
||||
self.flak_timer = 0
|
||||
shoot_flak_sound(pos)
|
||||
minetest.chat_send_player(name, flak_warning)
|
||||
else
|
||||
self.flak_timer = self.flak_timer + dtime
|
||||
end
|
||||
if self.flak_timer > flak_warning_time then
|
||||
player:set_hp(1, {type = "set_hp", cause = "hangglider:flak"})
|
||||
player:get_inventory():remove_item("main", ItemStack("hangglider:hangglider"))
|
||||
shoot_flak_sound(pos)
|
||||
gliding = false
|
||||
end
|
||||
end
|
||||
if not gliding then
|
||||
remove_physics_overrides(player)
|
||||
hanggliding_players[name] = nil
|
||||
set_hud_overlay(player, name, "blank.png")
|
||||
end
|
||||
end
|
||||
end
|
||||
if not gliding then
|
||||
self.object:set_detach()
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_physics_override(player, overrides)
|
||||
for _, attr in pairs(physics_attrs) do
|
||||
if overrides[attr] then
|
||||
if minetest.global_exists("player_monoids") then
|
||||
player_monoids[attr]:del_change(player, "hangglider:glider")
|
||||
else
|
||||
player:set_physics_override({[attr] = 1})
|
||||
end
|
||||
end
|
||||
end
|
||||
local function hangglider_use(stack, player)
|
||||
if type(player) ~= "userdata" then
|
||||
return -- Real players only
|
||||
end
|
||||
local pos = player:get_pos()
|
||||
local name = player:get_player_name()
|
||||
if not hanggliding_players[name] then
|
||||
minetest.sound_play("hanggliger_equip", {pos = pos, max_hear_distance = 8, gain = 1.0}, true)
|
||||
local entity = minetest.add_entity(pos, "hangglider:glider")
|
||||
if entity then
|
||||
entity:set_attach(player, "", vector.new(0, 10, 0), vector.new(0, 0, 0))
|
||||
local color = stack:get_meta():get("hangglider_color")
|
||||
if color then
|
||||
entity:set_properties({
|
||||
textures = {"wool_white.png^[multiply:#"..color, "default_wood.png"}
|
||||
})
|
||||
end
|
||||
set_hud_overlay(player, name, "hangglider_overlay.png")
|
||||
set_physics_overrides(player, {jump = 0, gravity = 0.25})
|
||||
hanggliding_players[name] = true
|
||||
if hangglider_uses > 0 then
|
||||
stack:add_wear(65535 / hangglider_uses)
|
||||
end
|
||||
return stack
|
||||
end
|
||||
else
|
||||
set_hud_overlay(player, name, "blank.png")
|
||||
remove_physics_overrides(player)
|
||||
hanggliding_players[name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local step_v
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
hanggliding_players[name] = nil
|
||||
remove_physics_overrides(player)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
hanggliding_players[name] = nil
|
||||
hud_overlay_ids[name] = nil
|
||||
remove_physics_overrides(player)
|
||||
end)
|
||||
|
||||
minetest.register_on_player_hpchange(function(player, hp_change, reason)
|
||||
local name = player:get_player_name()
|
||||
if hanggliding_players[name] and reason.type == "fall" then
|
||||
-- Stop all fall damage when hanggliding
|
||||
return 0, true
|
||||
end
|
||||
return hp_change
|
||||
end, true)
|
||||
|
||||
minetest.register_entity("hangglider:glider", {
|
||||
visual = "mesh",
|
||||
visual_size = {x = 12, y = 12},
|
||||
collisionbox = {0,0,0,0,0,0},
|
||||
mesh = "glider.obj",
|
||||
mesh = "hangglider.obj",
|
||||
immortal = true,
|
||||
static_save = false,
|
||||
textures = {"wool_white.png","default_wood.png"},
|
||||
on_step = function(self, dtime)
|
||||
local canExist = false
|
||||
if self.object:get_attach() then
|
||||
local player = self.object:get_attach("parent")
|
||||
if player then
|
||||
local pos = player:get_pos()
|
||||
local pname = player:get_player_name()
|
||||
if hangglider.use[pname] then
|
||||
local mrn_name = minetest.registered_nodes[minetest.get_node(vector.new(pos.x, pos.y-0.5, pos.z)).name]
|
||||
if mrn_name then
|
||||
if not (mrn_name.walkable or mrn_name.liquidtype ~= "none") then
|
||||
canExist = true
|
||||
|
||||
step_v = player:get_velocity().y
|
||||
if step_v < 0 and step_v > -3 then
|
||||
apply_physics_override(player, {speed=math.abs(step_v/2) + 0.75})
|
||||
elseif step_v <= -3 then --Cap our gliding movement speed.
|
||||
apply_physics_override(player, {speed=2.25})
|
||||
else
|
||||
remove_physics_override(player, {speed=1})
|
||||
end
|
||||
if debug then
|
||||
player:hud_change(hangglider.debug[pname].id, "text", step_v..', '..
|
||||
player:get_physics_override().gravity..', '..tostring(hangglider.airbreak[pname]))
|
||||
end
|
||||
apply_physics_override(player, {gravity=((step_v + 3)/20)})
|
||||
end
|
||||
end
|
||||
end
|
||||
if not hangglider.can_fly(pname,pos) then
|
||||
if not self.warned then -- warning shot
|
||||
self.warned = 0
|
||||
hangglider.shot_sound(pos)
|
||||
minetest.chat_send_player(pname, "Protected area! You will be shot down in two seconds by anti-aircraft guns!")
|
||||
end
|
||||
self.warned = self.warned + dtime
|
||||
if self.warned > 2 then -- shoot down
|
||||
player:set_hp(1)
|
||||
player:get_inventory():remove_item("main", ItemStack("hangglider:hangglider"))
|
||||
hangglider.shot_sound(pos)
|
||||
canExist = false
|
||||
end
|
||||
end
|
||||
if not canExist then
|
||||
|
||||
remove_physics_override(player, { gravity=1, jump = 1, speed = 1,})
|
||||
hangglider.use[pname] = false
|
||||
if HUD_Overlay then
|
||||
player:hud_change(hangglider.id[pname], "text", "blank.png")
|
||||
end
|
||||
--hangglider.airbreak[pname] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
if not canExist then
|
||||
self.object:set_detach()
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
textures = {"wool_white.png", "default_wood.png"},
|
||||
on_step = hangglider_step,
|
||||
})
|
||||
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
remove_physics_override(player, {
|
||||
gravity = 1,
|
||||
jump = 1,
|
||||
})
|
||||
hangglider.use[player:get_player_name()] = false
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local pname = player:get_player_name()
|
||||
remove_physics_override(player, {
|
||||
gravity = 1,
|
||||
jump = 1,
|
||||
})
|
||||
hangglider.use[pname] = false
|
||||
if HUD_Overlay then
|
||||
hangglider.id[pname] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
text = "blank.png",
|
||||
position = {x=0, y=0},
|
||||
scale = {x=-100, y=-100},
|
||||
alignment = {x=1, y=1},
|
||||
offset = {x=0, y=0},
|
||||
z_index = -150
|
||||
})
|
||||
end
|
||||
if debug then
|
||||
hangglider.debug[pname] = {id = player:hud_add({hud_elem_type = "text",
|
||||
position = {x=0.5, y=0.1},
|
||||
text = "-",
|
||||
number = 0xFF0000}), -- red text
|
||||
-- ht = {50,50,50},
|
||||
}
|
||||
end
|
||||
--hangglider.airbreak[pname] = false
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local pname = player:get_player_name()
|
||||
hangglider.use[pname] = nil
|
||||
if HUD_Overlay then hangglider.id[pname] = nil end
|
||||
if debug then hangglider.debug[pname] = nil end
|
||||
--hangglider.airbreak[pname] = nil
|
||||
end)
|
||||
|
||||
minetest.register_tool("hangglider:hangglider", {
|
||||
description = "Glider",
|
||||
inventory_image = "glider_item.png",
|
||||
stack_max=1,
|
||||
on_use = function(itemstack, player)
|
||||
if not player or player.is_fake_player then
|
||||
-- player does not exist or is created from an automated machine (fake_player)
|
||||
return
|
||||
end
|
||||
local pos = player:get_pos()
|
||||
local pname = player:get_player_name()
|
||||
if not hangglider.use[pname] then --Equip
|
||||
minetest.sound_play("bedsheet", {pos=pos, max_hear_distance = 8, gain = 1.0})
|
||||
if HUD_Overlay then player:hud_change(hangglider.id[pname], "text", "glider_struts.png") end
|
||||
local airbreak = false
|
||||
--[[if vel < -1.5 then -- engage mid-air, falling fast, so stop but ramp velocity more quickly
|
||||
--hangglider.airbreak[pname] = true
|
||||
airbreak = true
|
||||
local stopper = minetest.add_entity(pos, "hangglider:airstopper")
|
||||
minetest.after(0, function(stopper, player) --"Extreme Measures"
|
||||
stopper:set_pos(player:get_pos())
|
||||
stopper:get_luaentity().attach = player
|
||||
player:set_attach( stopper, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
end, stopper, player)
|
||||
end]]
|
||||
if not airbreak then
|
||||
if moveModelUp then
|
||||
minetest.add_entity(pos, "hangglider:glider"):set_attach(player, "", {x=0,y=10,z=0}, {x=0,y=0,z=0})
|
||||
else
|
||||
minetest.add_entity(pos, "hangglider:glider"):set_attach(player, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
|
||||
end
|
||||
end
|
||||
hangglider.use[pname] = true
|
||||
apply_physics_override(player, {jump = 0})
|
||||
-- if minetest 0.4.x use this:
|
||||
|
||||
-- if minetest 5.x use this:
|
||||
-- minetest.add_entity(player:get_pos(), "hangglider:glider"):set_attach(player, "", {x=0,y=10,z=0}, {x=0,y=0,z=0})
|
||||
itemstack:set_wear(itemstack:get_wear() + 255)
|
||||
return itemstack
|
||||
elseif hangglider.use[pname] then --Unequip
|
||||
if HUD_Overlay then player:hud_change(hangglider.id[pname], "text", "default_wood.png^[colorize:#0000:255") end
|
||||
hangglider.use[pname] = false
|
||||
end
|
||||
end,
|
||||
description = S("Glider"),
|
||||
inventory_image = "hangglider_item.png",
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
on_use = hangglider_use,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "hangglider:hangglider",
|
||||
recipe = {"default:paper", "default:paper", "default:paper",
|
||||
"default:paper", "hangglider:hangglider", "default:paper",
|
||||
"default:paper", "default:paper", "default:paper"
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "hangglider:hangglider",
|
||||
recipe = {
|
||||
{"wool:white", "wool:white", "wool:white"},
|
||||
{"default:stick", "", "default:stick"},
|
||||
{"", "default:stick", ""},
|
||||
}
|
||||
})
|
||||
dofile(minetest.get_modpath("hangglider").."/crafts.lua")
|
||||
|
28
locale/hangglider.ca.tr
Normal file
@ -0,0 +1,28 @@
|
||||
# textdomain: hangglider
|
||||
White=blanc
|
||||
Grey=gris
|
||||
Dark_grey=gris fosc
|
||||
Black=negre
|
||||
Violet=violeta
|
||||
Blue=blau
|
||||
Cyan=cian
|
||||
Dark_green=verd fosc
|
||||
Green=verd
|
||||
Yellow=groc
|
||||
Brown=marró
|
||||
Orange=taronja
|
||||
Red=vermell
|
||||
Magenta=magenta
|
||||
Pink=rosa
|
||||
Colored Glider=Planador de color
|
||||
@1 Glider=Planador @1
|
||||
You have entered restricted airspace!@@You will be shot down in @1 seconds by anti-aircraft guns!=Has entrat a l'espai aeri restringit!@@Seràs abatut en @1 segons per canons antiaeris!
|
||||
<ID>=
|
||||
Toggle airspace restrictions for area <ID>.=Activa o desactiva les restriccions d'espai aeri per a l'àrea <ID>.
|
||||
Invalid usage, see /help area_flak.=Ús no vàlid, consulta /help area_flak.
|
||||
Area @1 does not exist or is not owned by you.=L'àrea @1 no existeix o no és propietat teva.
|
||||
Area @1 airspace is @2.=L'àrea @1 espai aeri és @2.
|
||||
closed=tancat
|
||||
opened=obert
|
||||
Glider=Planador
|
||||
|
28
locale/hangglider.de.tr
Normal file
@ -0,0 +1,28 @@
|
||||
# textdomain: hangglider
|
||||
White=Weisser
|
||||
Grey=Grauer
|
||||
Dark_grey=Dunkelgrauer
|
||||
Black=Schwarzer
|
||||
Violet=Violeter
|
||||
Blue=Blauer
|
||||
Cyan=Cyan farbener
|
||||
Dark_green=Dunkelgrüner
|
||||
Green=Grüner
|
||||
Yellow=Gelber
|
||||
Brown=Brauner
|
||||
Orange=Orange farbener
|
||||
Red=Roter
|
||||
Magenta=Magenta farbener
|
||||
Pink=Rosa
|
||||
Colored Glider=Farbiger Gleitschirm
|
||||
@1 Glider=@1 Gleitschirm
|
||||
You have entered restricted airspace!@@You will be shot down in @1 seconds by anti-aircraft guns!=Du bist in eingeschränktem Luftraum eingedrungen!@nDu wirst in @1 Sekunden von FLAK abgeschossen.
|
||||
<ID>=
|
||||
Toggle airspace restrictions for area <ID>.=Luftraumbeschränkungen für Gebiet <ID> umschalten.
|
||||
Invalid usage, see /help area_flak.=Ungültige Verwendung, siehe /help area_flak.=
|
||||
Area @1 does not exist or is not owned by you.=Gebiet @1 existiert nicht oder es gehört dir nicht.
|
||||
Area @1 airspace is @2.=Gebiet @1 Luftraum ist @2.
|
||||
closed=eingeschränkt
|
||||
opened=geöffnet
|
||||
Glider=Gleitschirm
|
||||
|
28
locale/hangglider.es.tr
Normal file
@ -0,0 +1,28 @@
|
||||
# textdomain: hangglider
|
||||
White=blanco
|
||||
Grey=gris
|
||||
Dark_grey=gris oscuro
|
||||
Black=negro
|
||||
Violet=violeta
|
||||
Blue=azul
|
||||
Cyan=cian
|
||||
Dark_green=verde oscuro
|
||||
Green=verde
|
||||
Yellow=amarillo
|
||||
Brown=marrón
|
||||
Orange=naranja
|
||||
Red=rojo
|
||||
Magenta=magenta
|
||||
Pink=rosa
|
||||
Colored Glider=Planeador Colorizado
|
||||
@1 Glider=Planeador @1
|
||||
You have entered restricted airspace!@@You will be shot down in @1 seconds by anti-aircraft guns!=¡Has entrado en espacio aéreo restringido!@n¡Serás derribado en @1 segundos por cañones antiaéreos!
|
||||
<ID>=
|
||||
Toggle airspace restrictions for area <ID>.=Alternar restricciones de espacio aéreo para el área <ID>.
|
||||
Invalid usage, see /help area_flak.=Uso no válido, consulta /help area_flak.
|
||||
Area @1 does not exist or is not owned by you.=El área @1 no existe o no es tuya.
|
||||
Area @1 airspace is @2.=Área @1 espacio aéreo está @2.
|
||||
closed=cerrado
|
||||
opened=abierto
|
||||
Glider=Planeador
|
||||
|
28
locale/template.txt
Normal file
@ -0,0 +1,28 @@
|
||||
# textdomain: hangglider
|
||||
White=
|
||||
Grey=
|
||||
Dark_grey=
|
||||
Black=
|
||||
Violet=
|
||||
Blue=
|
||||
Cyan=
|
||||
Dark_green=
|
||||
Green=
|
||||
Yellow=
|
||||
Brown=
|
||||
Orange=
|
||||
Red=
|
||||
Magenta=
|
||||
Pink=
|
||||
Colored Glider=
|
||||
@1 Glider=
|
||||
You have entered restricted airspace!@@You will be shot down in @1 seconds by anti-aircraft guns!=
|
||||
<ID>=
|
||||
Toggle airspace restrictions for area <ID>.=
|
||||
Invalid usage, see /help area_flak.=
|
||||
Area @1 does not exist or is not owned by you.=
|
||||
Area @1 airspace is @2.=
|
||||
closed=
|
||||
opened=
|
||||
Glider=
|
||||
|
7
mod.conf
@ -1,4 +1,5 @@
|
||||
name = hangglider
|
||||
depends = default, wool
|
||||
optional_depends = areas, player_monoids
|
||||
min_minetest_version = 5.0
|
||||
description = Adds a functional hang glider for exploring
|
||||
depends = default, wool, dye
|
||||
optional_depends = areas, player_monoids, pova, unifieddyes
|
||||
min_minetest_version = 5.0
|
||||
|
0
models/glider.obj → models/hangglider.obj
Executable file → Normal file
BIN
screenshot.png
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 346 KiB |
11
settingtypes.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# The number of times the hangglider can be used before breaking. Set to 0 for infinite uses.
|
||||
hangglider.uses (Hangglider uses) int 250
|
||||
|
||||
# If true, an image of the hangglider struts is shown on the hud when gliding.
|
||||
hangglider.enable_hud_overlay (Enable overlay) bool true
|
||||
|
||||
# If enabled, and the `areas` mod is installed, enables airspace restrictions to be added to areas.
|
||||
hangglider.enable_flak (Enable flak) bool true
|
||||
|
||||
# Time in seconds before hanggliders get shot down when flying in restricted airspace
|
||||
hangglider.flak_warning_time (Flak warning time) float 2
|
BIN
sounds/hanggliger_equip.ogg
Normal file
Before Width: | Height: | Size: 174 B |
Before Width: | Height: | Size: 28 KiB |
BIN
textures/hangglider_color.png
Normal file
After Width: | Height: | Size: 95 B |
BIN
textures/hangglider_item.png
Normal file
After Width: | Height: | Size: 129 B |
BIN
textures/hangglider_overlay.png
Normal file
After Width: | Height: | Size: 18 KiB |