Noch mehr mods
26
mods/.caverealms_old/LICENSE.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2017, Craig Robbins and contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
31
mods/.caverealms_old/README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# caverealms-lite
|
||||
|
||||
Based on the original minetest-caverealms mod (https://github.com/HeroOfTheWinds/minetest-caverealms/).
|
||||
|
||||
Adds underground realms to minetest.
|
||||
|
||||
This caverealms fork provides all the biomes and decorations from the original caverealms, with several additions and without the overhead of generating caves. This lowers the server resources the mod requires, for example CPU and RAM. This also removes the large lava spills created by the original caverealms.
|
||||
|
||||
It is specifically written to work with the mgvalleys mapgen, but will work using other mapgens as well. The mapgen used will determine the shape and size of individual caves. Mapgens that generate only smaller caves may be less suitable for use with this fork than mgvalleys.
|
||||
|
||||
Note: For worlds where the original caverealms is already in use, this fork is not advised as a replacement. If used in this way, some unknown nodes and other minor issues should be expected.
|
||||
|
||||
|
||||
## License and Contributors
|
||||
|
||||
Source code: FreeBSD License (Simplified)
|
||||
The original caverealms was licensed as WTFPL.
|
||||
|
||||
Contributors:
|
||||
- Zeno, Shara RedCat - This rewrite
|
||||
- HeroOfTheWinds, Zeno - Original mod
|
||||
|
||||
|
||||
## Recommended Additions
|
||||
|
||||
- VanessaE's HDX texturepacks provide alternative textures. For example,
|
||||
https://gitlab.com/VanessaE/hdx-128.
|
||||
- ethereal mod unlocks additional content (https://notabug.org/tenplus1/ethereal).
|
||||
- mobs_monster mod allows Dungeon Masters to spawn in the Dungeon Master's Lair biome (https://notabug.org/tenplus1/mobs_monster).
|
||||
- mobs_redo is required to run mobs_monster (https://notabug.org/tenplus1/mobs_redo).
|
||||
- abritorch adds coloured torches made with caverealms items (https://github.com/Ezhh/abritorch).
|
53
mods/.caverealms_old/config.lua
Normal file
|
@ -0,0 +1,53 @@
|
|||
local CONFIG_FILE_PREFIX = "caverealms."
|
||||
|
||||
caverealms.config = {}
|
||||
|
||||
-- This function based on kaeza/minetest-irc/config.lua and used under the
|
||||
-- terms of BSD 2-clause license.
|
||||
local function setting(stype, name, default)
|
||||
local value
|
||||
if stype == "bool" then
|
||||
value = minetest.settings:get_bool(CONFIG_FILE_PREFIX..name)
|
||||
elseif stype == "string" then
|
||||
value = minetest.settings:get(CONFIG_FILE_PREFIX..name)
|
||||
elseif stype == "number" then
|
||||
value = tonumber(minetest.settings:get(CONFIG_FILE_PREFIX..name))
|
||||
end
|
||||
if value == nil then
|
||||
value = default
|
||||
end
|
||||
caverealms.config[name] = value
|
||||
end
|
||||
|
||||
--generation settings
|
||||
setting("number", "ymin", -10000) --bottom realm limit
|
||||
setting("number", "ymax", -4096) --top realm limit
|
||||
setting("number", "tcave", 0.75) --cave threshold
|
||||
|
||||
--decoration chances
|
||||
setting("number", "stagcha", 0.03) --chance of stalagmites (was 0.003)
|
||||
setting("number", "stalcha", 0.03) --chance of stalactites(was 0.003)
|
||||
|
||||
setting("number", "h_lag", 8) --max height for stalagmites
|
||||
setting("number", "h_lac", 8) --...stalactites
|
||||
setting("number", "crystal", 0.02) --chance of glow crystal formations (was 0.0002)
|
||||
setting("number", "h_cry", 8) --max height of glow crystals
|
||||
setting("number", "h_clac", 8) --max height of glow crystal stalactites
|
||||
|
||||
setting("number", "gemcha", 0.03) --chance of small glow gems
|
||||
setting("number", "mushcha", 0.04) --chance of mushrooms
|
||||
setting("number", "myccha", 0.03) --chance of mycena mushrooms
|
||||
setting("number", "wormcha", 0.015) --chance of glow worms
|
||||
setting("number", "giantcha", 0.001) --chance of giant mushrooms
|
||||
setting("number", "icicha", 0.035) --chance of icicles
|
||||
setting("number", "flacha", 0.04) --chance of constant flames
|
||||
|
||||
--realm limits for Dungeon Masters' Lair
|
||||
setting("number", "dm_top", -8000) --upper limit
|
||||
setting("number", "dm_bot", -10000) --lower limit
|
||||
|
||||
--should DMs spawn in DM Lair?
|
||||
setting("bool", "dm_spawn", true)
|
||||
|
||||
--Deep cave settings
|
||||
setting("number", "deep_cave", -7000) -- upper limit
|
145
mods/.caverealms_old/crafting.lua
Normal file
|
@ -0,0 +1,145 @@
|
|||
--thin ice to water
|
||||
minetest.register_craft({
|
||||
output = "default:water_source",
|
||||
type = "shapeless",
|
||||
recipe = {"caverealms:thin_ice"}
|
||||
})
|
||||
|
||||
--use for coal dust
|
||||
minetest.register_craft({
|
||||
output = "default:coalblock",
|
||||
recipe = {
|
||||
{"caverealms:coal_dust","caverealms:coal_dust","caverealms:coal_dust"},
|
||||
{"caverealms:coal_dust","caverealms:coal_dust","caverealms:coal_dust"},
|
||||
{"caverealms:coal_dust","caverealms:coal_dust","caverealms:coal_dust"}
|
||||
}
|
||||
})
|
||||
|
||||
-- DM statue
|
||||
minetest.register_craft({
|
||||
output = "caverealms:dm_statue",
|
||||
recipe = {
|
||||
{"caverealms:glow_ore","caverealms:hot_cobble","caverealms:glow_ore"},
|
||||
{"caverealms:hot_cobble","caverealms:hot_cobble","caverealms:hot_cobble"},
|
||||
{"caverealms:hot_cobble","caverealms:hot_cobble","caverealms:hot_cobble"}
|
||||
}
|
||||
})
|
||||
|
||||
-- Glow obsidian brick
|
||||
minetest.register_craft({
|
||||
output = "caverealms:glow_obsidian_brick 4",
|
||||
recipe = {
|
||||
{"caverealms:glow_obsidian", "caverealms:glow_obsidian"},
|
||||
{"caverealms:glow_obsidian", "caverealms:glow_obsidian"}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "caverealms:glow_obsidian_brick_2 4",
|
||||
recipe = {
|
||||
{"caverealms:glow_obsidian_2", "caverealms:glow_obsidian_2"},
|
||||
{"caverealms:glow_obsidian_2", "caverealms:glow_obsidian_2"}
|
||||
}
|
||||
})
|
||||
|
||||
-- Glow obsidian glass
|
||||
minetest.register_craft({
|
||||
output = "caverealms:glow_obsidian_glass 5",
|
||||
recipe = {
|
||||
{"default:glass", "default:glass", "default:glass"},
|
||||
{"default:glass", "default:glass", "caverealms:glow_obsidian"}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "caverealms:glow_obsidian_glass 5",
|
||||
recipe = {
|
||||
{"default:glass", "default:glass", "default:glass"},
|
||||
{"default:glass", "default:glass", "caverealms:glow_obsidian_2"}
|
||||
}
|
||||
})
|
||||
|
||||
-- Requires ethereal:fish_raw
|
||||
if minetest.get_modpath("ethereal") then
|
||||
|
||||
-- Professional Fishing Rod
|
||||
minetest.register_craftitem("caverealms:angler_rod", {
|
||||
description = "Pro Fishing Rod",
|
||||
inventory_image = "caverealms_angler_rod.png",
|
||||
wield_image = "caverealms_angler_rod.png"
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "caverealms:angler_rod",
|
||||
recipe = {
|
||||
{"","","default:steel_ingot"},
|
||||
{"", "default:steel_ingot", "caverealms:mushroom_gills"},
|
||||
{"default:steel_ingot", "", "caverealms:mushroom_gills"},
|
||||
}
|
||||
})
|
||||
|
||||
-- Glow Bait
|
||||
minetest.register_craftitem("caverealms:glow_bait", {
|
||||
description = "Glow Bait",
|
||||
inventory_image = "caverealms_glow_bait.png",
|
||||
wield_image = "caverealms_glow_bait.png",
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "caverealms:glow_bait 9",
|
||||
recipe = {
|
||||
{"caverealms:glow_worm_green"},
|
||||
}
|
||||
})
|
||||
|
||||
-- default ethereal fish
|
||||
local fish = {
|
||||
{"ethereal:fish_raw"},
|
||||
}
|
||||
|
||||
-- Pro Fishing Rod (Baited)
|
||||
minetest.register_craftitem("caverealms:angler_rod_baited", {
|
||||
description = "Baited Pro Fishing Rod",
|
||||
inventory_image = "caverealms_angler_rod_baited.png",
|
||||
wield_image = "caverealms_angler_rod_weild.png",
|
||||
stack_max = 1,
|
||||
liquids_pointable = true,
|
||||
|
||||
on_use = function (itemstack, user, pointed_thing)
|
||||
|
||||
if pointed_thing.type ~= "node" then
|
||||
return
|
||||
end
|
||||
|
||||
local node = minetest.get_node(pointed_thing.under).name
|
||||
|
||||
if (node == "default:water_source"
|
||||
or node == "default:river_water_source")
|
||||
and math.random(1, 100) < 35 then
|
||||
|
||||
local type = fish[math.random(1, #fish)][1]
|
||||
local inv = user:get_inventory()
|
||||
|
||||
if inv:room_for_item("main", {name = type}) then
|
||||
|
||||
inv:add_item("main", {name = type})
|
||||
|
||||
if (math.random() < 0.6) then
|
||||
return ItemStack("caverealms:angler_rod_baited")
|
||||
else
|
||||
return ItemStack("caverealms:angler_rod")
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(user:get_player_name(),
|
||||
"Inventory full, Fish Got Away!")
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "caverealms:angler_rod_baited",
|
||||
recipe = {"caverealms:angler_rod", "caverealms:glow_bait"},
|
||||
})
|
||||
end
|
1
mods/.caverealms_old/description.txt
Normal file
|
@ -0,0 +1 @@
|
|||
A mod for Minetest to add underground realms.
|
19
mods/.caverealms_old/docs/caverealms_lite_biomes.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
Biome #, Biome name, "floor node"
|
||||
|
||||
|
||||
0, None
|
||||
1, Moss, "caverealms:stone_with_moss"
|
||||
2, Fungal, "caverealms:stone_with_lichen"
|
||||
3, Algae, "caverealms:stone_with_algae"
|
||||
4, Glaciated, "caverealms:thin_ice"
|
||||
|
||||
The following are "deep realms"
|
||||
|
||||
5, Deep Glaciated, "default:ice"
|
||||
6, DM, "caverealms:hot_cobble"
|
||||
7, Salt Crystal, "caverealms:stone_with_salt"
|
||||
8, Glow Obsidian, "caverealms:glow_obsidian"
|
||||
OR "caverealms:glow_obsidian2"
|
||||
9, Coal, "default:coalblock"
|
||||
OR "caverealms:coal_dust"
|
||||
OR "default:desert_sand"
|
16
mods/.caverealms_old/dungeon_master.lua
Normal file
|
@ -0,0 +1,16 @@
|
|||
mobs:spawn({
|
||||
name = "mobs_monster:dungeon_master",
|
||||
nodes = {"caverealms:hot_cobble"},
|
||||
max_light = 12,
|
||||
min_light = 0,
|
||||
chance = 7000,
|
||||
active_object_count = 2,
|
||||
max_height = -8000,
|
||||
on_spawn = function(self, pos)
|
||||
self.hp_max = 70
|
||||
self.health = 70
|
||||
self.damage = 5
|
||||
self.shoot_interval = 1.5
|
||||
self.dogshoot_switch = 0
|
||||
end
|
||||
})
|
409
mods/.caverealms_old/functions.lua
Normal file
|
@ -0,0 +1,409 @@
|
|||
local H_LAG = caverealms.config.h_lag --15 --max height for stalagmites
|
||||
local H_LAC = caverealms.config.h_lac --20 --...stalactites
|
||||
local H_CRY = caverealms.config.h_cry --9 --max height of glow crystals
|
||||
local H_CLAC = caverealms.config.h_clac --13 --max height of glow crystal stalactites
|
||||
|
||||
function caverealms:above_solid(x,y,z,area,data)
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
local ai = area:index(x,y+1,z-3)
|
||||
if data[ai] == c_air then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function caverealms:below_solid(x,y,z,area,data)
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
local ai = area:index(x,y-1,z-3)
|
||||
if data[ai] == c_air then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--stalagmite spawner
|
||||
function caverealms:stalagmite(x,y,z, area, data)
|
||||
|
||||
if not caverealms:below_solid(x,y,z,area,data) then
|
||||
return
|
||||
end
|
||||
|
||||
--contest ids
|
||||
local c_stone = minetest.get_content_id("default:stone")
|
||||
|
||||
local top = math.random(6,H_LAG) --grab a random height for the stalagmite
|
||||
for j = 0, top do --y
|
||||
for k = -3, 3 do
|
||||
for l = -3, 3 do
|
||||
if j == 0 then
|
||||
if k*k + l*l <= 9 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
elseif j <= top/5 then
|
||||
if k*k + l*l <= 4 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
elseif j <= top/5 * 3 then
|
||||
if k*k + l*l <= 1 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
else
|
||||
local vi = area:index(x, y+j, z-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--stalactite spawner
|
||||
function caverealms:stalactite(x,y,z, area, data)
|
||||
|
||||
if not caverealms:above_solid(x,y,z,area,data) then
|
||||
return
|
||||
end
|
||||
|
||||
--contest ids
|
||||
local c_stone = minetest.get_content_id("default:stone")--("caverealms:limestone")
|
||||
|
||||
local bot = math.random(-H_LAC, -6) --grab a random height for the stalagmite
|
||||
for j = bot, 0 do --y
|
||||
for k = -3, 3 do
|
||||
for l = -3, 3 do
|
||||
if j >= -1 then
|
||||
if k*k + l*l <= 9 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
elseif j >= bot/5 then
|
||||
if k*k + l*l <= 4 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
elseif j >= bot/5 * 3 then
|
||||
if k*k + l*l <= 1 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
else
|
||||
local vi = area:index(x, y+j, z-3)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--glowing crystal stalagmite spawner
|
||||
function caverealms:crystal_stalagmite(x,y,z, area, data, biome)
|
||||
|
||||
if not caverealms:below_solid(x,y,z,area,data) then
|
||||
return
|
||||
end
|
||||
|
||||
--contest ids
|
||||
local c_stone = minetest.get_content_id("default:stone")
|
||||
local c_crystal = minetest.get_content_id("caverealms:glow_crystal")
|
||||
local c_crystore = minetest.get_content_id("caverealms:glow_ore")
|
||||
local c_emerald = minetest.get_content_id("caverealms:glow_emerald")
|
||||
local c_emore = minetest.get_content_id("caverealms:glow_emerald_ore")
|
||||
local c_mesecry = minetest.get_content_id("caverealms:glow_mese")
|
||||
local c_meseore = minetest.get_content_id("default:stone_with_mese")
|
||||
local c_ruby = minetest.get_content_id("caverealms:glow_ruby")
|
||||
local c_rubore = minetest.get_content_id("caverealms:glow_ruby_ore")
|
||||
local c_ameth = minetest.get_content_id("caverealms:glow_amethyst")
|
||||
local c_amethore = minetest.get_content_id("caverealms:glow_amethyst_ore")
|
||||
local c_ice = minetest.get_content_id("default:ice")
|
||||
local c_thinice = minetest.get_content_id("caverealms:thin_ice")
|
||||
|
||||
--for randomness
|
||||
local mode = 1
|
||||
if math.random(15) == 1 then
|
||||
mode = 2
|
||||
end
|
||||
if biome == 3 then
|
||||
if math.random(25) == 1 then
|
||||
mode = 2
|
||||
else
|
||||
mode = 1
|
||||
end
|
||||
end
|
||||
if biome == 4 or biome == 5 then
|
||||
if math.random(3) == 1 then
|
||||
mode = 2
|
||||
end
|
||||
end
|
||||
|
||||
local stalids = {
|
||||
{ {c_crystore, c_crystal}, {c_emore, c_emerald} },
|
||||
{ {c_emore, c_emerald}, {c_crystore, c_crystal} },
|
||||
{ {c_emore, c_emerald}, {c_meseore, c_mesecry} },
|
||||
{ {c_ice, c_thinice}, {c_crystore, c_crystal}},
|
||||
{ {c_ice, c_thinice}, {c_crystore, c_crystal}},
|
||||
{ {c_rubore, c_ruby}, {c_meseore, c_mesecry}},
|
||||
{ {c_crystore, c_crystal}, {c_rubore, c_ruby} },
|
||||
{ {c_rubore, c_ruby}, {c_emore, c_emerald}},
|
||||
{ {c_amethore, c_ameth}, {c_meseore, c_mesecry} },
|
||||
}
|
||||
|
||||
local nid_a
|
||||
local nid_b
|
||||
local nid_s = c_stone --stone base, will be rewritten to ice in certain biomes
|
||||
|
||||
if biome > 3 and biome < 6 then
|
||||
if mode == 1 then
|
||||
nid_a = c_ice
|
||||
nid_b = c_thinice
|
||||
nid_s = c_ice
|
||||
else
|
||||
nid_a = c_crystore
|
||||
nid_b = c_crystal
|
||||
end
|
||||
elseif mode == 1 then
|
||||
nid_a = stalids[biome][1][1]
|
||||
nid_b = stalids[biome][1][2]
|
||||
else
|
||||
nid_a = stalids[biome][2][1]
|
||||
nid_b = stalids[biome][2][2]
|
||||
end
|
||||
|
||||
local top = math.random(5,H_CRY) --grab a random height for the stalagmite
|
||||
for j = 0, top do --y
|
||||
for k = -3, 3 do
|
||||
for l = -3, 3 do
|
||||
if j == 0 then
|
||||
if k*k + l*l <= 9 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = nid_s
|
||||
end
|
||||
elseif j <= top/5 then
|
||||
if k*k + l*l <= 4 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = nid_a
|
||||
end
|
||||
elseif j <= top/5 * 3 then
|
||||
if k*k + l*l <= 1 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = nid_b
|
||||
end
|
||||
else
|
||||
local vi = area:index(x, y+j, z-3)
|
||||
data[vi] = nid_b
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--crystal stalactite spawner
|
||||
function caverealms:crystal_stalactite(x,y,z, area, data, biome)
|
||||
|
||||
if not caverealms:above_solid(x,y,z,area,data) then
|
||||
return
|
||||
end
|
||||
|
||||
--contest ids
|
||||
local c_stone = minetest.get_content_id("default:stone")
|
||||
local c_crystore = minetest.get_content_id("caverealms:glow_ore")
|
||||
local c_crystal = minetest.get_content_id("caverealms:glow_crystal")
|
||||
local c_emerald = minetest.get_content_id("caverealms:glow_emerald")
|
||||
local c_emore = minetest.get_content_id("caverealms:glow_emerald_ore")
|
||||
local c_mesecry = minetest.get_content_id("caverealms:glow_mese")
|
||||
local c_meseore = minetest.get_content_id("default:stone_with_mese")
|
||||
local c_ruby = minetest.get_content_id("caverealms:glow_ruby")
|
||||
local c_rubore = minetest.get_content_id("caverealms:glow_ruby_ore")
|
||||
local c_ameth = minetest.get_content_id("caverealms:glow_amethyst")
|
||||
local c_amethore = minetest.get_content_id("caverealms:glow_amethyst_ore")
|
||||
local c_ice = minetest.get_content_id("default:ice")
|
||||
local c_thinice = minetest.get_content_id("caverealms:hanging_thin_ice")
|
||||
|
||||
--for randomness
|
||||
local mode = 1
|
||||
if math.random(15) == 1 then
|
||||
mode = 2
|
||||
end
|
||||
if biome == 3 then
|
||||
if math.random(25) == 1 then
|
||||
mode = 2
|
||||
else
|
||||
mode = 1
|
||||
end
|
||||
end
|
||||
if biome == 4 or biome == 5 then
|
||||
if math.random(3) == 1 then
|
||||
mode = 2
|
||||
end
|
||||
end
|
||||
|
||||
local stalids = {
|
||||
{ {c_crystore, c_crystal}, {c_emore, c_emerald} },
|
||||
{ {c_emore, c_emerald}, {c_crystore, c_crystal} },
|
||||
{ {c_emore, c_emerald}, {c_meseore, c_mesecry} },
|
||||
{ {c_ice, c_thinice}, {c_crystore, c_crystal}},
|
||||
{ {c_ice, c_thinice}, {c_crystore, c_crystal}},
|
||||
{ {c_rubore, c_ruby}, {c_meseore, c_mesecry}},
|
||||
{ {c_crystore, c_crystal}, {c_rubore, c_ruby} },
|
||||
{ {c_rubore, c_ruby}, {c_emore, c_emerald}},
|
||||
{ {c_amethore, c_ameth}, {c_meseore, c_mesecry} },
|
||||
}
|
||||
|
||||
local nid_a
|
||||
local nid_b
|
||||
local nid_s = c_stone --stone base, will be rewritten to ice in certain biomes
|
||||
|
||||
if biome > 3 and biome < 6 then
|
||||
if mode == 1 then
|
||||
nid_a = c_ice
|
||||
nid_b = c_thinice
|
||||
nid_s = c_ice
|
||||
else
|
||||
nid_a = c_crystore
|
||||
nid_b = c_crystal
|
||||
end
|
||||
elseif mode == 1 then
|
||||
nid_a = stalids[biome][1][1]
|
||||
nid_b = stalids[biome][1][2]
|
||||
else
|
||||
nid_a = stalids[biome][2][1]
|
||||
nid_b = stalids[biome][2][2]
|
||||
end
|
||||
|
||||
local bot = math.random(-H_CLAC, -6) --grab a random height for the stalagmite
|
||||
for j = bot, 0 do --y
|
||||
for k = -3, 3 do
|
||||
for l = -3, 3 do
|
||||
if j >= -1 then
|
||||
if k*k + l*l <= 9 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = nid_s
|
||||
end
|
||||
elseif j >= bot/5 then
|
||||
if k*k + l*l <= 4 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = nid_a
|
||||
end
|
||||
elseif j >= bot/5 * 3 then
|
||||
if k*k + l*l <= 1 then
|
||||
local vi = area:index(x+k, y+j, z+l-3)
|
||||
data[vi] = nid_b
|
||||
end
|
||||
else
|
||||
local vi = area:index(x, y+j, z-3)
|
||||
data[vi] = nid_b
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--glowing crystal stalagmite spawner
|
||||
function caverealms:salt_stalagmite(x,y,z, area, data, biome)
|
||||
|
||||
if not caverealms:below_solid(x,y,z,area,data) then
|
||||
return
|
||||
end
|
||||
|
||||
--contest ids
|
||||
local c_stone = minetest.get_content_id("default:stone")
|
||||
local c_salt = minetest.get_content_id("caverealms:salt_crystal")
|
||||
|
||||
local scale = math.random(2, 4)
|
||||
if scale == 2 then
|
||||
for j = -3, 3 do
|
||||
for k = -3, 3 do
|
||||
local vi = area:index(x+j, y, z+k)
|
||||
data[vi] = c_stone
|
||||
if math.abs(j) ~= 3 and math.abs(k) ~= 3 then
|
||||
local vi = area:index(x+j, y+1, z+k)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for j = -4, 4 do
|
||||
for k = -4, 4 do
|
||||
local vi = area:index(x+j, y, z+k)
|
||||
data[vi] = c_stone
|
||||
if math.abs(j) ~= 4 and math.abs(k) ~= 4 then
|
||||
local vi = area:index(x+j, y+1, z+k)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for j = 2, scale + 2 do --y
|
||||
for k = -2, scale - 2 do
|
||||
for l = -2, scale - 2 do
|
||||
local vi = area:index(x+k, y+j, z+l)
|
||||
data[vi] = c_salt -- make cube
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--function to create giant 'shrooms
|
||||
function caverealms:giant_shroom(x, y, z, area, data)
|
||||
|
||||
if not caverealms:below_solid(x,y,z,area,data) then
|
||||
return
|
||||
end
|
||||
|
||||
local c_cap
|
||||
local c_stem
|
||||
|
||||
--as usual, grab the content ID's
|
||||
if minetest.get_modpath("ethereal") then
|
||||
c_stem = minetest.get_content_id("ethereal:mushroom_trunk")
|
||||
c_cap = minetest.get_content_id("ethereal:mushroom")
|
||||
else
|
||||
c_stem = minetest.get_content_id("caverealms:mushroom_stem")
|
||||
c_cap = minetest.get_content_id("caverealms:mushroom_cap")
|
||||
end
|
||||
|
||||
local c_gills = minetest.get_content_id("caverealms:mushroom_gills")
|
||||
|
||||
z = z - 5
|
||||
--cap
|
||||
for k = -5, 5 do
|
||||
for l = -5, 5 do
|
||||
if k*k + l*l <= 25 then
|
||||
local vi = area:index(x+k, y+5, z+l)
|
||||
data[vi] = c_cap
|
||||
end
|
||||
if k*k + l*l <= 16 then
|
||||
local vi = area:index(x+k, y+6, z+l)
|
||||
data[vi] = c_cap
|
||||
vi = area:index(x+k, y+5, z+l)
|
||||
data[vi] = c_gills
|
||||
end
|
||||
if k*k + l*l <= 9 then
|
||||
local vi = area:index(x+k, y+7, z+l)
|
||||
data[vi] = c_cap
|
||||
end
|
||||
if k*k + l*l <= 4 then
|
||||
local vi = area:index(x+k, y+8, z+l)
|
||||
data[vi] = c_cap
|
||||
end
|
||||
end
|
||||
end
|
||||
--stem
|
||||
for j = 0, 5 do
|
||||
for k = -1,1 do
|
||||
local vi = area:index(x+k, y+j, z)
|
||||
data[vi] = c_stem
|
||||
if k == 0 then
|
||||
local ai = area:index(x, y+j, z+1)
|
||||
data[ai] = c_stem
|
||||
ai = area:index(x, y+j, z-1)
|
||||
data[ai] = c_stem
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
24
mods/.caverealms_old/init.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
-- caverealms v.0.8 by HeroOfTheWinds
|
||||
-- original cave code modified from paramat's subterrain
|
||||
-- For Minetest 0.4.8 stable
|
||||
-- Depends default
|
||||
-- License: code WTFPL
|
||||
|
||||
caverealms = {} --create a container for functions and constants
|
||||
|
||||
--grab a shorthand for the filepath of the mod
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
--load companion lua files
|
||||
dofile(modpath.."/config.lua") --configuration file; holds various constants
|
||||
dofile(modpath.."/crafting.lua") --crafting recipes
|
||||
dofile(modpath.."/nodes.lua") --node definitions
|
||||
dofile(modpath.."/functions.lua") --function definitions
|
||||
dofile(modpath.."/plants.lua")
|
||||
dofile(modpath.."/biomes.lua")
|
||||
|
||||
if minetest.get_modpath("mobs_monster") then
|
||||
if caverealms.config.dm_spawn == true then
|
||||
dofile(modpath.."/dungeon_master.lua") --special DMs for DM's Lair biome
|
||||
end
|
||||
end
|
1
mods/.caverealms_old/mod.conf
Normal file
|
@ -0,0 +1 @@
|
|||
name = caverealms
|
521
mods/.caverealms_old/nodes.lua
Normal file
|
@ -0,0 +1,521 @@
|
|||
-- CaveRealms nodes.lua
|
||||
|
||||
--NODES--
|
||||
|
||||
--glowing crystal
|
||||
minetest.register_node("caverealms:glow_crystal", {
|
||||
description = "Glow Sapphire",
|
||||
tiles = {"caverealms_glow_crystal.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 13,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
})
|
||||
|
||||
--glowing emerald
|
||||
minetest.register_node("caverealms:glow_emerald", {
|
||||
description = "Glow Emerald",
|
||||
tiles = {"caverealms_glow_emerald.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 13,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
})
|
||||
|
||||
--glowing mese crystal blocks
|
||||
minetest.register_node("caverealms:glow_mese", {
|
||||
description = "Glow Mese Crystal",
|
||||
tiles = {"caverealms_glow_mese.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 13,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
})
|
||||
|
||||
--glowing ruby
|
||||
minetest.register_node("caverealms:glow_ruby", {
|
||||
description = "Glow Ruby",
|
||||
tiles = {"caverealms_glow_ruby.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 13,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
})
|
||||
|
||||
--glowing amethyst
|
||||
minetest.register_node("caverealms:glow_amethyst", {
|
||||
description = "Glow Amethyst",
|
||||
tiles = {"caverealms_glow_amethyst.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 13,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
})
|
||||
|
||||
--embedded crystal
|
||||
minetest.register_node("caverealms:glow_ore", {
|
||||
description = "Glow Crystal Ore",
|
||||
tiles = {"caverealms_glow_ore.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=2},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 10,
|
||||
paramtype = "light",
|
||||
})
|
||||
|
||||
--embedded emerald
|
||||
minetest.register_node("caverealms:glow_emerald_ore", {
|
||||
description = "Glow Emerald Ore",
|
||||
tiles = {"caverealms_glow_emerald_ore.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=2},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 10,
|
||||
paramtype = "light",
|
||||
})
|
||||
|
||||
--embedded ruby
|
||||
minetest.register_node("caverealms:glow_ruby_ore", {
|
||||
description = "Glow Ruby Ore",
|
||||
tiles = {"caverealms_glow_ruby_ore.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=2},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 10,
|
||||
paramtype = "light",
|
||||
})
|
||||
|
||||
--embedded amethyst
|
||||
minetest.register_node("caverealms:glow_amethyst_ore", {
|
||||
description = "Glow Amethyst Ore",
|
||||
tiles = {"caverealms_glow_amethyst_ore.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=2},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 10,
|
||||
paramtype = "light",
|
||||
})
|
||||
|
||||
--thin (transparent) ice
|
||||
minetest.register_node("caverealms:thin_ice", {
|
||||
description = "Thin Ice",
|
||||
tiles = {"caverealms_thin_ice.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
freezemelt = "default:water_source",
|
||||
paramtype = "light",
|
||||
})
|
||||
|
||||
--salt crystal
|
||||
minetest.register_node("caverealms:salt_crystal", {
|
||||
description = "Salt Crystal",
|
||||
tiles = {"caverealms_salt_crystal.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=2},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 11,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
})
|
||||
|
||||
--glowing crystal gem
|
||||
minetest.register_node("caverealms:glow_gem", {
|
||||
description = "Glow Gem",
|
||||
tiles = {"caverealms_glow_gem.png"},
|
||||
inventory_image = "caverealms_glow_gem.png",
|
||||
wield_image = "caverealms_glow_gem.png",
|
||||
is_ground_content = true,
|
||||
groups = {cracky = 3, oddly_breakable_by_hand = 1, attached_node = 1},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 11,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 0.75,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
||||
}
|
||||
})
|
||||
|
||||
--glowing salt gem
|
||||
minetest.register_node("caverealms:salt_gem", {
|
||||
description = "Salt Gem",
|
||||
tiles = {"caverealms_salt_gem.png"},
|
||||
inventory_image = "caverealms_salt_gem.png",
|
||||
wield_image = "caverealms_salt_gem.png",
|
||||
is_ground_content = true,
|
||||
groups = {cracky = 3, oddly_breakable_by_hand = 1, attached_node = 1},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 11,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 0.75,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
||||
}
|
||||
})
|
||||
|
||||
--stone spike
|
||||
minetest.register_node("caverealms:spike", {
|
||||
description = "Stone Spike",
|
||||
tiles = {"caverealms_spike.png"},
|
||||
inventory_image = "caverealms_spike.png",
|
||||
wield_image = "caverealms_spike.png",
|
||||
is_ground_content = true,
|
||||
groups = {cracky = 3, oddly_breakable_by_hand = 1, attached_node = 1},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
light_source = 3,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 0.75,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
--upward pointing icicle
|
||||
minetest.register_node("caverealms:icicle_up", {
|
||||
description = "Icicle",
|
||||
tiles = {"caverealms_icicle_up.png"},
|
||||
inventory_image = "caverealms_icicle_up.png",
|
||||
wield_image = "caverealms_icicle_up.png",
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3, oddly_breakable_by_hand=1},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 8,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 1.0,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
||||
},
|
||||
})
|
||||
|
||||
--downward pointing icicle
|
||||
minetest.register_node("caverealms:icicle_down", {
|
||||
description = "Icicle",
|
||||
tiles = {"caverealms_icicle_down.png"},
|
||||
inventory_image = "caverealms_icicle_down.png",
|
||||
wield_image = "caverealms_icicle_down.png",
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3, oddly_breakable_by_hand=1},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
light_source = 8,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 1.0,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
||||
},
|
||||
})
|
||||
|
||||
--cave mossy cobble - bluish?
|
||||
minetest.register_node("caverealms:stone_with_moss", {
|
||||
description = "Cave Stone with Moss",
|
||||
tiles = {"default_cobble.png^caverealms_moss.png", "default_cobble.png", "default_cobble.png^caverealms_moss_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=1, cracky=3},
|
||||
drop = 'default:cobble',
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
|
||||
--cave lichen-covered cobble - purple-ish
|
||||
minetest.register_node("caverealms:stone_with_lichen", {
|
||||
description = "Cave Stone with Lichen",
|
||||
tiles = {"default_cobble.png^caverealms_lichen.png", "default_cobble.png", "default_cobble.png^caverealms_lichen_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=1, cracky=3},
|
||||
drop = 'default:cobble',
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
|
||||
--cave algae-covered cobble - yellow-ish
|
||||
minetest.register_node("caverealms:stone_with_algae", {
|
||||
description = "Cave Stone with Algae",
|
||||
tiles = {"default_cobble.png^caverealms_algae.png", "default_cobble.png", "default_cobble.png^caverealms_algae_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=1, cracky=3},
|
||||
drop = 'default:cobble',
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
|
||||
--tiny-salt-crystal-covered cobble - pink-ish
|
||||
minetest.register_node("caverealms:stone_with_salt", {
|
||||
description = "Salt Crystal",
|
||||
tiles = {"caverealms_salty2.png"},
|
||||
light_source = 9,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
--Hot Cobble - cobble with lava instead of mortar XD
|
||||
minetest.register_node("caverealms:hot_cobble", {
|
||||
description = "Hot Cobble",
|
||||
tiles = {"caverealms_hot_cobble.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=1, hot=1, unbreakable = 1, stone = 1},
|
||||
damage_per_second = 1,
|
||||
light_source = 3,
|
||||
paramtype = "light",
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
--Glow Obsidian
|
||||
minetest.register_node("caverealms:glow_obsidian", {
|
||||
description = "Glowing Obsidian",
|
||||
tiles = {"caverealms_glow_obsidian.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=1, level=2},
|
||||
light_source = 7,
|
||||
paramtype = "light",
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
--Glow Obsidian 2 - has traces of lava
|
||||
minetest.register_node("caverealms:glow_obsidian_2", {
|
||||
description = "Hot Glowing Obsidian",
|
||||
tiles = {"caverealms_glow_obsidian2.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=1, hot=1, level=2},
|
||||
light_source = 9,
|
||||
paramtype = "light",
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
--Glow Obsidian Bricks
|
||||
minetest.register_node("caverealms:glow_obsidian_brick", {
|
||||
description = "Glow Obsidian Brick",
|
||||
tiles = {"caverealms_glow_obsidian_brick.png"},
|
||||
light_source = 7,
|
||||
groups = {cracky = 1, level = 2},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("caverealms:glow_obsidian_brick_2", {
|
||||
description = "Glow Obsidian Brick",
|
||||
tiles = {"caverealms_glow_obsidian_brick_2.png"},
|
||||
light_source = 9,
|
||||
groups = {cracky = 1, level = 2},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
--Glow Obsidian Stairs/Slabs
|
||||
stairs.register_stair_and_slab(
|
||||
"glow_obsidian_brick",
|
||||
"caverealms:glow_obsidian_brick",
|
||||
{cracky = 1, level = 2},
|
||||
{"caverealms_glow_obsidian_brick.png"},
|
||||
"Glow Obsidian Brick Stair",
|
||||
"Glow Obsidian Brick Slab",
|
||||
default.node_sound_stone_defaults())
|
||||
|
||||
stairs.register_stair_and_slab(
|
||||
"glow_obsidian_brick_2",
|
||||
"caverealms:glow_obsidian_brick_2",
|
||||
{cracky = 1, level = 2},
|
||||
{"caverealms_glow_obsidian_brick_2.png"},
|
||||
"Glow Obsidian Brick Stair",
|
||||
"Glow Obsidian Brick Slab",
|
||||
default.node_sound_stone_defaults())
|
||||
|
||||
--Glow Obsidian Glass
|
||||
minetest.register_node("caverealms:glow_obsidian_glass", {
|
||||
description = "Glow Obsidian Glass",
|
||||
drawtype = "glasslike_framed_optional",
|
||||
tiles = {"caverealms_glow_obsidian_glass.png", "default_obsidian_glass_detail.png"},
|
||||
paramtype = "light",
|
||||
light_source = 13,
|
||||
sunlight_propagates = true,
|
||||
groups = {cracky = 3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
--Coal Dust
|
||||
minetest.register_node("caverealms:coal_dust", {
|
||||
description = "Coal Dust",
|
||||
tiles = {"caverealms_coal_dust.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3, falling_node=1, sand=1},
|
||||
sounds = default.node_sound_sand_defaults(),
|
||||
})
|
||||
|
||||
--glow worms
|
||||
minetest.register_node("caverealms:glow_worm", {
|
||||
description = "Blue Glow Worms",
|
||||
tiles = {"caverealms_glow_worm.png"},
|
||||
inventory_image = "caverealms_glow_worm.png",
|
||||
wield_image = "caverealms_glow_worm.png",
|
||||
is_ground_content = true,
|
||||
groups = {oddly_breakable_by_hand=3},
|
||||
light_source = 9,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 1.0,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/6, -1/2, -1/6, 1/6, 1/2, 1/6},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node("caverealms:glow_worm_green", {
|
||||
description = "Green Glow Worms",
|
||||
tiles = {"caverealms_glow_worm_green.png"},
|
||||
inventory_image = "caverealms_glow_worm_green.png",
|
||||
wield_image = "caverealms_glow_worm_green.png",
|
||||
is_ground_content = true,
|
||||
groups = {oddly_breakable_by_hand=3},
|
||||
light_source = 9,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 1.0,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/6, -1/2, -1/6, 1/6, 1/2, 1/6},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node("caverealms:fire_vine", {
|
||||
description = "Fire Vine",
|
||||
tiles = {"caverealms_fire_vine.png"},
|
||||
inventory_image = "caverealms_fire_vine.png",
|
||||
wield_image = "caverealms_fire_vine.png",
|
||||
is_ground_content = true,
|
||||
damage_per_second = 1,
|
||||
groups = {oddly_breakable_by_hand=3},
|
||||
light_source = 9,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 1.0,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/6, -1/2, -1/6, 1/6, 1/2, 1/6},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
--define special flame so that it does not expire
|
||||
minetest.register_node("caverealms:constant_flame", {
|
||||
description = "Fire",
|
||||
drawtype = "plantlike",
|
||||
tiles = {{
|
||||
name="fire_basic_flame_animated.png",
|
||||
animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=1},
|
||||
}},
|
||||
inventory_image = "fire_basic_flame.png",
|
||||
light_source = 14,
|
||||
groups = {igniter=2, dig_immediate=3, hot=3, not_in_creative_inventory=1},
|
||||
paramtype = "light",
|
||||
drop = '',
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
floodable = true,
|
||||
damage_per_second = 4,
|
||||
})
|
||||
|
||||
--dungeon master statue (nodebox)
|
||||
minetest.register_node("caverealms:dm_statue", {
|
||||
description = "Dungeon Master Statue",
|
||||
tiles = {
|
||||
"caverealms_dm_stone.png",
|
||||
"caverealms_dm_stone.png",
|
||||
"caverealms_dm_stone.png",
|
||||
"caverealms_dm_stone.png",
|
||||
"caverealms_dm_stone.png",
|
||||
"caverealms_stone_eyes.png"
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.4375, -0.5, -0.4375, 0.4375, -0.3125, 0.4375}, -- NodeBox1
|
||||
{-0.25, -0.125, -0.1875, 0.25, 0.5, 0.1875}, -- NodeBox2
|
||||
{-0.375, 0, -0.125, -0.25, 0.4375, 0.125}, -- NodeBox3
|
||||
{0.25, 0.125, -0.4375, 0.375, 0.375, 0.1875}, -- NodeBox4
|
||||
{-0.25, -0.5, -0.125, -0.125, -0.125, 0.125}, -- NodeBox5
|
||||
{0.125, -0.3125, -0.125, 0.25, 0, 0.125}, -- NodeBox6
|
||||
}
|
||||
},
|
||||
selection_box = {
|
||||
type = "regular"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
-- Compatibility
|
||||
minetest.register_alias("caverealms:hanging_thin_ice", "caverealms:thin_ice")
|
||||
|
||||
minetest.register_alias("caverealms:spike_2", "caverealms:spike")
|
||||
minetest.register_alias("caverealms:spike_3", "caverealms:spike")
|
||||
minetest.register_alias("caverealms:spike_4", "caverealms:spike")
|
||||
minetest.register_alias("caverealms:spike_5", "caverealms:spike")
|
||||
|
||||
minetest.register_alias("caverealms:salt_gem_2", "caverealms:salt_gem")
|
||||
minetest.register_alias("caverealms:salt_gem_3", "caverealms:salt_gem")
|
||||
minetest.register_alias("caverealms:salt_gem_4", "caverealms:salt_gem")
|
||||
minetest.register_alias("caverealms:salt_gem_5", "caverealms:salt_gem")
|
||||
|
||||
minetest.register_alias("caverealms:glow_gem_2", "caverealms:glow_gem")
|
||||
minetest.register_alias("caverealms:glow_gem_3", "caverealms:glow_gem")
|
||||
minetest.register_alias("caverealms:glow_gem_4", "caverealms:glow_gem")
|
||||
minetest.register_alias("caverealms:glow_gem_5", "caverealms:glow_gem")
|
191
mods/.caverealms_old/plants.lua
Normal file
|
@ -0,0 +1,191 @@
|
|||
-- Cavrealms plants and trees for lichen, moss and algae biomes
|
||||
|
||||
-- Lichen biome
|
||||
|
||||
-- glowing fungi
|
||||
minetest.register_node("caverealms:fungus", {
|
||||
description = "Glowing Fungus",
|
||||
tiles = {"caverealms_fungi.png"},
|
||||
inventory_image = "caverealms_fungi.png",
|
||||
wield_image = "caverealms_fungi.png",
|
||||
is_ground_content = true,
|
||||
groups = {oddly_breakable_by_hand = 3, attached_node = 1, flammable = 1},
|
||||
light_source = 5,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 1.0,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
||||
},
|
||||
})
|
||||
|
||||
-- mycena mushroom
|
||||
minetest.register_node("caverealms:mycena", {
|
||||
description = "Mycena Mushroom",
|
||||
tiles = {"caverealms_mycena.png"},
|
||||
inventory_image = "caverealms_mycena.png",
|
||||
wield_image = "caverealms_mycena.png",
|
||||
is_ground_content = true,
|
||||
groups = {oddly_breakable_by_hand = 3, attached_node = 1, flammable = 1},
|
||||
light_source = 6,
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
buildable_to = true,
|
||||
visual_scale = 1.0,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
||||
},
|
||||
})
|
||||
|
||||
-- giant mushroom
|
||||
if minetest.get_modpath("ethereal") then
|
||||
minetest.register_alias("caverealms:mushroom_cap", "ethereal:mushroom")
|
||||
minetest.register_alias("caverealms:mushroom_stem", "ethereal:mushroom_trunk")
|
||||
else
|
||||
-- stem
|
||||
minetest.register_node("caverealms:mushroom_stem", {
|
||||
description = "Giant Mushroom Stem",
|
||||
tiles = {"caverealms_mushroom_stem.png"},
|
||||
is_ground_content = true,
|
||||
groups = {choppy=2, oddly_breakable_by_hand=1},
|
||||
})
|
||||
|
||||
-- cap
|
||||
minetest.register_node("caverealms:mushroom_cap", {
|
||||
description = "Giant Mushroom Cap",
|
||||
tiles = {"caverealms_mushroom_cap.png"},
|
||||
is_ground_content = true,
|
||||
groups = {choppy=2, oddly_breakable_by_hand=1,},
|
||||
drop = {
|
||||
max_items = 1,
|
||||
items = {
|
||||
{items = {"caverealms:mushroom_sapling"}, rarity = 20},
|
||||
{items = {"caverealms:mushroom_cap"}}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
-- sapling
|
||||
minetest.register_node("caverealms:mushroom_sapling", {
|
||||
description = "Mushroom Tree Sapling",
|
||||
drawtype = "plantlike",
|
||||
tiles = {"caverealms_mushroom_sapling.png"},
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-4 / 16, -0.5, -4 / 16, 4 / 16, 7 / 16, 4 / 16}
|
||||
},
|
||||
groups = {snappy = 2, dig_immediate = 3, flammable = 2},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
end
|
||||
|
||||
-- gills
|
||||
minetest.register_node("caverealms:mushroom_gills", {
|
||||
description = "Giant Mushroom Gills",
|
||||
tiles = {"caverealms_mushroom_gills.png"},
|
||||
is_ground_content = true,
|
||||
light_source = 10,
|
||||
walkable = false,
|
||||
groups = {choppy=2, oddly_breakable_by_hand=1},
|
||||
drawtype = "plantlike",
|
||||
paramtype = "light",
|
||||
})
|
||||
|
||||
|
||||
-- Saplings
|
||||
|
||||
-- grow trees
|
||||
local add_tree = function (pos, ofx, ofy, ofz, schem)
|
||||
if not schem then
|
||||
print ("Schematic not found")
|
||||
return
|
||||
end
|
||||
minetest.swap_node(pos, {name = "air"})
|
||||
minetest.place_schematic(
|
||||
{x = pos.x - ofx, y = pos.y - ofy, z = pos.z - ofz},
|
||||
schem, 0, nil, false)
|
||||
end
|
||||
|
||||
local path = minetest.get_modpath("caverealms").."/schematics/"
|
||||
|
||||
-- giant mushrooms
|
||||
function grow_caverealms_mushroom(pos)
|
||||
add_tree(pos, 5, 0, 5, path .. "shroom.mts")
|
||||
end
|
||||
|
||||
-- height check
|
||||
local function enough_height(pos, height)
|
||||
local nod = minetest.line_of_sight(
|
||||
{x = pos.x, y = pos.y + 1, z = pos.z},
|
||||
{x = pos.x, y = pos.y + height, z = pos.z})
|
||||
if not nod then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Caverealms grow sapling",
|
||||
nodenames = {"ethereal:mushroom_sapling", "caverealms:mushroom_sapling"},
|
||||
interval = 10,
|
||||
chance = 50,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
local light_level = minetest.get_node_light(pos)
|
||||
-- check light level
|
||||
if not light_level or light_level > 10 then
|
||||
return
|
||||
end
|
||||
-- get node under sapling
|
||||
local under = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}).name
|
||||
-- check if registered
|
||||
if not minetest.registered_nodes[node.name] then
|
||||
return
|
||||
end
|
||||
-- ethereal sapling on lichen stone
|
||||
if node.name == "ethereal:mushroom_sapling"
|
||||
and under == "caverealms:stone_with_lichen"
|
||||
and enough_height(pos, 10) then
|
||||
grow_caverealms_mushroom(pos)
|
||||
-- caverealms sapling on lichen stone
|
||||
elseif node.name == "caverealms:mushroom_sapling"
|
||||
and under == "caverealms:stone_with_lichen"
|
||||
and enough_height(pos, 10) then
|
||||
grow_caverealms_mushroom(pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- spread moss/lichen/algae to nearby cobblestone
|
||||
minetest.register_abm({
|
||||
label = "Caverealms stone spread",
|
||||
nodenames = {
|
||||
"caverealms:stone_with_moss",
|
||||
"caverealms:stone_with_lichen",
|
||||
"caverealms:stone_with_algae",
|
||||
},
|
||||
neighbors = {"air"},
|
||||
interval = 16,
|
||||
chance = 50,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
local num = minetest.find_nodes_in_area_under_air(
|
||||
{x = pos.x - 1, y = pos.y - 2, z = pos.z - 1},
|
||||
{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1},
|
||||
"default:cobble")
|
||||
if #num > 0 then
|
||||
minetest.set_node(num[math.random(#num)], {name = node.name})
|
||||
end
|
||||
end,
|
||||
})
|
BIN
mods/.caverealms_old/schematics/shroom.mts
Normal file
BIN
mods/.caverealms_old/textures/caverealms_algae.png
Normal file
After Width: | Height: | Size: 739 B |
BIN
mods/.caverealms_old/textures/caverealms_algae_side.png
Normal file
After Width: | Height: | Size: 446 B |
BIN
mods/.caverealms_old/textures/caverealms_angler_rod.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
mods/.caverealms_old/textures/caverealms_angler_rod_baited.png
Normal file
After Width: | Height: | Size: 273 B |
BIN
mods/.caverealms_old/textures/caverealms_angler_rod_weild.png
Normal file
After Width: | Height: | Size: 260 B |
BIN
mods/.caverealms_old/textures/caverealms_coal_dust.png
Normal file
After Width: | Height: | Size: 288 B |
BIN
mods/.caverealms_old/textures/caverealms_dm_stone.png
Normal file
After Width: | Height: | Size: 590 B |
BIN
mods/.caverealms_old/textures/caverealms_fire_vine.png
Normal file
After Width: | Height: | Size: 554 B |
BIN
mods/.caverealms_old/textures/caverealms_fungi.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_amethyst.png
Normal file
After Width: | Height: | Size: 325 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_amethyst_ore.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_bait.png
Normal file
After Width: | Height: | Size: 168 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_crystal.png
Normal file
After Width: | Height: | Size: 330 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_emerald.png
Normal file
After Width: | Height: | Size: 330 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_emerald_ore.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_gem.png
Normal file
After Width: | Height: | Size: 248 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_mese.png
Normal file
After Width: | Height: | Size: 330 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_obsidian.png
Normal file
After Width: | Height: | Size: 162 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_obsidian2.png
Normal file
After Width: | Height: | Size: 245 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_obsidian_brick.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3 KiB |
BIN
mods/.caverealms_old/textures/caverealms_glow_obsidian_glass.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
mods/.caverealms_old/textures/caverealms_glow_ore.png
Normal file
After Width: | Height: | Size: 345 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_ruby.png
Normal file
After Width: | Height: | Size: 330 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_ruby_ore.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_worm.png
Normal file
After Width: | Height: | Size: 406 B |
BIN
mods/.caverealms_old/textures/caverealms_glow_worm_green.png
Normal file
After Width: | Height: | Size: 351 B |
BIN
mods/.caverealms_old/textures/caverealms_hot_cobble.png
Normal file
After Width: | Height: | Size: 431 B |
BIN
mods/.caverealms_old/textures/caverealms_icicle_down.png
Normal file
After Width: | Height: | Size: 161 B |
BIN
mods/.caverealms_old/textures/caverealms_icicle_up.png
Normal file
After Width: | Height: | Size: 158 B |
BIN
mods/.caverealms_old/textures/caverealms_lichen.png
Normal file
After Width: | Height: | Size: 925 B |
BIN
mods/.caverealms_old/textures/caverealms_lichen_side.png
Normal file
After Width: | Height: | Size: 437 B |
BIN
mods/.caverealms_old/textures/caverealms_moss.png
Normal file
After Width: | Height: | Size: 754 B |
BIN
mods/.caverealms_old/textures/caverealms_moss_side.png
Normal file
After Width: | Height: | Size: 457 B |
BIN
mods/.caverealms_old/textures/caverealms_mushroom_cap.png
Normal file
After Width: | Height: | Size: 172 B |
BIN
mods/.caverealms_old/textures/caverealms_mushroom_gills.png
Normal file
After Width: | Height: | Size: 141 B |
BIN
mods/.caverealms_old/textures/caverealms_mushroom_sapling.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
mods/.caverealms_old/textures/caverealms_mushroom_stem.png
Normal file
After Width: | Height: | Size: 402 B |
BIN
mods/.caverealms_old/textures/caverealms_mycena.png
Normal file
After Width: | Height: | Size: 240 B |
BIN
mods/.caverealms_old/textures/caverealms_salt_crystal.png
Normal file
After Width: | Height: | Size: 402 B |
BIN
mods/.caverealms_old/textures/caverealms_salt_gem.png
Normal file
After Width: | Height: | Size: 243 B |
BIN
mods/.caverealms_old/textures/caverealms_salty2.png
Normal file
After Width: | Height: | Size: 330 B |
BIN
mods/.caverealms_old/textures/caverealms_spike.png
Normal file
After Width: | Height: | Size: 248 B |
BIN
mods/.caverealms_old/textures/caverealms_stone_eyes.png
Normal file
After Width: | Height: | Size: 662 B |
BIN
mods/.caverealms_old/textures/caverealms_thin_ice.png
Normal file
After Width: | Height: | Size: 679 B |
BIN
mods/.caverealms_old/textures/fire_basic_flame.png
Normal file
After Width: | Height: | Size: 719 B |
BIN
mods/.caverealms_old/textures/fire_basic_flame_animated.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
46
mods/airutils/.luacheckrc
Normal file
|
@ -0,0 +1,46 @@
|
|||
-- Disable some (non critical) warnings
|
||||
-- unused = false
|
||||
unused_args = false
|
||||
redefined = false
|
||||
|
||||
globals = {
|
||||
"airutils",
|
||||
}
|
||||
|
||||
read_globals = {
|
||||
"DIR_DELIM",
|
||||
"ItemStack",
|
||||
"PseudoRandom",
|
||||
"basic_machines",
|
||||
"biomass",
|
||||
"climate_api",
|
||||
"core",
|
||||
"creative",
|
||||
"default",
|
||||
"dump",
|
||||
"emote",
|
||||
"math",
|
||||
"mcl_formspec",
|
||||
"mcl_player",
|
||||
"minetest",
|
||||
"player_api",
|
||||
"signs_lib",
|
||||
"skins",
|
||||
"string",
|
||||
"technic",
|
||||
"vector",
|
||||
"wardrobe",
|
||||
}
|
||||
|
||||
-- Per file options
|
||||
files["airutils_biofuel.lua"] = {
|
||||
globals = {"basic_machines.grinder_recipes"},
|
||||
}
|
||||
|
||||
files["lib_planes/utilities.lua"] = {
|
||||
globals = {"player_api.player_attached.?", "mcl_player.player_attached.?"}
|
||||
}
|
||||
|
||||
files["pilot_skin_manager.lua"] = {
|
||||
globals = {"skins.skin_class.apply_skin_to_player"}
|
||||
}
|
37
mods/airutils/LICENSE
Normal file
|
@ -0,0 +1,37 @@
|
|||
Except for the file "text.lua", adapted from signs_lib from VanessaE,
|
||||
that is licenced under LGPL 3.0 (see at: https://www.gnu.org/licenses/lgpl-3.0.txt)
|
||||
all the code is licenced under MIT Licence, as below:
|
||||
|
||||
==================================================================================================
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 APercy - Alexsandro Percy
|
||||
Copyright (c) 2019 TheTermos (for code from mobkit at physics_lib.lua)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
==================================================================================================
|
||||
|
||||
Media Licence:
|
||||
|
||||
CC0-1.0 for all media
|
||||
the "airutils_explode.ogg" comes from minetest game tnt mod
|
||||
|
||||
|
16
mods/airutils/README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# airutils
|
||||
Airport Utils for Minetest
|
||||
|
||||
This mod is a lib and offers utilities to be used in airports.
|
||||
We have only 2 items now, but will be expanded as needed.
|
||||
|
||||
The first is PAPI (Precision Approach Path Indicator), to guide you in approaching landings. I recommend this article from wikipedia to understand how it works: https://en.wikipedia.org/wiki/Precision ... _indicator
|
||||
|
||||
The PAPI is usually located on the left-hand side of the runway at right angles to the runway center line, so, if you want to place it at right side, just right click it to invert lights order.
|
||||
|
||||
|
||||
The second, the tug, allows the repositioning of aircraft that may be blocking the runway or taxiways. In my mods only the owner can fly his own plane, so with this tool, if the person owns the area or the area has no owner, it is possible to move the aircraft without the presence of the pilot. Just click to move, and shift + click to rotate in your direction
|
||||
|
||||
Except the media listed bellow, all media licence is CC0
|
||||
pilot_novaskin_girl.png adapted from Pilot Girl - https://minecraft.novaskin.me/skin/254193054/Pilot-girl
|
||||
pilot_novaskin_girl_steampunk.png from girl steampunk pilot - https://minecraft.novaskin.me/skin/6190203356577792/girl-steampunk-pilot
|
267
mods/airutils/airutils_biofuel.lua
Normal file
|
@ -0,0 +1,267 @@
|
|||
----------
|
||||
--biofuel
|
||||
----------
|
||||
local S = airutils.S
|
||||
local module_name = "airutils"
|
||||
|
||||
if core.get_modpath("technic") then
|
||||
if technic then
|
||||
technic.register_extractor_recipe({input = {"farming:wheat 33"}, output = "biofuel:biofuel 1"})
|
||||
technic.register_extractor_recipe({input = {"farming:corn 33"}, output = "biofuel:biofuel 1"})
|
||||
technic.register_extractor_recipe({input = {"farming:potato 33"}, output = "biofuel:biofuel 1"})
|
||||
technic.register_extractor_recipe({input = {"default:papyrus 99"}, output = "biofuel:biofuel 1"})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if core.get_modpath("basic_machines") then
|
||||
if basic_machines then
|
||||
basic_machines.grinder_recipes["farming:wheat"] = {50,"biofuel:biofuel",1}
|
||||
basic_machines.grinder_recipes["farming:corn"] = {50,"biofuel:biofuel",1}
|
||||
basic_machines.grinder_recipes["farming:potato"] = {50,"biofuel:biofuel",1}
|
||||
basic_machines.grinder_recipes["default:papyrus"] = {70,"biofuel:biofuel",1}
|
||||
end
|
||||
end
|
||||
|
||||
if core.get_modpath("default") then
|
||||
core.register_craft({
|
||||
output = module_name .. ":biofuel_distiller",
|
||||
recipe = {
|
||||
{"default:copper_ingot", "default:copper_ingot", "default:copper_ingot"},
|
||||
{"default:steel_ingot" , "", "default:steel_ingot"},
|
||||
{"default:steel_ingot" , "default:steel_ingot", "default:steel_ingot"},
|
||||
},
|
||||
})
|
||||
end
|
||||
if core.get_modpath("mcl_core") then
|
||||
core.register_craft({
|
||||
output = module_name .. ":biofuel_distiller",
|
||||
recipe = {
|
||||
{"mcl_copper:copper_ingot", "mcl_copper:copper_ingot", "mcl_copper:copper_ingot"},
|
||||
{"mcl_core:iron_ingot" , "", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot" , "mcl_core:iron_ingot", "mcl_core:iron_ingot"},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
-- biofuel
|
||||
local new_gallon_id = "airutils:biofuel"
|
||||
core.register_craftitem(new_gallon_id,{
|
||||
description = S("Bio Fuel"),
|
||||
inventory_image = "airutils_biofuel_inv.png",
|
||||
})
|
||||
|
||||
core.register_craft({
|
||||
type = "fuel",
|
||||
recipe = new_gallon_id,
|
||||
burntime = 50,
|
||||
})
|
||||
|
||||
core.register_alias("biofuel:biofuel", new_gallon_id) --for the old biofuel
|
||||
|
||||
local ferment = {
|
||||
{"default:papyrus", new_gallon_id},
|
||||
{"farming:wheat", new_gallon_id},
|
||||
{"farming:corn", new_gallon_id},
|
||||
{"farming:baked_potato", new_gallon_id},
|
||||
{"farming:potato", new_gallon_id}
|
||||
}
|
||||
|
||||
local ferment_groups = {'flora', 'leaves', 'flower', 'sapling', 'tree', 'wood', 'stick', 'plant', 'seed',
|
||||
'leafdecay', 'leafdecay_drop', 'mushroom', 'vines' }
|
||||
|
||||
-- distiller
|
||||
local biofueldistiller_formspec = "size[8,9]"
|
||||
.. "list[current_name;src;2,1;1,1;]" .. airutils.get_itemslot_bg(2, 1, 1, 1)
|
||||
.. "list[current_name;dst;5,1;1,1;]" .. airutils.get_itemslot_bg(5, 1, 1, 1)
|
||||
.. "list[current_player;main;0,5;8,4;]" .. airutils.get_itemslot_bg(0, 5, 8, 4)
|
||||
.. "listring[current_name;dst]"
|
||||
.. "listring[current_player;main]"
|
||||
.. "listring[current_name;src]"
|
||||
.. "listring[current_player;main]"
|
||||
.. "image[3.5,1;1,1;gui_furnace_arrow_bg.png^[transformR270]"
|
||||
|
||||
core.register_node( module_name .. ":biofuel_distiller", {
|
||||
description = S("Biofuel Distiller"),
|
||||
tiles = {"airutils_black.png", "airutils_aluminum.png", "airutils_copper.png" },
|
||||
drawtype = "mesh",
|
||||
mesh = "airutils_biofuel_distiller.b3d",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
groups = {
|
||||
choppy = 2, oddly_breakable_by_hand = 1, flammable = 2
|
||||
},
|
||||
legacy_facedir_simple = true,
|
||||
|
||||
on_place = core.rotate_node,
|
||||
|
||||
on_construct = function(pos)
|
||||
|
||||
local meta = core.get_meta(pos)
|
||||
|
||||
meta:set_string("formspec", biofueldistiller_formspec)
|
||||
meta:set_string("infotext", S("Biofuel Distiller"))
|
||||
meta:set_float("status", 0.0)
|
||||
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
inv:set_size("src", 1)
|
||||
inv:set_size("dst", 1)
|
||||
end,
|
||||
|
||||
can_dig = function(pos,player)
|
||||
|
||||
local meta = core.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
if not inv:is_empty("dst")
|
||||
or not inv:is_empty("src") then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
|
||||
if core.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
return stack:get_count()
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
|
||||
if core.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if listname == "src" then
|
||||
return stack:get_count()
|
||||
elseif listname == "dst" then
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
|
||||
if core.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if to_list == "src" then
|
||||
return count
|
||||
elseif to_list == "dst" then
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
|
||||
on_metadata_inventory_put = function(pos)
|
||||
|
||||
local timer = core.get_node_timer(pos)
|
||||
|
||||
timer:start(5)
|
||||
end,
|
||||
|
||||
on_timer = function(pos)
|
||||
|
||||
local meta = core.get_meta(pos) ; if not meta then return end
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
-- is barrel empty?
|
||||
if not inv or inv:is_empty("src") then
|
||||
|
||||
meta:set_float("status", 0.0)
|
||||
meta:set_string("infotext", S("Fuel Distiller"))
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- does it contain any of the source items on the list?
|
||||
local has_item
|
||||
|
||||
--normal items
|
||||
for n = 1, #ferment do
|
||||
if inv:contains_item("src", ItemStack(ferment[n][1])) then
|
||||
has_item = n
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
--groups
|
||||
local has_group
|
||||
if not has_item then
|
||||
local inv_content = inv:get_list("src")
|
||||
if inv_content then
|
||||
for k, v in pairs(inv_content) do
|
||||
local item_name = v:get_name()
|
||||
for n = 1, #ferment_groups do
|
||||
if core.get_item_group(item_name, ferment_groups[n]) == 1 then
|
||||
has_group = n
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not has_item and not has_group then
|
||||
return false
|
||||
end
|
||||
|
||||
-- is there room for additional fermentation?
|
||||
if has_item and not inv:room_for_item("dst", ferment[has_item][2]) then
|
||||
meta:set_string("infotext", S("Fuel Distiller (FULL)"))
|
||||
return true
|
||||
end
|
||||
|
||||
if has_group and not inv:room_for_item("dst", new_gallon_id) then
|
||||
meta:set_string("infotext", S("Fuel Distiller (FULL)"))
|
||||
return true
|
||||
end
|
||||
|
||||
local status = meta:get_float("status")
|
||||
|
||||
-- fermenting (change status)
|
||||
if status < 100 then
|
||||
meta:set_string("infotext", S("Fuel Distiller @1% done", status))
|
||||
meta:set_float("status", status + 5)
|
||||
else
|
||||
if not has_group then
|
||||
inv:remove_item("src", ferment[has_item][1])
|
||||
inv:add_item("dst", ferment[has_item][2])
|
||||
else
|
||||
for i,itemstack in pairs(inv:get_list("src")) do
|
||||
inv:remove_item("src", ItemStack(itemstack:get_name().." 1"))
|
||||
end
|
||||
inv:add_item("dst", new_gallon_id)
|
||||
end
|
||||
|
||||
meta:set_float("status", 0,0)
|
||||
end
|
||||
|
||||
if inv:is_empty("src") then
|
||||
meta:set_float("status", 0.0)
|
||||
meta:set_string("infotext", S("Fuel Distiller"))
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
--lets remove the old one
|
||||
core.register_node(":".."biofuel:biofuel_distiller", {
|
||||
groups = {old_biofuel=1},
|
||||
})
|
||||
|
||||
core.register_abm({
|
||||
nodenames = {"group:old_biofuel"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node)
|
||||
--core.remove_node(pos)
|
||||
core.swap_node(pos,{name = module_name..":biofuel_distiller"})
|
||||
end,
|
||||
})
|
170
mods/airutils/airutils_papi.lua
Normal file
|
@ -0,0 +1,170 @@
|
|||
local S = airutils.S
|
||||
|
||||
local function check_protection(pos, name)
|
||||
if core.is_protected(pos, name) then
|
||||
core.log("action", name
|
||||
.. " tried to place a PAPI"
|
||||
.. " at protected position "
|
||||
.. core.pos_to_string(pos)
|
||||
)
|
||||
core.record_protection_violation(pos, name)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function airutils.PAPIplace(player,pos)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
|
||||
local dir = core.dir_to_facedir(player:get_look_dir())
|
||||
|
||||
local player_name = player:get_player_name()
|
||||
if check_protection(pos, player_name) then
|
||||
return
|
||||
end
|
||||
|
||||
core.set_node(pos, {name="airutils:papi", param2=dir})
|
||||
local meta = core.get_meta(pos)
|
||||
meta:set_string("infotext", S("PAPI") .. "\r" .. S("Owned by: @1", player_name))
|
||||
meta:set_string("owner", player_name)
|
||||
meta:set_string("dont_destroy", "false")
|
||||
return true
|
||||
end
|
||||
|
||||
function airutils.togglePapiSide(pos, node, clicker, itemstack)
|
||||
local player_name = clicker:get_player_name()
|
||||
local meta = core.get_meta(pos)
|
||||
|
||||
if player_name ~= meta:get_string("owner") then
|
||||
return
|
||||
end
|
||||
|
||||
local dir=node.param2
|
||||
if node.name == "airutils:papi_right" then
|
||||
core.set_node(pos, {name="airutils:papi", param2=dir})
|
||||
meta:set_string("infotext", S("PAPI") .. " - " .. S("left side") .. "\r" .. S("Owned by: @1",player_name))
|
||||
elseif node.name == "airutils:papi" then
|
||||
core.set_node(pos, {name="airutils:papi_right", param2=dir})
|
||||
meta:set_string("infotext", S("PAPI") .. " - " .. S("right side") .. "\r" .. S("Owned by: @1",player_name))
|
||||
end
|
||||
|
||||
meta:set_string("owner", player_name)
|
||||
meta:set_string("dont_destroy", "false")
|
||||
end
|
||||
|
||||
airutils.papi_collision_box = {
|
||||
type = "fixed",
|
||||
fixed={{-0.5,-0.5,-0.5,0.5,-0.42,0.5},},
|
||||
}
|
||||
|
||||
airutils.papi_selection_box = {
|
||||
type = "fixed",
|
||||
fixed={{-0.5,-0.5,-0.5,0.5,1.5,0.5},},
|
||||
}
|
||||
|
||||
airutils.groups_right = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}
|
||||
airutils.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}
|
||||
|
||||
-- PAPI node (default left)
|
||||
core.register_node("airutils:papi",{
|
||||
description = S("PAPI"),
|
||||
--inventory_image = "papi.png",
|
||||
--wield_image = "papi.png",
|
||||
tiles = {"airutils_black.png", "airutils_u_black.png", "airutils_white.png",
|
||||
"airutils_metal.png", {name = "airutils_red.png", backface_culling = true},},
|
||||
groups = airutils.groups,
|
||||
paramtype2 = "facedir",
|
||||
paramtype = "light",
|
||||
drawtype = "mesh",
|
||||
mesh = "papi.b3d",
|
||||
visual_scale = 1.0,
|
||||
light_source = 13,
|
||||
backface_culling = true,
|
||||
selection_box = airutils.papi_selection_box,
|
||||
collision_box = airutils.papi_collision_box,
|
||||
can_dig = airutils.canDig,
|
||||
_color = "",
|
||||
on_destruct = airutils.remove,
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local pos = pointed_thing.above
|
||||
if airutils.PAPIplace(placer,pos)==true then
|
||||
itemstack:take_item(1)
|
||||
return itemstack
|
||||
else
|
||||
return
|
||||
end
|
||||
end,
|
||||
on_rightclick=airutils.togglePapiSide,
|
||||
on_punch = function(pos, node, puncher, pointed_thing)
|
||||
local player_name = puncher:get_player_name()
|
||||
local meta = core.get_meta(pos)
|
||||
if player_name ~= meta:get_string("owner") then
|
||||
local privs = core.get_player_privs(player_name)
|
||||
if privs.server == false then
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
function airutils.remove_papi(pos)
|
||||
--[[
|
||||
local meta = core.get_meta(pos)
|
||||
local node = core.get_node(pos)
|
||||
if node and meta then
|
||||
local dir=node.param2
|
||||
if node.name == "airutils:papi_right" then
|
||||
core.set_node(pos, {name="airutils:papi", param2=dir})
|
||||
meta:set_string("infotext", "PAPI - left side\rOwned by: "..player_name)
|
||||
end
|
||||
|
||||
meta:set_string("owner", player_name)
|
||||
meta:set_string("dont_destroy", "false")
|
||||
|
||||
if meta:get_string("dont_destroy") == "true" then
|
||||
-- when swapping it
|
||||
return
|
||||
end
|
||||
end]]--
|
||||
end
|
||||
|
||||
-- PAPI right node
|
||||
core.register_node("airutils:papi_right",{
|
||||
description = S("PAPI") .. "_" .. S("right_side"),
|
||||
tiles = {"airutils_black.png", "airutils_u_black.png", "airutils_white.png",
|
||||
"airutils_metal.png", {name = "airutils_red.png", backface_culling = true},},
|
||||
groups = airutils.groups_right,
|
||||
paramtype2 = "facedir",
|
||||
paramtype = "light",
|
||||
drawtype = "mesh",
|
||||
mesh = "papi_right.b3d",
|
||||
visual_scale = 1.0,
|
||||
light_source = 13,
|
||||
backface_culling = true,
|
||||
selection_box = airutils.papi_selection_box,
|
||||
collision_box = airutils.papi_collision_box,
|
||||
can_dig = airutils.canDig,
|
||||
_color = "",
|
||||
on_destruct = airutils.remove_papi,
|
||||
on_rightclick=airutils.togglePapiSide,
|
||||
on_punch = function(pos, node, puncher, pointed_thing)
|
||||
local player_name = puncher:get_player_name()
|
||||
local meta = core.get_meta(pos)
|
||||
if player_name ~= meta:get_string("owner") then
|
||||
return
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- PAPI craft
|
||||
core.register_craft({
|
||||
output = 'airutils:papi',
|
||||
recipe = {
|
||||
{'default:glass', 'default:mese_crystal', 'default:glass'},
|
||||
{'default:glass', 'default:steel_ingot' , 'default:glass'},
|
||||
{'' , 'default:steel_ingot' , ''},
|
||||
}
|
||||
})
|
16
mods/airutils/airutils_repair.lua
Normal file
|
@ -0,0 +1,16 @@
|
|||
local S = airutils.S
|
||||
|
||||
-- trike repair
|
||||
core.register_craftitem("airutils:repair_tool",{
|
||||
description = S("Repair Tool"),
|
||||
inventory_image = "airutils_repair_tool.png",
|
||||
})
|
||||
|
||||
core.register_craft({
|
||||
output = "airutils:repair_tool",
|
||||
recipe = {
|
||||
{"", "default:steel_ingot", ""},
|
||||
{"", "default:steel_ingot", ""},
|
||||
{"default:steel_ingot", "", "default:steel_ingot"},
|
||||
},
|
||||
})
|
105
mods/airutils/airutils_tug.lua
Normal file
|
@ -0,0 +1,105 @@
|
|||
local S = airutils.S
|
||||
|
||||
function airutils.move_target(player, pointed_thing)
|
||||
local pos = player:get_pos()
|
||||
local yaw = player:get_look_horizontal()
|
||||
|
||||
local object = pointed_thing.ref
|
||||
--core.chat_send_all(dump(object))
|
||||
if object then
|
||||
local obj_pos = object:get_pos()
|
||||
if not obj_pos then return end
|
||||
local hip = math.sqrt(math.pow(obj_pos.x - pos.x,2)+math.pow(obj_pos.z - pos.z,2)) + 1
|
||||
local pos_x = math.sin(yaw) * -hip
|
||||
local pos_z = math.cos(yaw) * hip
|
||||
obj_pos.x = pos.x + pos_x
|
||||
obj_pos.z = pos.z + pos_z
|
||||
|
||||
local node = core.get_node(obj_pos).name
|
||||
local nodedef = core.registered_nodes[node]
|
||||
local is_airlike = nodedef.drawtype == "airlike"
|
||||
local is_liquid = (nodedef.drawtype == "flowingliquid" or nodedef.drawtype == "liquid")
|
||||
|
||||
if player:get_player_control().sneak == true then
|
||||
local rotation = object:get_rotation()
|
||||
if rotation then
|
||||
rotation.y = yaw + math.rad(180)
|
||||
object:set_rotation(rotation)
|
||||
end
|
||||
else
|
||||
if is_airlike or is_liquid then object:set_pos(obj_pos) end
|
||||
end
|
||||
--[[if object:get_attach() then
|
||||
local dir = player:get_look_dir()
|
||||
core.chat_send_all('detach')
|
||||
object:set_detach()
|
||||
object:set_rotation(dir)
|
||||
else
|
||||
core.chat_send_all('object found')
|
||||
object:set_attach(player, "", {x=0, y=0, z=20})
|
||||
end]]--
|
||||
end
|
||||
end
|
||||
|
||||
core.register_tool("airutils:tug", {
|
||||
description = S("Tug tool for airport"),
|
||||
inventory_image = "airutils_tug.png",
|
||||
stack_max=1,
|
||||
on_use = function(itemstack, player, pointed_thing)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
|
||||
local is_admin = core.check_player_privs(player, {server=true})
|
||||
|
||||
local pos = player:get_pos()
|
||||
local pname = player:get_player_name()
|
||||
|
||||
--[[if areas then
|
||||
if not areas:canInteract(pos, pname) then
|
||||
local owners = areas:getNodeOwners(pos)
|
||||
core.chat_send_player(pname,
|
||||
S("@1 is protected by @2.",
|
||||
core.pos_to_string(pos),
|
||||
table.concat(owners, ", ")))
|
||||
else
|
||||
airutils.move_target(player, pointed_thing)
|
||||
end
|
||||
end]]--
|
||||
local is_protected = core.is_protected
|
||||
if is_protected then
|
||||
local owner = nil
|
||||
local object = pointed_thing.ref
|
||||
if object then
|
||||
local ent = object:get_luaentity()
|
||||
if ent then
|
||||
if ent.owner then owner = ent.owner end
|
||||
end
|
||||
end
|
||||
if not is_protected(pos, pname) or pname == owner or is_admin then
|
||||
airutils.move_target(player, pointed_thing)
|
||||
else
|
||||
core.chat_send_player(pname,
|
||||
S("@1 is protected.",
|
||||
core.pos_to_string(pos)))
|
||||
end
|
||||
end
|
||||
|
||||
if not is_protected then
|
||||
airutils.move_target(player, pointed_thing)
|
||||
end
|
||||
|
||||
|
||||
end,
|
||||
|
||||
sound = {breaks = "default_tool_breaks"},
|
||||
})
|
||||
|
||||
core.register_craft({
|
||||
output = "airutils:tug",
|
||||
recipe = {
|
||||
{"", "", "default:steel_ingot"},
|
||||
{"", "default:steel_ingot", ""},
|
||||
{"default:steel_ingot", "default:stick", "default:diamond"},
|
||||
}
|
||||
})
|
193
mods/airutils/airutils_wind.lua
Normal file
|
@ -0,0 +1,193 @@
|
|||
local S = airutils.S
|
||||
|
||||
local function check_protection(pos, name)
|
||||
if core.is_protected(pos, name) then
|
||||
core.log("action", name
|
||||
.. " tried to place a Wind Indicator"
|
||||
.. " at protected position "
|
||||
.. core.pos_to_string(pos)
|
||||
)
|
||||
core.record_protection_violation(pos, name)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function airutils.WindDplace(player,pos)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
|
||||
local dir = core.dir_to_facedir(vector.new())
|
||||
local pos1 = vector.new(pos)
|
||||
|
||||
local player_name = player:get_player_name()
|
||||
if check_protection(pos, player_name) then
|
||||
return
|
||||
end
|
||||
|
||||
core.set_node(pos1, {name="airutils:wind", param2=dir})
|
||||
local meta = core.get_meta(pos)
|
||||
meta:set_string("infotext", S("Wind Indicator") .. "\r" .. S("Owned by: @1",player_name))
|
||||
meta:set_string("owner", player_name)
|
||||
meta:set_string("dont_destroy", "false")
|
||||
return true
|
||||
end
|
||||
|
||||
airutils.wind_collision_box = {
|
||||
type = "fixed",
|
||||
fixed={{-0.5,0,-0.5,0.5,5.0,0.5},},
|
||||
}
|
||||
|
||||
airutils.wind_selection_box = {
|
||||
type = "fixed",
|
||||
fixed={{-0.5,0,-0.5,0.5,5.0,0.5},},
|
||||
}
|
||||
|
||||
local function get_smooth(angle_initial, reference, last_ref, value)
|
||||
local range = reference-last_ref
|
||||
local retVal = (value*angle_initial)/range
|
||||
local retval = angle_initial - retVal
|
||||
if retval < 0 then retval = 0 end
|
||||
return retval
|
||||
end
|
||||
|
||||
core.register_entity("airutils:wind_indicator",{
|
||||
-- common props
|
||||
physical = true,
|
||||
stepheight = 0.5,
|
||||
collide_with_objects = true,
|
||||
collisionbox = {-0.5, 0, -0.5, 0.5, 5.0, 0.5},
|
||||
visual = "mesh",
|
||||
mesh = "airutils_wind.b3d",
|
||||
textures = {"airutils_red.png", "airutils_black.png", "airutils_white.png", "airutils_metal.png"},
|
||||
static_save = true,
|
||||
makes_footstep_sound = false,
|
||||
_pos = nil,
|
||||
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
self._pos = self.object:get_pos()
|
||||
end,
|
||||
|
||||
on_step = function(self,dtime,colinfo)
|
||||
self.object:set_pos(self._pos)
|
||||
|
||||
local wind = airutils.get_wind(self._pos, 1.0)
|
||||
local wind_yaw = core.dir_to_yaw(wind)
|
||||
self.object:set_bone_position("ajuste", {x=0,y=42,z=0}, {x=0,y=0,z=90})
|
||||
self.object:set_bone_position("b_a", {x=0,y=0,z=0}, {x=math.deg(wind_yaw)-90,y=0,z=0})
|
||||
|
||||
local false_div = 1 --trying to make it more o minus sensible
|
||||
local vel = ((vector.dot(vector.multiply(wind,dtime),wind))/false_div)*100
|
||||
--core.chat_send_all(vel)
|
||||
local b_b = 65
|
||||
if vel > 11 then
|
||||
b_b = get_smooth(65, 11, 0, vel)
|
||||
end
|
||||
self.object:set_bone_position("b_b", {x=0,y=8.25,z=0}, {x=0,y=0,z=-b_b})
|
||||
|
||||
local b_c = 15
|
||||
if vel > 16 then
|
||||
b_c = get_smooth(15, 16, 11, vel)
|
||||
end
|
||||
self.object:set_bone_position("b_c", {x=0,y=6.0,z=0}, {x=0,y=0,z=-b_c})
|
||||
|
||||
local b_d = 5
|
||||
if vel > 22 then
|
||||
b_d = get_smooth(5, 22, 16, vel)
|
||||
end
|
||||
self.object:set_bone_position("b_d", {x=0,y=4.5,z=0}, {x=0,y=0,z=-b_d})
|
||||
|
||||
local b_e = 2
|
||||
if vel > 28 then
|
||||
b_e = get_smooth(2, 28, 22, vel)
|
||||
end
|
||||
self.object:set_bone_position("b_e", {x=0,y=3,z=0}, {x=0,y=0,z=-b_e})
|
||||
|
||||
--core.chat_send_all("Wind Direction: "..math.deg(wind_yaw))
|
||||
end, -- required
|
||||
--on_activate = mobkit.actfunc, -- required
|
||||
--get_staticdata = mobkit.statfunc,
|
||||
max_hp = 65535,
|
||||
timeout = 0,
|
||||
on_punch=function(self, puncher)
|
||||
return
|
||||
end,
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
local wind = airutils.get_wind(self.object:get_pos(), 2.0)
|
||||
local wind_yaw = core.dir_to_yaw(wind)
|
||||
core.chat_send_player(clicker:get_player_name(),core.colorize('#00ff00', S(" >>> The wind direction now is @1", math.deg(wind_yaw))))
|
||||
return
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
-- Wind Indicator node (default left)
|
||||
core.register_node("airutils:wind",{
|
||||
description = S("Wind Direction Indicator"),
|
||||
waving = 1,
|
||||
tiles = {"default_steel_block.png","default_steel_block.png","default_steel_block.png","default_steel_block.png","default_steel_block.png","default_steel_block.png"},
|
||||
paramtype = "light",
|
||||
paramtype2 = "leveled",
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 1, level = 2},
|
||||
walkable = true,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
{-0.1, 0.5, -0.1, 0.1, 2.0, 0.1}
|
||||
}
|
||||
},
|
||||
|
||||
node_dig_prediction = "default:dirt",
|
||||
node_placement_prediction = "airutils:wind",
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
|
||||
local pos = pointed_thing.above
|
||||
|
||||
local player_name = placer:get_player_name()
|
||||
|
||||
|
||||
if not core.is_protected(pos, player_name) and not core.is_protected(pos, player_name) then
|
||||
core.set_node(pos, {name = "airutils:wind",param2 = 1 })
|
||||
core.add_entity({x=pos.x, y=pos.y, z=pos.z},"airutils:wind_indicator")
|
||||
if not (creative and creative.is_enabled_for and creative.is_enabled_for(player_name)) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
else
|
||||
core.chat_send_player(player_name, S("Node is protected"))
|
||||
core.record_protection_violation(pos, player_name)
|
||||
end
|
||||
|
||||
|
||||
return itemstack
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
local meta=core.get_meta(pos)
|
||||
if meta then
|
||||
local cpos = {x=pos.x, y= pos.y, z=pos.z}
|
||||
local object = core.get_objects_inside_radius(cpos, 1)
|
||||
for _,obj in ipairs(object) do
|
||||
local entity = obj:get_luaentity()
|
||||
if entity and entity.name == "airutils:wind_indicator" then
|
||||
obj:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- WIND craft
|
||||
core.register_craft({
|
||||
output = 'airutils:wind',
|
||||
recipe = {
|
||||
{'wool:white', 'wool:white', 'wool:white'},
|
||||
{'wool:white', 'default:steel_ingot' , 'wool:white'},
|
||||
{'' , 'default:steel_ingot' , ''},
|
||||
}
|
||||
})
|
197
mods/airutils/attach_extern_ent.lua
Normal file
|
@ -0,0 +1,197 @@
|
|||
local S = airutils.S
|
||||
|
||||
local function attach_entity(self, target_obj, ent, dest_pos, relative_pos, attach_up)
|
||||
attach_up = attach_up or false
|
||||
if not target_obj then return end
|
||||
if self.object then
|
||||
if self._vehicle_custom_data then
|
||||
local y = 0
|
||||
if attach_up == false then
|
||||
y = self.initial_properties.collisionbox[2] - ent.initial_properties.collisionbox[2]
|
||||
else
|
||||
y = (relative_pos.y/10) + ent.initial_properties.collisionbox[5]
|
||||
end
|
||||
dest_pos.y = dest_pos.y + y
|
||||
target_obj:set_pos(dest_pos)
|
||||
local ent = target_obj:get_luaentity()
|
||||
if ent then
|
||||
relative_pos.y = y*10
|
||||
target_obj:set_attach(self.object,'',relative_pos,{x=0,y=0,z=0})
|
||||
self._vehicle_custom_data.simple_external_attach_entity = ent.name
|
||||
self._vehicle_custom_data.simple_external_attach_pos = relative_pos
|
||||
self._vehicle_custom_data.simple_external_attach_invid = ent._inv_id --why?! Because I can identify the target entity by it's inventory ;)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.get_attached_entity(self)
|
||||
if not self._vehicle_custom_data then return nil, nil end
|
||||
if not self._vehicle_custom_data.simple_external_attach_entity then return nil, nil end
|
||||
|
||||
local inv_id = self._vehicle_custom_data.simple_external_attach_invid
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local nearby_objects = minetest.get_objects_inside_radius(pos, 32)
|
||||
for i,obj in ipairs(nearby_objects) do
|
||||
local ent = obj:get_luaentity()
|
||||
if ent then
|
||||
if ent._inv_id then
|
||||
if ent._inv_id == inv_id then
|
||||
return ent, obj
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
function airutils.dettach_entity(self)
|
||||
local ent, obj = airutils.get_attached_entity(self)
|
||||
if ent and obj then
|
||||
local relative_pos = self._vehicle_custom_data.simple_external_attach_pos
|
||||
local pos = self.object:get_pos()
|
||||
local rotation = self.object:get_rotation()
|
||||
local direction = rotation.y
|
||||
local velocity = self.object:get_velocity()
|
||||
|
||||
local move = -1*relative_pos.z/10
|
||||
pos.x = pos.x + move * math.sin(direction)
|
||||
pos.z = pos.z - move * math.cos(direction)
|
||||
pos.y = pos.y + self.initial_properties.collisionbox[2] - ent.initial_properties.collisionbox[2]
|
||||
obj:set_detach()
|
||||
obj:set_pos(pos)
|
||||
obj:set_rotation(rotation)
|
||||
obj:set_velocity(velocity)
|
||||
--clear
|
||||
self._vehicle_custom_data.simple_external_attach_entity = nil
|
||||
self._vehicle_custom_data.simple_external_attach_pos = nil
|
||||
self._vehicle_custom_data.simple_external_attach_invid = nil
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.attach_external_object(self, object, ent, destination_pos, relative_pos, attach_up)
|
||||
local dest_pos = vector.new(destination_pos)
|
||||
local rel_pos = vector.new(relative_pos)
|
||||
if attach_up == false then
|
||||
rel_pos.y = 0
|
||||
end
|
||||
dest_pos = vector.add(dest_pos, vector.divide(rel_pos,10))
|
||||
attach_entity(self, object, ent, dest_pos, rel_pos, attach_up)
|
||||
end
|
||||
|
||||
function airutils.simple_external_attach(self, relative_pos, entity_name, radius, attach_up)
|
||||
attach_up = attach_up or false
|
||||
radius = radius or 12
|
||||
if self.object then
|
||||
local curr_ent, _ = airutils.get_attached_entity(self)
|
||||
if curr_ent then return end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local nearby_objects = minetest.get_objects_inside_radius(pos, radius)
|
||||
for i,obj in ipairs(nearby_objects) do
|
||||
if obj == self.object then
|
||||
table.remove(nearby_objects,i)
|
||||
end
|
||||
local ent = obj:get_luaentity()
|
||||
if ent then
|
||||
if ent.name == entity_name then
|
||||
airutils.attach_external_object(self, nearby_objects[i], ent, pos, relative_pos, attach_up)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--execute on load
|
||||
function airutils.restore_external_attach(self)
|
||||
if not self._vehicle_custom_data then return end
|
||||
if not self._vehicle_custom_data.simple_external_attach_invid then return end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local dest_pos = vector.new(pos)
|
||||
local relative_pos = self._vehicle_custom_data.simple_external_attach_pos
|
||||
local inv_id = self._vehicle_custom_data.simple_external_attach_invid
|
||||
dest_pos = vector.add(dest_pos, relative_pos)
|
||||
|
||||
minetest.after(0.3, function()
|
||||
local nearby_objects = minetest.get_objects_inside_radius(pos, 32)
|
||||
local ent
|
||||
for i,obj in ipairs(nearby_objects) do
|
||||
ent = obj:get_luaentity()
|
||||
if ent then
|
||||
--minetest.chat_send_all(dump(ent.name))
|
||||
if ent._inv_id then
|
||||
--minetest.chat_send_all(">> "..dump(ent._inv_id).." >> "..dump(inv_id))
|
||||
if ent._inv_id == inv_id and ent._inv_id ~= self._inv_id then
|
||||
--minetest.chat_send_all("++ "..dump(ent._inv_id).." ++ "..dump(inv_id))
|
||||
local target_obj = nearby_objects[i]
|
||||
target_obj:set_pos(dest_pos)
|
||||
target_obj:set_attach(self.object,'',relative_pos,{x=0,y=0,z=0})
|
||||
--attach_entity(self, nearby_objects[i], dest_pos, relative_pos, entity_name, inv_id)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--clear
|
||||
--self._vehicle_custom_data.simple_external_attach_entity = nil
|
||||
--self._vehicle_custom_data.simple_external_attach_pos = nil
|
||||
--self._vehicle_custom_data.simple_external_attach_invid = nil
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("remove_hook", {
|
||||
params = "",
|
||||
description = S("Dettach current vehicle from another"),
|
||||
privs = {interact=true},
|
||||
func = function(name, param)
|
||||
local colorstring = core.colorize('#ff0000', S(" >>> you are not inside a plane"))
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local attached_to = player:get_attach()
|
||||
|
||||
if attached_to ~= nil then
|
||||
local seat = attached_to:get_attach()
|
||||
if seat ~= nil then
|
||||
local entity = seat:get_luaentity()
|
||||
if entity then
|
||||
if entity.on_step == airutils.on_step then
|
||||
local rem_obj = entity.object:get_attach()
|
||||
if not rem_obj then
|
||||
minetest.chat_send_player(name,core.colorize('#ff0000', S(" >>> no hook found")))
|
||||
return
|
||||
end
|
||||
local rem_ent = rem_obj:get_luaentity()
|
||||
|
||||
local pos = rem_ent.object:get_pos()
|
||||
local rotation = rem_ent.object:get_rotation()
|
||||
local direction = rotation.y
|
||||
local velocity = rem_ent.object:get_velocity()
|
||||
|
||||
local move = 0
|
||||
if rem_ent._vehicle_custom_data.simple_external_attach_pos then
|
||||
move = -1*rem_ent._vehicle_custom_data.simple_external_attach_pos.z/10
|
||||
end
|
||||
pos.x = pos.x + move * math.sin(direction)
|
||||
pos.z = pos.z + move * math.cos(direction)
|
||||
pos.y = pos.y + rem_ent.initial_properties.collisionbox[2] - entity.initial_properties.collisionbox[2]
|
||||
entity.object:set_detach()
|
||||
entity.object:set_pos(pos)
|
||||
entity.object:set_rotation(rotation)
|
||||
entity.object:set_velocity(velocity)
|
||||
--clear
|
||||
rem_ent._vehicle_custom_data.simple_external_attach_entity = nil
|
||||
rem_ent._vehicle_custom_data.simple_external_attach_pos = nil
|
||||
rem_ent._vehicle_custom_data.simple_external_attach_invid = nil
|
||||
else
|
||||
minetest.chat_send_player(name,colorstring)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name,colorstring)
|
||||
end
|
||||
end
|
||||
})
|
24
mods/airutils/common_entities.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
--
|
||||
-- seat pivot
|
||||
--
|
||||
minetest.register_entity('airutils:seat_base',{
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
collide_with_objects=false,
|
||||
pointable=false,
|
||||
visual = "mesh",
|
||||
mesh = "airutils_seat_base.b3d",
|
||||
textures = {"airutils_alpha.png",},
|
||||
},
|
||||
|
||||
on_activate = function(self,std)
|
||||
self.sdata = minetest.deserialize(std) or {}
|
||||
if self.sdata.remove then self.object:remove() end
|
||||
end,
|
||||
|
||||
get_staticdata=function(self)
|
||||
self.sdata.remove=true
|
||||
return minetest.serialize(self.sdata)
|
||||
end,
|
||||
|
||||
})
|
1
mods/airutils/description.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Airport Utils for Minetest
|
676
mods/airutils/init.lua
Normal file
|
@ -0,0 +1,676 @@
|
|||
-- Minetest 5.4.1 : airutils
|
||||
airutils = {}
|
||||
|
||||
airutils.storage = core.get_mod_storage()
|
||||
|
||||
local storage = airutils.storage
|
||||
|
||||
airutils.colors ={
|
||||
black='#2b2b2b',
|
||||
blue='#0063b0',
|
||||
brown='#8c5922',
|
||||
cyan='#07B6BC',
|
||||
dark_green='#567a42',
|
||||
dark_grey='#6d6d6d',
|
||||
green='#4ee34c',
|
||||
grey='#9f9f9f',
|
||||
magenta='#ff0098',
|
||||
orange='#ff8b0e',
|
||||
pink='#ff62c6',
|
||||
red='#dc1818',
|
||||
violet='#a437ff',
|
||||
white='#FFFFFF',
|
||||
yellow='#ffe400',
|
||||
}
|
||||
|
||||
airutils.S = nil
|
||||
|
||||
if(core.get_translator ~= nil) then
|
||||
airutils.S = core.get_translator(core.get_current_modname())
|
||||
|
||||
else
|
||||
airutils.S = function ( s ) return s end
|
||||
end
|
||||
|
||||
local S = airutils.S
|
||||
|
||||
local load_blast_damage = storage:get_int("blast_damage")
|
||||
airutils.blast_damage = true
|
||||
-- 1 == true ---- 2 == false
|
||||
if load_blast_damage == 2 then airutils.blast_damage = false end
|
||||
|
||||
airutils.is_minetest = core.get_modpath("player_api")
|
||||
airutils.is_mcl = core.get_modpath("mcl_player")
|
||||
airutils.is_repixture = core.get_modpath("rp_player")
|
||||
|
||||
airutils.fuel = {['biofuel:biofuel'] = 1,['biofuel:bottle_fuel'] = 1,
|
||||
['biofuel:phial_fuel'] = 0.25, ['biofuel:fuel_can'] = 10,
|
||||
['airutils:biofuel'] = 1,}
|
||||
|
||||
airutils.protect_in_areas = core.settings:get_bool('airutils_protect_in_areas')
|
||||
airutils.debug_log = core.settings:get_bool('airutils_debug_log')
|
||||
|
||||
if not core.settings:get_bool('airutils_disable_papi') then
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "airutils_papi.lua")
|
||||
end
|
||||
if not core.settings:get_bool('airutils_disable_tug') then
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "airutils_tug.lua")
|
||||
end
|
||||
if not core.settings:get_bool('airutils_disable_repair') then
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "airutils_repair.lua")
|
||||
end
|
||||
|
||||
airutils.splash_texture = "airutils_splash.png"
|
||||
airutils.use_water_particles = false
|
||||
if core.settings:get_bool('airutils_enable_water_particles', false) then
|
||||
airutils.use_water_particles = true
|
||||
end
|
||||
|
||||
airutils._use_signs_api = true
|
||||
if not core.get_modpath("signs_lib") then airutils._use_signs_api = false end
|
||||
if core.settings:get_bool('airutils_disable_signs_api') then airutils._use_signs_api = false end
|
||||
|
||||
airutils.get_wind = dofile(core.get_modpath("airutils") .. DIR_DELIM ..'/wind.lua')
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "uuid_manager.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "common_entities.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "airutils_wind.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "water_splash.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "inventory_management.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "light.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "physics_lib.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "init.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "lib_copter" .. DIR_DELIM .. "init.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "texture_management.lua")
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "attach_extern_ent.lua")
|
||||
if airutils._use_signs_api then dofile(core.get_modpath("airutils") .. DIR_DELIM .. "text.lua") end
|
||||
|
||||
local is_biofuel_installed = false
|
||||
if biomass then
|
||||
if biomass.convertible_groups then is_biofuel_installed = true end
|
||||
end
|
||||
local enable_internal_biofuel = core.settings:get_bool('airutils.force_enable_biofuel')
|
||||
if not is_biofuel_installed or enable_internal_biofuel then
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "airutils_biofuel.lua")
|
||||
end
|
||||
|
||||
if core.get_modpath("player_api") and not core.settings:get_bool('airutils.disable_uniforms') then
|
||||
dofile(core.get_modpath("airutils") .. DIR_DELIM .. "pilot_skin_manager.lua")
|
||||
end
|
||||
|
||||
function airutils.remove(pos)
|
||||
local meta = core.get_meta(pos)
|
||||
if meta:get_string("dont_destroy") == "true" then
|
||||
-- when swapping it
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.canDig(pos, player)
|
||||
local meta = core.get_meta(pos)
|
||||
return meta:get_string("dont_destroy") ~= "true"
|
||||
and player:get_player_name() == meta:get_string("owner")
|
||||
end
|
||||
|
||||
function airutils.check_node_below(obj, how_low)
|
||||
local pos_below = obj:get_pos()
|
||||
if pos_below then
|
||||
pos_below.y = pos_below.y - how_low
|
||||
local node_below = core.get_node(pos_below).name
|
||||
local nodedef = core.registered_nodes[node_below]
|
||||
local touching_ground = not nodedef or -- unknown nodes are solid
|
||||
nodedef.walkable or false
|
||||
local liquid_below = not touching_ground and nodedef.liquidtype ~= "none"
|
||||
return touching_ground, liquid_below
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
function airutils.check_is_under_water(obj)
|
||||
local pos_up = obj:get_pos()
|
||||
pos_up.y = pos_up.y + 0.1
|
||||
local node_up = core.get_node(pos_up).name
|
||||
local nodedef = core.registered_nodes[node_up]
|
||||
local liquid_up = nodedef.liquidtype ~= "none"
|
||||
return liquid_up
|
||||
end
|
||||
|
||||
function airutils.setText(self, vehicle_name)
|
||||
local properties = self.object:get_properties()
|
||||
local formatted = ""
|
||||
if type(self.hp_max) ~= "number" then self.hp_max = 0.1 end --strange error when hpmax is NaN
|
||||
if self.hp_max then
|
||||
formatted = S(" Current hp: ") .. string.format(
|
||||
"%.2f", self.hp_max
|
||||
)
|
||||
end
|
||||
if properties then
|
||||
properties.infotext = S("Nice @1 of @2.@3", vehicle_name, self.owner, formatted)
|
||||
self.object:set_properties(properties)
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.transfer_control(self, status)
|
||||
if not self._have_copilot then return end
|
||||
if status == false then
|
||||
self._command_is_given = false
|
||||
if self.co_pilot then
|
||||
core.chat_send_player(self.co_pilot,
|
||||
core.colorize('#ff0000', S(" >>> The captain got the control.")))
|
||||
end
|
||||
if self.driver_name then
|
||||
core.chat_send_player(self.driver_name,
|
||||
core.colorize('#00ff00', S(" >>> The control is with you now.")))
|
||||
end
|
||||
else
|
||||
self._command_is_given = true
|
||||
if self.co_pilot then
|
||||
core.chat_send_player(self.co_pilot,
|
||||
core.colorize('#00ff00', S(" >>> The control is with you now.")))
|
||||
end
|
||||
if self.driver_name then core.chat_send_player(self.driver_name,S(" >>> The control was given.")) end
|
||||
end
|
||||
end
|
||||
|
||||
--returns 0 for old, 1 for new
|
||||
function airutils.detect_player_api(player)
|
||||
local player_proterties = player:get_properties()
|
||||
--local mesh = "character.b3d"
|
||||
--if player_proterties.mesh == mesh then
|
||||
if core.get_modpath("player_api") then
|
||||
local models = player_api.registered_models
|
||||
local character = models[player_proterties.mesh]
|
||||
--core.chat_send_all(dump(character));
|
||||
if character then
|
||||
if character.animations.sit.eye_height then
|
||||
--core.chat_send_all(dump(character.animations.sit.eye_height));
|
||||
if character.animations.sit.eye_height == 0.8 then
|
||||
--core.chat_send_all("new model");
|
||||
return 1
|
||||
else
|
||||
--core.chat_send_all("new height");
|
||||
return 2 --strange bug with armor ands skins returning 1.47
|
||||
end
|
||||
else
|
||||
--core.chat_send_all("old model");
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
local function get_nodedef_field(nodename, fieldname)
|
||||
if not core.registered_nodes[nodename] then
|
||||
return nil
|
||||
end
|
||||
return core.registered_nodes[nodename][fieldname]
|
||||
end
|
||||
|
||||
--for
|
||||
function airutils.eval_vertical_interception(initial_pos, end_pos)
|
||||
local ret_y = nil
|
||||
local cast = core.raycast(initial_pos, end_pos, true, true)
|
||||
local thing = cast:next()
|
||||
while thing do
|
||||
if thing.type == "node" then
|
||||
local pos = thing.intersection_point
|
||||
if pos then
|
||||
local nodename = core.get_node(thing.under).name
|
||||
local drawtype = get_nodedef_field(nodename, "drawtype")
|
||||
if drawtype ~= "plantlike" then
|
||||
ret_y = pos.y
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
thing = cast:next()
|
||||
end
|
||||
return ret_y
|
||||
end
|
||||
|
||||
--lift
|
||||
local function pitchroll2pitchyaw(aoa,roll)
|
||||
if roll == 0.0 then return aoa,0 end
|
||||
-- assumed vector x=0,y=0,z=1
|
||||
local p1 = math.tan(aoa)
|
||||
local y = math.cos(roll)*p1
|
||||
local x = math.sqrt(p1^2-y^2)
|
||||
local pitch = math.atan(y)
|
||||
local yaw=math.atan(x)*math.sign(roll)
|
||||
return pitch,yaw
|
||||
end
|
||||
|
||||
local function lerp(a, b, c)
|
||||
return a + (b - a) * c
|
||||
end
|
||||
|
||||
function airutils.quadBezier(t, p0, p1, p2)
|
||||
local l1 = lerp(p0, p1, t)
|
||||
local l2 = lerp(p1, p2, t)
|
||||
local quad = lerp(l1, l2, t)
|
||||
return quad
|
||||
end
|
||||
|
||||
function airutils.get_ground_effect_lift(self, curr_pos, lift, wingspan)
|
||||
local half_wingspan = wingspan/2
|
||||
local lower_collision = self.initial_properties.collisionbox[2]
|
||||
if not self._ground_effect_ammount_percent then self._ground_effect_ammount_percent = 0.5 end
|
||||
local initial_pos = {x=curr_pos.x, y=curr_pos.y + lower_collision, z=curr_pos.z} --lets make my own table to avoid interferences
|
||||
|
||||
if self._extra_lift == nil then self._extra_lift = 0 end
|
||||
if self._last_ground_effect_eval == nil then self._last_ground_effect_eval = 0 end
|
||||
|
||||
self._last_ground_effect_eval = self._last_ground_effect_eval + self.dtime --dtime cames from airutils
|
||||
|
||||
local ground_distance = wingspan
|
||||
if self._last_ground_effect_eval >= 0.25 then
|
||||
self._last_ground_effect_eval = 0
|
||||
self._last_ground_distance = ground_distance
|
||||
local ground_y = airutils.eval_vertical_interception(initial_pos, {x=initial_pos.x, y=initial_pos.y - half_wingspan, z=initial_pos.z})
|
||||
if ground_y then
|
||||
ground_distance = initial_pos.y - ground_y
|
||||
end
|
||||
--core.chat_send_all(dump(ground_distance))
|
||||
|
||||
--smooth the curve
|
||||
local distance_factor = ((ground_distance) * 1) / (wingspan)
|
||||
local effect_factor = airutils.quadBezier(distance_factor, 0, wingspan, 0)
|
||||
if effect_factor < 0 then effect_factor = 0 end
|
||||
if effect_factor > 0 then
|
||||
effect_factor = math.abs( half_wingspan - effect_factor )
|
||||
end
|
||||
|
||||
local lift_factor = ((effect_factor) * 1) / (half_wingspan) --agora isso é um percentual
|
||||
local max_extra_lift_percent = self._ground_effect_ammount_percent * lift --e aqui o maximo extra de sustentação
|
||||
local extra_lift = max_extra_lift_percent * lift_factor
|
||||
self._extra_lift = extra_lift
|
||||
end
|
||||
|
||||
return self._extra_lift --return the value stored
|
||||
end
|
||||
|
||||
|
||||
-- velocity: velocity table
|
||||
-- accel: current acceleration
|
||||
-- longit_speed: the vehicle speed
|
||||
-- roll: roll angle
|
||||
-- curr_pos: current position
|
||||
-- lift: lift factor (very simplified)
|
||||
-- max_height: the max ceilling for the airplane
|
||||
-- wingspan: for ground effect calculation
|
||||
function airutils.getLiftAccel(self, velocity, accel, longit_speed, roll, curr_pos, in_lift, max_height, wingspan)
|
||||
if longit_speed == nil then longit_speed = 0 end
|
||||
wingspan = wingspan or 10
|
||||
local lift = in_lift
|
||||
if not airutils.ground_effect_is_disabled then
|
||||
local ground_effect_extra_lift = airutils.get_ground_effect_lift(self, curr_pos, in_lift, wingspan)
|
||||
lift = lift + ground_effect_extra_lift
|
||||
end
|
||||
|
||||
--lift calculations
|
||||
-----------------------------------------------------------
|
||||
max_height = max_height or 20000
|
||||
local wing_config = 0
|
||||
if self._wing_configuration then wing_config = self._wing_configuration end --flaps!
|
||||
|
||||
local retval = accel
|
||||
local min_speed = 1;
|
||||
if self._min_speed then min_speed = self._min_speed end
|
||||
min_speed = min_speed / 2
|
||||
|
||||
local striped_velocity = vector.new(velocity)
|
||||
local cut_velocity = (min_speed * 1)/longit_speed
|
||||
striped_velocity.x = striped_velocity.x - (striped_velocity.x * cut_velocity)
|
||||
striped_velocity.z = striped_velocity.z - (striped_velocity.z * cut_velocity)
|
||||
|
||||
local angle_of_attack = math.rad(self._angle_of_attack + wing_config)
|
||||
--local acc = 0.8
|
||||
local daoa = math.deg(angle_of_attack)
|
||||
--core.chat_send_all(dump(daoa))
|
||||
|
||||
--to decrease the lift coefficient at hight altitudes
|
||||
local curr_percent_height = (100 - ((curr_pos.y * 100) / max_height))/100
|
||||
|
||||
local rotation=self.object:get_rotation()
|
||||
local vrot = airutils.dir_to_rot(velocity,rotation)
|
||||
|
||||
local hpitch,hyaw = pitchroll2pitchyaw(angle_of_attack,roll)
|
||||
|
||||
local hrot = {x=vrot.x+hpitch,y=vrot.y-hyaw,z=roll}
|
||||
local hdir = airutils.rot_to_dir(hrot) --(hrot)
|
||||
local cross = vector.cross(velocity,hdir)
|
||||
local lift_dir = vector.normalize(vector.cross(cross,hdir))
|
||||
|
||||
local lift_coefficient = (0.24*math.abs(daoa)*(1/(0.025*daoa+3))^4*math.sign(daoa))
|
||||
local lift_val = math.abs((lift*(vector.length(striped_velocity)^2)*lift_coefficient)*curr_percent_height)
|
||||
if lift_val < 1 then lift_val = 1 end -- hipotetical aerodinamic wing will have no "lift" for down
|
||||
|
||||
if self._climb_speed then --for helicopters
|
||||
if (velocity.y) > self._climb_speed then lift_val = math.abs(airutils.gravity) end
|
||||
end
|
||||
if self._lift_dead_zone then
|
||||
if lift_val < (math.abs(airutils.gravity)+self._lift_dead_zone) and lift_val > (math.abs(airutils.gravity)-self._lift_dead_zone) then
|
||||
lift_val = math.abs(airutils.gravity)
|
||||
end
|
||||
end
|
||||
|
||||
if airutils.show_lift then
|
||||
core.chat_send_player(airutils.show_lift,core.colorize('#ffff00', " >>> lift: "..lift_val))
|
||||
end
|
||||
|
||||
local lift_acc = vector.multiply(lift_dir,lift_val)
|
||||
--lift_acc=vector.add(vector.multiply(core.yaw_to_dir(rotation.y),acc),lift_acc)
|
||||
|
||||
retval = vector.add(retval,lift_acc)
|
||||
-----------------------------------------------------------
|
||||
-- end lift
|
||||
|
||||
return retval
|
||||
end
|
||||
|
||||
function airutils.get_plane_pitch(y_velocity, longit_speed, min_speed, angle_of_attack)
|
||||
local v_speed_factor = 0
|
||||
if longit_speed > 0 then v_speed_factor = (y_velocity * math.rad(2)) end --the pitch for climbing or descenting
|
||||
local min_rotation_speed = min_speed/2
|
||||
local pitch_by_longit_speed = 0
|
||||
if longit_speed > min_rotation_speed then --just start the rotation after the rotation speed
|
||||
local scale_pitch_graph = ((longit_speed-min_rotation_speed)*1)/min_rotation_speed --lets use the min rotation speed for reference to when we will start the control work
|
||||
if scale_pitch_graph > 1 then scale_pitch_graph = 1 end --normalize to 100%
|
||||
pitch_by_longit_speed = airutils.quadBezier(scale_pitch_graph, 0, angle_of_attack, angle_of_attack) --here the magic happens using a bezier curve
|
||||
end
|
||||
return math.rad(pitch_by_longit_speed) + v_speed_factor
|
||||
end
|
||||
|
||||
function airutils.adjust_attack_angle_by_speed(angle_of_attack, min_angle, max_angle, limit, longit_speed, ideal_step, dtime)
|
||||
--coloca em nivel gradualmente
|
||||
local factor = 0
|
||||
if angle_of_attack > max_angle then factor = -1 end
|
||||
if angle_of_attack < min_angle then factor = 1 end
|
||||
local correction = (limit*(longit_speed/5000)) * factor * (dtime/ideal_step)
|
||||
--core.chat_send_all("angle: "..angle_of_attack.." - correction: "..correction)
|
||||
local new_angle_of_attack = angle_of_attack + correction
|
||||
|
||||
return new_angle_of_attack
|
||||
end
|
||||
|
||||
function airutils.elevator_auto_correction(self, longit_speed, dtime, max_speed, elevator_angle, elevator_limit, ideal_step, intensity)
|
||||
intensity = intensity or 500
|
||||
if longit_speed <= 0 then return end
|
||||
local factor = 1
|
||||
|
||||
if self._elevator_angle > 0 then factor = -1 end
|
||||
local ref_speed = longit_speed
|
||||
if ref_speed > max_speed then ref_speed = max_speed end
|
||||
local speed_scale = (elevator_limit + (elevator_limit/10)) - ((elevator_limit*ref_speed)/max_speed)
|
||||
local divisor = intensity
|
||||
speed_scale = speed_scale / divisor
|
||||
local correction = speed_scale * factor * (dtime/ideal_step)
|
||||
|
||||
local before_correction = elevator_angle
|
||||
local new_elevator_angle = elevator_angle + correction
|
||||
|
||||
if math.sign(before_correction) ~= math.sign(new_elevator_angle) then
|
||||
new_elevator_angle = 0
|
||||
end
|
||||
return new_elevator_angle
|
||||
end
|
||||
|
||||
function airutils.set_paint(self, puncher, itmstck, texture_name)
|
||||
local item_name = ""
|
||||
if itmstck then item_name = itmstck:get_name() end
|
||||
|
||||
if item_name == "automobiles_lib:painter" or item_name == "bike:painter" then
|
||||
--painting with bike painter
|
||||
local meta = itmstck:get_meta()
|
||||
local colstr = meta:get_string("paint_color")
|
||||
--core.chat_send_all(dump(colstr))
|
||||
airutils.paint(self, colstr, texture_name)
|
||||
return true
|
||||
else
|
||||
--painting with dyes
|
||||
local split = string.split(item_name, ":")
|
||||
local indx, _
|
||||
if split[1] then _,indx = split[1]:find('dye') end
|
||||
if indx then
|
||||
--[[for clr,_ in pairs(airutils.colors) do
|
||||
local _,x = split[2]:find(clr)
|
||||
if x then color = clr end
|
||||
end]]--
|
||||
--lets paint!!!!
|
||||
local color = (item_name:sub(indx+1)):gsub(":", "")
|
||||
local colstr = airutils.colors[color]
|
||||
--core.chat_send_all(color ..' '.. dump(colstr))
|
||||
if colstr then
|
||||
airutils.paint(self, colstr, texture_name)
|
||||
if self._alternate_painting_texture and self._mask_painting_texture then
|
||||
airutils.paint_with_mask(self, colstr, self._alternate_painting_texture, self._mask_painting_texture)
|
||||
end
|
||||
itmstck:set_count(itmstck:get_count()-1)
|
||||
if puncher ~= nil then puncher:set_wielded_item(itmstck) end
|
||||
return true
|
||||
end
|
||||
-- end painting
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function airutils._set_name(self)
|
||||
if not airutils._use_signs_api then return end
|
||||
local l_textures = self.object:get_properties().textures --self.initial_properties.textures
|
||||
for _, texture in ipairs(l_textures) do
|
||||
local indx = texture:find('airutils_name_canvas.png')
|
||||
if indx then
|
||||
l_textures[_] = "airutils_name_canvas.png^"..airutils.convert_text_to_texture(self._ship_name, self._name_color or 0, self._name_hor_aligment or 0.8)
|
||||
end
|
||||
end
|
||||
self.object:set_properties({textures=l_textures})
|
||||
end
|
||||
|
||||
--painting
|
||||
function airutils.paint(self, colstr, texture_name)
|
||||
if not self then return end
|
||||
if colstr then
|
||||
self._color = colstr
|
||||
local l_textures = self.initial_properties.textures
|
||||
for _, texture in ipairs(l_textures) do
|
||||
local indx = texture:find(texture_name)
|
||||
if indx then
|
||||
l_textures[_] = texture_name.."^[multiply:".. colstr
|
||||
end
|
||||
end
|
||||
self.object:set_properties({textures=l_textures})
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.getAngleFromPositions(origin, destiny)
|
||||
local angle_north = math.deg(math.atan2(destiny.x - origin.x, destiny.z - origin.z))
|
||||
if angle_north < 0 then angle_north = angle_north + 360 end
|
||||
return angle_north
|
||||
end
|
||||
|
||||
function airutils.sit(player)
|
||||
--set_animation(frame_range, frame_speed, frame_blend, frame_loop)
|
||||
player:set_animation({x = 81, y = 160},30, 0, true)
|
||||
if core.get_modpath("emote") then emote.start(player:get_player_name(), "sit") end
|
||||
end
|
||||
|
||||
local function get_norm_angle(angle)
|
||||
local new_angle = angle/360
|
||||
new_angle = (new_angle - math.floor(new_angle))*360
|
||||
if new_angle < -180 then new_angle = new_angle + 360 end
|
||||
if new_angle > 180 then new_angle = new_angle - 360 end
|
||||
return new_angle
|
||||
end
|
||||
|
||||
function airutils.normalize_rotations(rotations)
|
||||
return {x = get_norm_angle(rotations.x), y = get_norm_angle(rotations.y), z = get_norm_angle(rotations.z)}
|
||||
end
|
||||
|
||||
core.register_chatcommand("enable_blast_damage", {
|
||||
params = "<true/false>",
|
||||
description = S("Enable/disable explosion blast damage"),
|
||||
privs = {server=true},
|
||||
func = function(name, param)
|
||||
local command = param
|
||||
|
||||
if command == "false" then
|
||||
airutils.blast_damage = false
|
||||
core.chat_send_player(name, S(">>> Blast damage by explosion is disabled"))
|
||||
else
|
||||
airutils.blast_damage = true
|
||||
core.chat_send_player(name, S(">>> Blast damage by explosion is enabled"))
|
||||
end
|
||||
local save = 2
|
||||
if airutils.blast_damage == true then save = 1 end
|
||||
storage:set_int("blast_damage", save)
|
||||
end,
|
||||
})
|
||||
|
||||
core.register_chatcommand("transfer_ownership", {
|
||||
params = "<new_owner>",
|
||||
description = S("Transfer the property of a plane to another player"),
|
||||
privs = {interact=true},
|
||||
func = function(name, param)
|
||||
local player = core.get_player_by_name(name)
|
||||
local target_player = core.get_player_by_name(param)
|
||||
local attached_to = player:get_attach()
|
||||
|
||||
if attached_to ~= nil then
|
||||
if target_player ~= nil then
|
||||
local seat = attached_to:get_attach()
|
||||
if seat ~= nil then
|
||||
local entity = seat:get_luaentity()
|
||||
if entity then
|
||||
if entity.owner == name or core.check_player_privs(name, {protection_bypass=true}) then
|
||||
entity.owner = param
|
||||
core.chat_send_player(name,core.colorize('#00ff00', S(" >>> This plane now is property of: ")..param))
|
||||
else
|
||||
core.chat_send_player(name,core.colorize('#ff0000', S(" >>> only the owner or moderators can transfer this airplane")))
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
core.chat_send_player(name,core.colorize('#ff0000', S(" >>> the target player must be logged in")))
|
||||
end
|
||||
else
|
||||
core.chat_send_player(name,core.colorize('#ff0000', S(" >>> you are not inside a plane to perform the command")))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
core.register_chatcommand("eject_from_plane", {
|
||||
params = "",
|
||||
description = S("Ejects from a plane"),
|
||||
privs = {interact = true},
|
||||
func = function(name, param)
|
||||
local colorstring = core.colorize('#ff0000', S(" >>> you are not inside a plane"))
|
||||
local player = core.get_player_by_name(name)
|
||||
local attached_to = player:get_attach()
|
||||
|
||||
if attached_to ~= nil then
|
||||
local seat = attached_to:get_attach()
|
||||
if seat ~= nil then
|
||||
local entity = seat:get_luaentity()
|
||||
if entity then
|
||||
if entity.on_step == airutils.on_step then
|
||||
if entity.driver_name == name then
|
||||
airutils.dettachPlayer(entity, player)
|
||||
elseif entity._passenger == name then
|
||||
local passenger = core.get_player_by_name(entity._passenger)
|
||||
airutils.dettach_pax(entity, passenger)
|
||||
end
|
||||
else
|
||||
core.chat_send_player(name,colorstring)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
core.chat_send_player(name,colorstring)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
core.register_chatcommand("ground_effect", {
|
||||
params = "<on/off>",
|
||||
description = S("Enables/disables the ground effect (for debug purposes)"),
|
||||
privs = {server=true},
|
||||
func = function(name, param)
|
||||
if core.check_player_privs(name, {server=true}) then
|
||||
if param == "on" or param == "" then
|
||||
airutils.ground_effect_is_disabled = nil
|
||||
core.chat_send_player(name,core.colorize('#00ff00', S(" >>> Ground effect was turned on.")))
|
||||
elseif param == "off" then
|
||||
airutils.ground_effect_is_disabled = true
|
||||
core.chat_send_player(name,core.colorize('#0000ff', S(">>> Ground effect was turned off.")))
|
||||
end
|
||||
else
|
||||
core.chat_send_player(name,core.colorize('#ff0000', S(" >>> You need 'server' priv to run this command.")))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
core.register_chatcommand("show_lift", {
|
||||
params = "<on/off>",
|
||||
description = S("Enables/disables the lift printing (for debug purposes)"),
|
||||
privs = {server=true},
|
||||
func = function(name, param)
|
||||
if core.check_player_privs(name, {server=true}) then
|
||||
if param == "on" or param == "" then
|
||||
airutils.show_lift = name
|
||||
core.chat_send_player(name,core.colorize('#0000ff', S(" >>> Lift printing turned on.")))
|
||||
elseif param == "off" then
|
||||
airutils.show_lift = nil
|
||||
core.chat_send_player(name,core.colorize('#00ff00', S(" >>> Lift printing turned off.")))
|
||||
end
|
||||
else
|
||||
core.chat_send_player(name,core.colorize('#ff0000', S(" >>> You need 'server' priv to run this command.")))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
if airutils._use_signs_api then
|
||||
local function prefix_change(name, param)
|
||||
local colorstring = core.colorize('#ff0000', S(" >>> you are not inside a vehicle"))
|
||||
local player = core.get_player_by_name(name)
|
||||
if not player then return end
|
||||
local attached_to = player:get_attach()
|
||||
|
||||
if attached_to ~= nil then
|
||||
local seat = attached_to:get_attach()
|
||||
if seat ~= nil then
|
||||
local entity = seat:get_luaentity()
|
||||
if entity then
|
||||
if entity.owner == name or core.check_player_privs(name, {protection_bypass=true}) then
|
||||
if param then
|
||||
entity._ship_name = string.sub(param, 1, 40)
|
||||
else
|
||||
entity._ship_name = ""
|
||||
end
|
||||
airutils._set_name(entity)
|
||||
core.chat_send_player(name,core.colorize('#00ff00', S(" >>> the vehicle name was changed")))
|
||||
else
|
||||
core.chat_send_player(name,core.colorize('#ff0000', S(" >>> only the owner or moderators can name this vehicle")))
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
core.chat_send_player(name,colorstring)
|
||||
end
|
||||
end
|
||||
|
||||
core.register_chatcommand("set_vehicle_name", {
|
||||
params = "<name>",
|
||||
description = S("this command is an alias for /set_prefix"),
|
||||
privs = {interact = true},
|
||||
func = prefix_change,
|
||||
})
|
||||
|
||||
core.register_chatcommand("set_prefix", {
|
||||
params = "<name>",
|
||||
description = S("Sets the vehicle prefix"),
|
||||
privs = {interact = true},
|
||||
func = prefix_change,
|
||||
})
|
||||
end
|
217
mods/airutils/inventory_management.lua
Normal file
|
@ -0,0 +1,217 @@
|
|||
local storage = airutils.storage
|
||||
airutils.modname = core.get_current_modname()
|
||||
|
||||
--function to format formspec for mineclone. In case of minetest, just returns an empty string
|
||||
function airutils.get_itemslot_bg(a, b, c, d)
|
||||
if airutils.is_mcl then
|
||||
if mcl_formspec then
|
||||
return mcl_formspec.get_itemslot_bg(a,b,c,d)
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function get_formspec_by_size(self, size)
|
||||
local background = ""
|
||||
local hotbar = ""
|
||||
local is_minetest_game = airutils.is_minetest or false
|
||||
if is_minetest_game then
|
||||
background = background .. default.gui_bg .. default.gui_bg_img .. default.gui_slots
|
||||
hotbar = default.get_hotbar_bg(0,4.85)
|
||||
end
|
||||
local default_inventory_formspecs = {
|
||||
["2"]="size[8,6]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;3.0,0;3,1;]" .. airutils.get_itemslot_bg(3.0, 0, 2, 1) ..
|
||||
"list[current_player;main;0,2;8,4;]" .. airutils.get_itemslot_bg(0, 2, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["3"]="size[8,6]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;2.5,0;3,1;]" .. airutils.get_itemslot_bg(2.5, 0, 3, 1) ..
|
||||
"list[current_player;main;0,2;8,4;]" .. airutils.get_itemslot_bg(0, 2, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["4"]="size[8,6]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;2,0;4,1;]" .. airutils.get_itemslot_bg(2.0, 0, 4, 1) ..
|
||||
"list[current_player;main;0,2;8,4;]" .. airutils.get_itemslot_bg(0, 2, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["6"]="size[8,6]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;1,0;6,1;]".. airutils.get_itemslot_bg(1.0, 0, 6, 1) ..
|
||||
"list[current_player;main;0,2;8,4;]" .. airutils.get_itemslot_bg(0, 2, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["8"]="size[8,6]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;0,0;8,1;]".. airutils.get_itemslot_bg(0, 0, 8, 1) ..
|
||||
"list[current_player;main;0,2;8,4;]" .. airutils.get_itemslot_bg(0, 2, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["12"]="size[8,7]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;1,0;6,2;]".. airutils.get_itemslot_bg(1, 0, 6, 2) ..
|
||||
"list[current_player;main;0,3;8,4;]" .. airutils.get_itemslot_bg(0, 3, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["16"]="size[8,7]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;0,0;8,2;]".. airutils.get_itemslot_bg(0, 0, 8, 2) ..
|
||||
"list[current_player;main;0,3;8,4;]" .. airutils.get_itemslot_bg(0, 3, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["24"]="size[8,8]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;0,0;8,3;]".. airutils.get_itemslot_bg(0, 0, 8, 3) ..
|
||||
"list[current_player;main;0,4;8,4;]" .. airutils.get_itemslot_bg(0, 4, 8, 4) ..
|
||||
"listring[]",
|
||||
|
||||
["32"]="size[8,9]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;0,0.3;8,4;]".. airutils.get_itemslot_bg(0, 0.3, 8, 4) ..
|
||||
"list[current_player;main;0,5;8,4;]".. airutils.get_itemslot_bg(0, 5, 8, 4) ..
|
||||
"listring[]" ..
|
||||
hotbar,
|
||||
|
||||
["50"]="size[10,10]".. background ..
|
||||
"list[detached:" .. self._inv_id .. ";main;0,0;10,5;]".. airutils.get_itemslot_bg(0, 0, 10, 5) ..
|
||||
"list[current_player;main;1,6;8,4;]" .. airutils.get_itemslot_bg(1, 6, 8, 4) ..
|
||||
"listring[]",
|
||||
}
|
||||
|
||||
local formspec = default_inventory_formspecs[tostring(size)]
|
||||
return formspec
|
||||
end
|
||||
|
||||
local function inventory_id(maker_name)
|
||||
local id= airutils.modname .. "_" .. maker_name .. "_"
|
||||
for i=0,5 do
|
||||
id=id..(math.random(0,9))
|
||||
end
|
||||
return id
|
||||
end
|
||||
|
||||
function airutils.load_inventory(self)
|
||||
if self._inv then
|
||||
local inv_content = core.deserialize(storage:get_string(self._inv_id))
|
||||
if inv_content then
|
||||
self._inv:set_list("main", inv_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.save_inventory(self)
|
||||
if self._inv then
|
||||
local inv_content = self._inv:get_list("main")
|
||||
if inv_content then
|
||||
for k, v in pairs(inv_content) do
|
||||
inv_content[k] = v:to_string()
|
||||
end
|
||||
|
||||
local inv_content = core.serialize(inv_content)
|
||||
storage:set_string(self._inv_id, inv_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.remove_inventory(self)
|
||||
local inventory = airutils.get_inventory(self)
|
||||
if inventory then
|
||||
if inventory:is_empty("main") then
|
||||
return core.remove_detached_inventory(self._inv_id)
|
||||
else
|
||||
local inv_content = inventory:get_list("main")
|
||||
if inv_content then
|
||||
local pos = self.object:get_pos()
|
||||
for k, v in pairs(inv_content) do
|
||||
local count = 0
|
||||
for i = 0,v:get_count()-1,1
|
||||
do
|
||||
core.add_item({x=pos.x+math.random()-0.5,y=pos.y,z=pos.z+math.random()-0.5},v:get_name())
|
||||
count = count + 1
|
||||
if count >= 5 then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
return core.remove_detached_inventory(self._inv_id)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function airutils.destroy_inventory(self)
|
||||
airutils.remove_inventory(self)
|
||||
storage:set_string(self._inv_id, nil)
|
||||
end
|
||||
|
||||
--show inventory form to user
|
||||
function airutils.show_vehicle_trunk_formspec(self, player, size)
|
||||
local form = get_formspec_by_size(self, size)
|
||||
core.show_formspec(player:get_player_name(), airutils.modname .. ":inventory",
|
||||
form
|
||||
)
|
||||
end
|
||||
|
||||
function airutils.create_inventory(self, size, owner)
|
||||
owner = owner or ""
|
||||
if owner == "" then owner = self.owner end
|
||||
--core.chat_send_all("slots: " .. size)
|
||||
if owner ~= nil and owner ~= "" then
|
||||
if self._inv_id == "" then
|
||||
self._inv_id = inventory_id(owner)
|
||||
end
|
||||
local vehicle_inv = core.create_detached_inventory(self._inv_id, {
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
local is_moderator = core.check_player_privs(player, {server=true}) or core.check_player_privs(player, {protection_bypass=true})
|
||||
if player:get_player_name() ~= owner and is_moderator == false then
|
||||
return 0
|
||||
end
|
||||
return count -- allow moving
|
||||
end,
|
||||
|
||||
allow_put = function(inv, listname, index, stack, player)
|
||||
local is_moderator = core.check_player_privs(player, {server=true}) or core.check_player_privs(player, {protection_bypass=true})
|
||||
if player:get_player_name() ~= owner and is_moderator == false then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count() -- allow putting
|
||||
end,
|
||||
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
local is_moderator = core.check_player_privs(player, {server=true}) or core.check_player_privs(player, {protection_bypass=true})
|
||||
if player:get_player_name() ~= owner and is_moderator == false then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count() -- allow taking
|
||||
end,
|
||||
on_put = function(inv, toList, toIndex, stack, player)
|
||||
airutils.save_inventory(self)
|
||||
end,
|
||||
on_take = function(inv, toList, toIndex, stack, player)
|
||||
airutils.save_inventory(self)
|
||||
end,
|
||||
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
airutils.save_inventory(self)
|
||||
end,
|
||||
}, owner)
|
||||
if size >= 8 then
|
||||
if vehicle_inv:set_size("main", size) then
|
||||
vehicle_inv:set_width("main", 8)
|
||||
end
|
||||
else
|
||||
vehicle_inv:set_size("main", size)
|
||||
end
|
||||
self._inv = vehicle_inv
|
||||
airutils.load_inventory(self)
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.get_inventory(self)
|
||||
if self._inv then
|
||||
return core.get_inventory({type="detached", name=self._inv_id})
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function airutils.list_inventory(self)
|
||||
local inventory = airutils.get_inventory(self)
|
||||
if inventory then
|
||||
local list = inventory.get_list("main")
|
||||
|
||||
core.chat_send_all(dump(list))
|
||||
end
|
||||
end
|
||||
|
167
mods/airutils/lib_copter/control.lua
Normal file
|
@ -0,0 +1,167 @@
|
|||
--[[airutils.rudder_limit = 30
|
||||
airutils.elevator_limit = 40]]--
|
||||
local S = airutils.S
|
||||
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "utilities.lua")
|
||||
|
||||
local function set_yaw_by_mouse(self, dir)
|
||||
local rotation = self.object:get_rotation()
|
||||
local rot_y = math.deg(rotation.y)
|
||||
|
||||
local total = math.abs(math.floor(rot_y/360))
|
||||
|
||||
if rot_y < 0 then rot_y = rot_y + (360*total) end
|
||||
if rot_y > 360 then rot_y = rot_y - (360*total) end
|
||||
if rot_y >= 270 and dir <= 90 then dir = dir + 360 end
|
||||
if rot_y <= 90 and dir >= 270 then dir = dir - 360 end
|
||||
|
||||
local intensity = self._yaw_intensity / 10
|
||||
local command = (rot_y - dir) * intensity
|
||||
if command < -90 then command = -90
|
||||
elseif command > 90 then command = 90 end
|
||||
--minetest.chat_send_all("rotation y: "..rot_y.." - dir: "..dir.." - command: "..command)
|
||||
|
||||
self._rudder_angle = (-command * self._rudder_limit)/90
|
||||
end
|
||||
|
||||
local function set_yaw(self, dir, dtime)
|
||||
local yaw_factor = self._yaw_intensity or 25
|
||||
if dir == 1 then
|
||||
self._rudder_angle = math.max(self._rudder_angle-(yaw_factor*dtime),-self._rudder_limit)
|
||||
elseif dir == -1 then
|
||||
self._rudder_angle = math.min(self._rudder_angle+(yaw_factor*dtime),self._rudder_limit)
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.heli_control(self, dtime, hull_direction, longit_speed, longit_drag, nhdir,
|
||||
later_speed, later_drag, accel, player, is_flying)
|
||||
--if self.driver_name == nil then return end
|
||||
local retval_accel = accel
|
||||
|
||||
local stop = false
|
||||
local ctrl
|
||||
|
||||
local time_correction = (dtime/airutils.ideal_step)
|
||||
if time_correction < 1 then time_correction = 1 end
|
||||
self._vehicle_acc = self._vehicle_acc or 0
|
||||
|
||||
-- player control
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
|
||||
if self._last_time_command > 0.5 then
|
||||
self._last_time_command = 0.5
|
||||
end
|
||||
|
||||
if not self._acceleration then self._acceleration = 0 end
|
||||
if not self._lat_acceleration then self._lat_acceleration = 0 end
|
||||
|
||||
if self._engine_running then
|
||||
--control lift
|
||||
local collective_up_max = 1.2
|
||||
local min_angle = self._min_collective
|
||||
local collective_up = collective_up_max / 10
|
||||
if ctrl.jump then
|
||||
self._wing_configuration = self._wing_configuration + collective_up
|
||||
--end
|
||||
self._is_going_up = true
|
||||
elseif ctrl.sneak then
|
||||
self._wing_configuration = self._wing_configuration - collective_up
|
||||
--end
|
||||
else
|
||||
self._wing_configuration = self._stable_collective
|
||||
end
|
||||
if self._wing_configuration < min_angle then self._wing_configuration = min_angle end
|
||||
local up_limit = (self._wing_angle_of_attack+collective_up_max)
|
||||
if self._wing_configuration > up_limit then self._wing_configuration = up_limit end
|
||||
--end lift
|
||||
else
|
||||
self._wing_configuration = self._stable_collective or 1
|
||||
end
|
||||
|
||||
local yaw_cmd = 0
|
||||
if is_flying or self.wheels then
|
||||
local acc_fraction = (self._max_engine_acc / 40)*time_correction
|
||||
if ctrl.up then
|
||||
if longit_speed < self._max_speed then
|
||||
self._acceleration = self._acceleration + acc_fraction
|
||||
else
|
||||
self._acceleration = 0
|
||||
end
|
||||
elseif ctrl.down then
|
||||
if longit_speed > -self._max_speed then
|
||||
self._acceleration = self._acceleration + (-acc_fraction)
|
||||
else
|
||||
self._acceleration = 0
|
||||
end
|
||||
else
|
||||
self._acceleration = 0
|
||||
end
|
||||
self._acceleration = math.min(self._acceleration,self._max_engine_acc)
|
||||
self._acceleration = math.max(self._acceleration,-self._max_engine_acc)
|
||||
|
||||
if is_flying then --why double check? because I dont want lateral movement when landed
|
||||
if ctrl.right then
|
||||
yaw_cmd = 1
|
||||
if later_speed < self._max_speed and self._yaw_by_mouse then
|
||||
self._lat_acceleration = self._lat_acceleration + acc_fraction
|
||||
else
|
||||
self._lat_acceleration = 0
|
||||
end
|
||||
elseif ctrl.left then
|
||||
yaw_cmd = -1
|
||||
if later_speed > -self._max_speed and self._yaw_by_mouse then
|
||||
self._lat_acceleration = self._lat_acceleration + (-acc_fraction)
|
||||
else
|
||||
self._lat_acceleration = 0
|
||||
end
|
||||
else
|
||||
self._lat_acceleration = 0
|
||||
end
|
||||
end
|
||||
else
|
||||
self._acceleration = 0
|
||||
self._lat_acceleration = 0
|
||||
self.object:set_velocity({x=0,y=self.object:get_velocity().y,z=0})
|
||||
end
|
||||
|
||||
self._vehicle_acc = math.min(self._acceleration, self._max_engine_acc)
|
||||
self._vehicle_acc = math.max(self._acceleration,-self._max_engine_acc)
|
||||
self._lat_acc = math.min(self._lat_acceleration, self._max_engine_acc)
|
||||
|
||||
local hull_acc = vector.multiply(hull_direction,self._vehicle_acc)
|
||||
local lat_hull_acc = vector.multiply(nhdir,self._lat_acc)
|
||||
--colocar aceleração lateral aqui
|
||||
retval_accel=vector.add(retval_accel,hull_acc)
|
||||
retval_accel=vector.add(retval_accel,lat_hull_acc)
|
||||
|
||||
-- yaw
|
||||
if self._yaw_by_mouse then
|
||||
local rot_y = math.deg(player:get_look_horizontal())
|
||||
set_yaw_by_mouse(self, rot_y)
|
||||
else
|
||||
set_yaw(self, yaw_cmd, dtime)
|
||||
end
|
||||
|
||||
--I'm desperate, center all!
|
||||
if ctrl.right and ctrl.left then
|
||||
self._wing_configuration = self._stable_collective
|
||||
end
|
||||
|
||||
if ctrl.up and ctrl.down and self._last_time_command >= 0.5 then
|
||||
self._last_time_command = 0
|
||||
local name = player:get_player_name()
|
||||
if self._yaw_by_mouse == true then
|
||||
minetest.chat_send_player(name, core.colorize('#0000ff', S(" >>> Mouse control disabled.")))
|
||||
self._yaw_by_mouse = false
|
||||
else
|
||||
minetest.chat_send_player(name, core.colorize('#0000ff', S(" >>> Mouse control enabled.")))
|
||||
self._yaw_by_mouse = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return retval_accel, stop
|
||||
end
|
||||
|
||||
|
382
mods/airutils/lib_copter/entities.lua
Normal file
|
@ -0,0 +1,382 @@
|
|||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "global_definitions.lua")
|
||||
|
||||
local function engineSoundPlay(self, increment, base)
|
||||
increment = increment or 0.0
|
||||
--sound
|
||||
if self.sound_handle then minetest.sound_stop(self.sound_handle) end
|
||||
if self.object then
|
||||
local base_pitch = base
|
||||
local pitch_adjust = base_pitch + increment
|
||||
self.sound_handle = minetest.sound_play({name = self._engine_sound},
|
||||
{object = self.object, gain = 2.0,
|
||||
pitch = pitch_adjust,
|
||||
max_hear_distance = 32,
|
||||
loop = true,})
|
||||
end
|
||||
end
|
||||
|
||||
local function engine_set_sound_and_animation(self, is_flying, newpitch, newroll)
|
||||
is_flying = is_flying or false
|
||||
|
||||
if self._engine_running then --engine running
|
||||
if not self.sound_handle then
|
||||
engineSoundPlay(self, 0.0, 0.9)
|
||||
end
|
||||
--self._cmd_snd
|
||||
if self._snd_last_cmd ~= self._cmd_snd then
|
||||
local increment
|
||||
self._snd_last_cmd = self._cmd_snd
|
||||
if self._cmd_snd then increment = 0.1 else increment = 0.0 end
|
||||
engineSoundPlay(self, increment, 0.9)
|
||||
end
|
||||
|
||||
self.object:set_animation_frame_speed(100)
|
||||
else
|
||||
if is_flying then --autorotation here
|
||||
if self._snd_last_cmd ~= self._cmd_snd then
|
||||
local increment
|
||||
self._snd_last_cmd = self._cmd_snd
|
||||
if self._cmd_snd then increment = 0.1 else increment = 0.0 end
|
||||
engineSoundPlay(self, increment, 0.6)
|
||||
end
|
||||
|
||||
self.object:set_animation_frame_speed(70)
|
||||
else --stop all
|
||||
if self.sound_handle then
|
||||
self._snd_last_roll = nil
|
||||
self._snd_last_pitch = nil
|
||||
minetest.sound_stop(self.sound_handle)
|
||||
self.sound_handle = nil
|
||||
self.object:set_animation_frame_speed(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.logic_heli(self)
|
||||
local velocity = self.object:get_velocity()
|
||||
local curr_pos = self.object:get_pos()
|
||||
self._curr_pos = curr_pos --shared
|
||||
self._last_accel = self.object:get_acceleration()
|
||||
|
||||
self._last_time_command = self._last_time_command + self.dtime
|
||||
|
||||
if self._last_time_command > 1 then self._last_time_command = 1 end
|
||||
|
||||
local player = nil
|
||||
if self.driver_name then player = minetest.get_player_by_name(self.driver_name) end
|
||||
local co_pilot = nil
|
||||
if self.co_pilot and self._have_copilot then co_pilot = minetest.get_player_by_name(self.co_pilot) end
|
||||
|
||||
--test collision
|
||||
airutils.testImpact(self, velocity, curr_pos)
|
||||
|
||||
local ctrl = nil
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
---------------------
|
||||
-- change the driver
|
||||
---------------------
|
||||
if co_pilot and self._have_copilot and self._last_time_command >= 1 then
|
||||
if self._command_is_given == true then
|
||||
if ctrl.sneak or ctrl.jump or ctrl.up or ctrl.down or ctrl.right or ctrl.left then
|
||||
self._last_time_command = 0
|
||||
--take the control
|
||||
airutils.transfer_control(self, false)
|
||||
end
|
||||
else
|
||||
if ctrl.sneak == true and ctrl.jump == true then
|
||||
self._last_time_command = 0
|
||||
--trasnfer the control to student
|
||||
airutils.transfer_control(self, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not self.object:get_acceleration() then return end
|
||||
local accel_y = self.object:get_acceleration().y
|
||||
local rotation = self.object:get_rotation()
|
||||
local yaw = rotation.y
|
||||
local newyaw=yaw
|
||||
local roll = rotation.z
|
||||
|
||||
local hull_direction = airutils.rot_to_dir(rotation) --minetest.yaw_to_dir(yaw)
|
||||
local nhdir = {x=hull_direction.z,y=0,z=-hull_direction.x} -- lateral unit vector
|
||||
|
||||
local longit_speed = vector.dot(velocity,hull_direction)
|
||||
self._longit_speed = longit_speed
|
||||
|
||||
local longit_drag = vector.multiply(hull_direction,longit_speed*
|
||||
longit_speed*self._longit_drag_factor*-1*airutils.sign(longit_speed))
|
||||
local later_speed = airutils.dot(velocity,nhdir)
|
||||
--minetest.chat_send_all('later_speed: '.. later_speed)
|
||||
local later_drag = vector.multiply(nhdir,later_speed*later_speed*
|
||||
self._later_drag_factor*-1*airutils.sign(later_speed))
|
||||
local accel = vector.add(longit_drag,later_drag)
|
||||
local stop = false
|
||||
|
||||
local is_flying = true
|
||||
if self.colinfo then
|
||||
is_flying = (not self.colinfo.touching_ground)
|
||||
end
|
||||
if self.isinliquid == true then
|
||||
is_flying = false
|
||||
end
|
||||
--if self.isonground then is_flying = false end
|
||||
--if is_flying then minetest.chat_send_all('is flying') end
|
||||
|
||||
local is_attached = airutils.checkAttach(self, player)
|
||||
if self._indicated_speed == nil then self._indicated_speed = 0 end
|
||||
|
||||
if not is_attached then
|
||||
-- for some engine error the player can be detached from the machine, so lets set him attached again
|
||||
airutils.checkattachBug(self)
|
||||
end
|
||||
|
||||
if self._custom_step_additional_function then
|
||||
self._custom_step_additional_function(self)
|
||||
end
|
||||
|
||||
--landing light
|
||||
if self._have_landing_lights then
|
||||
airutils.landing_lights_operate(self)
|
||||
end
|
||||
|
||||
--smoke and fire
|
||||
if self._engine_running then
|
||||
local curr_health_percent = (self.hp_max * 100)/self._max_plane_hp
|
||||
if curr_health_percent < 20 then
|
||||
airutils.add_smoke_trail(self, 2)
|
||||
elseif curr_health_percent < 50 then
|
||||
airutils.add_smoke_trail(self, 1)
|
||||
end
|
||||
else
|
||||
if self._smoke_spawner and not self._smoke_semaphore then
|
||||
self._smoke_semaphore = 1 --to set it only one time
|
||||
minetest.after(5, function()
|
||||
if self._smoke_spawner then
|
||||
minetest.delete_particlespawner(self._smoke_spawner)
|
||||
self._smoke_spawner = nil
|
||||
self._smoke_semaphore = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
if (math.abs(velocity.x) < 0.1 and math.abs(velocity.z) < 0.1) and is_flying == false and is_attached == false and self._engine_running == false then
|
||||
if self._ground_friction then
|
||||
if not self.isinliquid then self.object:set_velocity({x=0,y=airutils.gravity*self.dtime,z=0}) end
|
||||
end
|
||||
engine_set_sound_and_animation(self, false, 0, 0)
|
||||
return
|
||||
end
|
||||
|
||||
--adjust climb indicator
|
||||
local y_velocity = 0
|
||||
if self._engine_running or is_flying then y_velocity = velocity.y end
|
||||
local climb_rate = y_velocity
|
||||
if climb_rate > 5 then climb_rate = 5 end
|
||||
if climb_rate < -5 then
|
||||
climb_rate = -5
|
||||
end
|
||||
|
||||
-- pitch and roll
|
||||
local newroll = 0
|
||||
local newpitch = 0
|
||||
if ctrl and is_flying then
|
||||
local command_angle = self._tilt_angle or 0
|
||||
local max_acc = self._max_engine_acc
|
||||
|
||||
local pitch_ammount = (math.abs(self._vehicle_acc or 0) * command_angle) / max_acc
|
||||
if math.abs(longit_speed) >= self._max_speed then pitch_ammount = command_angle end --gambiarra pra continuar com angulo
|
||||
pitch_ammount = math.rad(math.min(pitch_ammount, command_angle))
|
||||
|
||||
if ctrl.up then newpitch = -pitch_ammount end
|
||||
if ctrl.down then newpitch = pitch_ammount end
|
||||
|
||||
local roll_ammount = (math.abs(self._lat_acc or 0) * command_angle) / max_acc
|
||||
if math.abs(later_speed) >= self._max_speed then roll_ammount = command_angle end --gambiarra pra continuar com angulo
|
||||
roll_ammount = math.rad(math.min(roll_ammount, command_angle))
|
||||
|
||||
if ctrl.left then newroll = -roll_ammount end
|
||||
if ctrl.right then newroll = roll_ammount end
|
||||
|
||||
if ctrl.up or ctrl.down or ctrl.left or ctrl.right then
|
||||
self._cmd_snd = true
|
||||
else
|
||||
self._cmd_snd = false
|
||||
end
|
||||
end
|
||||
|
||||
-- new yaw
|
||||
if math.abs(self._rudder_angle)>1.5 then
|
||||
local turn_rate = math.rad(self._yaw_turn_rate)
|
||||
local yaw_turn = self.dtime * math.rad(self._rudder_angle) * turn_rate * 4
|
||||
newyaw = yaw + yaw_turn
|
||||
end
|
||||
|
||||
---------------------------------
|
||||
-- end roll
|
||||
|
||||
local pilot = player
|
||||
if self._have_copilot then
|
||||
if self._command_is_given and co_pilot then
|
||||
pilot = co_pilot
|
||||
else
|
||||
self._command_is_given = false
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
--accell calculation block
|
||||
------------------------------------------------------
|
||||
if is_attached or co_pilot then
|
||||
accel, stop = airutils.heli_control(self, self.dtime, hull_direction,
|
||||
longit_speed, longit_drag, nhdir, later_speed, later_drag, accel, pilot, is_flying)
|
||||
end
|
||||
--end accell
|
||||
|
||||
--get disconnected players
|
||||
airutils.rescueConnectionFailedPassengers(self)
|
||||
|
||||
if accel == nil then accel = {x=0,y=0,z=0} end
|
||||
|
||||
--lift calculation
|
||||
accel.y = accel_y
|
||||
|
||||
--lets apply some bob in water
|
||||
if self.isinliquid then
|
||||
local bob = airutils.minmax(airutils.dot(accel,hull_direction),0.02) -- vertical bobbing
|
||||
if bob < 0 then bob = 0 end
|
||||
accel.y = accel.y + bob
|
||||
local max_pitch = 6
|
||||
local ref_speed = longit_speed * 20
|
||||
if ref_speed < 0 then ref_speed = 0 end
|
||||
local h_vel_compensation = ((ref_speed * 100)/max_pitch)/100
|
||||
if h_vel_compensation < 0 then h_vel_compensation = 0 end
|
||||
if h_vel_compensation > max_pitch then h_vel_compensation = max_pitch end
|
||||
--minetest.chat_send_all(h_vel_compensation)
|
||||
newpitch = newpitch + (velocity.y * math.rad(max_pitch - h_vel_compensation))
|
||||
end
|
||||
|
||||
local ceiling = 5000
|
||||
local blade_speed = self._rotor_speed or 15
|
||||
local limit = (self._max_speed)
|
||||
if self._engine_running == false then
|
||||
if is_flying then
|
||||
blade_speed = self._rotor_idle_speed or 12
|
||||
if math.abs(longit_speed) > 0.5 then blade_speed = self._rotor_idle_speed + (self._rotor_speed - self._rotor_idle_speed) / 2 end
|
||||
else
|
||||
blade_speed = 0.001 --to avoid division by 0
|
||||
end
|
||||
end
|
||||
local new_accel = airutils.getLiftAccel(self, {x=0, y=velocity.y, z=blade_speed}, {x=0, y=accel.y, z=blade_speed/self.dtime}, blade_speed, roll, curr_pos, self._lift, ceiling, self._wing_span)
|
||||
local y_accell = new_accel.y
|
||||
new_accel = vector.new(accel)
|
||||
new_accel.y = y_accell
|
||||
if velocity.y > limit then new_accel.y = 0 end --it isn't a rocket :/
|
||||
|
||||
--wind effects
|
||||
if airutils.wind and is_flying == true then
|
||||
local wind = airutils.get_wind(curr_pos, 0.1)
|
||||
new_accel = vector.add(new_accel, wind)
|
||||
end
|
||||
|
||||
if stop ~= true then --maybe == nil
|
||||
self._last_accell = new_accel
|
||||
self.object:move_to(curr_pos)
|
||||
--airutils.set_acceleration(self.object, new_accel)
|
||||
--local limit = self._climb_speed
|
||||
--if new_accel.y > limit then new_accel.y = limit end --it isn't a rocket :/
|
||||
|
||||
else
|
||||
if stop == true then
|
||||
self._last_accell = vector.new() --self.object:get_acceleration()
|
||||
self.object:set_acceleration({x=0,y=0,z=0})
|
||||
self.object:set_velocity({x=0,y=0,z=0})
|
||||
end
|
||||
end
|
||||
|
||||
if self.wheels then
|
||||
if is_flying == false then --isn't flying?
|
||||
--animate wheels
|
||||
local min_speed_animation = 0.1
|
||||
if math.abs(velocity.x) > min_speed_animation or math.abs(velocity.z) > min_speed_animation then
|
||||
self.wheels:set_animation_frame_speed(longit_speed * 10)
|
||||
else
|
||||
self.wheels:set_animation_frame_speed(0)
|
||||
end
|
||||
else
|
||||
--stop wheels
|
||||
self.wheels:set_animation_frame_speed(0)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- end accell
|
||||
------------------------------------------------------
|
||||
|
||||
------------------------------------------------------
|
||||
-- sound and animation
|
||||
------------------------------------------------------
|
||||
local is_ship_attached = self.object:get_attach()
|
||||
if is_ship_attached then
|
||||
engine_set_sound_and_animation(self, false, newpitch, newroll) --is attached to a mother ship, so stop all
|
||||
else
|
||||
engine_set_sound_and_animation(self, is_flying, newpitch, newroll)
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
--GAUGES
|
||||
--minetest.chat_send_all('rate '.. climb_rate)
|
||||
local climb_angle = airutils.get_gauge_angle(climb_rate)
|
||||
self._climb_rate = climb_rate
|
||||
|
||||
local indicated_speed = longit_speed * 0.9
|
||||
if indicated_speed < 0 then indicated_speed = 0 end
|
||||
self._indicated_speed = indicated_speed
|
||||
local speed_angle = airutils.get_gauge_angle(indicated_speed, -45)
|
||||
|
||||
--adjust power indicator
|
||||
local fixed_power = 60
|
||||
if self._engine_running == false then fixed_power = 0 end
|
||||
local power_indicator_angle = airutils.get_gauge_angle(fixed_power/10) + 90
|
||||
local fuel_in_percent = (self._energy * 1)/self._max_fuel
|
||||
local energy_indicator_angle = (180*fuel_in_percent)-180
|
||||
|
||||
if is_attached then
|
||||
if self._show_hud then
|
||||
airutils.update_hud(player, climb_angle, speed_angle, power_indicator_angle, energy_indicator_angle)
|
||||
else
|
||||
airutils.remove_hud(player)
|
||||
end
|
||||
end
|
||||
|
||||
if is_flying == false then
|
||||
newyaw = yaw
|
||||
end
|
||||
|
||||
if player and self._use_camera_relocation then
|
||||
--minetest.chat_send_all(dump(newroll))
|
||||
local new_eye_offset = airutils.camera_reposition(player, newpitch, newroll)
|
||||
player:set_eye_offset(new_eye_offset, {x = 0, y = 1, z = -30})
|
||||
end
|
||||
|
||||
--apply rotations
|
||||
self.object:set_rotation({x=newpitch,y=newyaw,z=newroll})
|
||||
--end
|
||||
|
||||
-- calculate energy consumption --
|
||||
airutils.consumptionCalc(self, accel)
|
||||
|
||||
--saves last velocity for collision detection (abrupt stop)
|
||||
self._last_accel = new_accel
|
||||
self._last_vel = self.object:get_velocity()
|
||||
self._last_longit_speed = longit_speed
|
||||
self._yaw = newyaw
|
||||
self._roll = newroll
|
||||
self._pitch = newpitch
|
||||
end
|
8
mods/airutils/lib_copter/init.lua
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_copter" .. DIR_DELIM .. "control.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_copter" .. DIR_DELIM .. "entities.lua")
|
||||
|
||||
|
||||
|
||||
|
313
mods/airutils/lib_planes/control.lua
Normal file
|
@ -0,0 +1,313 @@
|
|||
--global constants
|
||||
airutils.ideal_step = 0.02
|
||||
|
||||
--[[airutils.rudder_limit = 30
|
||||
airutils.elevator_limit = 40]]--
|
||||
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "utilities.lua")
|
||||
local S = airutils.S
|
||||
|
||||
function airutils.powerAdjust(self,dtime,factor,dir,max_power)
|
||||
local max = max_power or 100
|
||||
local add_factor = factor/2
|
||||
add_factor = add_factor * (dtime/airutils.ideal_step) --adjusting the command speed by dtime
|
||||
|
||||
if dir == 1 then
|
||||
if self._power_lever < max then
|
||||
self._power_lever = self._power_lever + add_factor
|
||||
end
|
||||
if self._power_lever > max then
|
||||
self._power_lever = max
|
||||
end
|
||||
end
|
||||
if dir == -1 then
|
||||
if self._power_lever > 0 then
|
||||
self._power_lever = self._power_lever - add_factor
|
||||
if self._power_lever < 0 then self._power_lever = 0 end
|
||||
end
|
||||
if self._power_lever <= 0 then
|
||||
self._power_lever = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.control(self, dtime, hull_direction, longit_speed, longit_drag,
|
||||
later_speed, later_drag, accel, player, is_flying)
|
||||
--if self.driver_name == nil then return end
|
||||
local retval_accel = accel
|
||||
|
||||
local stop = false
|
||||
local ctrl = nil
|
||||
|
||||
-- player control
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
|
||||
if ctrl.aux1 and self._last_time_command > 0.5 then
|
||||
self._last_time_command = 0
|
||||
|
||||
end
|
||||
----------------------------------
|
||||
-- flap operation
|
||||
----------------------------------
|
||||
if ctrl.aux1 and ctrl.sneak and self._last_time_command >= 0.3 and self._wing_angle_extra_flaps then
|
||||
self._last_time_command = 0
|
||||
airutils.flap_operate(self, player)
|
||||
end
|
||||
|
||||
self._acceleration = 0
|
||||
if self._engine_running then
|
||||
--engine acceleration calc
|
||||
local engineacc = (self._power_lever * self._max_engine_acc) / 100;
|
||||
|
||||
local factor = 1
|
||||
|
||||
--increase power lever
|
||||
if ctrl.jump then
|
||||
airutils.powerAdjust(self, dtime, factor, 1)
|
||||
end
|
||||
--decrease power lever
|
||||
if ctrl.sneak then
|
||||
airutils.powerAdjust(self, dtime, factor, -1)
|
||||
if self._power_lever <= 0 and is_flying == false then
|
||||
--break
|
||||
if longit_speed > 0 then
|
||||
engineacc = -1
|
||||
if (longit_speed + engineacc) < 0 then
|
||||
engineacc = longit_speed * -1
|
||||
end
|
||||
end
|
||||
if longit_speed < 0 then
|
||||
engineacc = 1
|
||||
if (longit_speed + engineacc) > 0 then
|
||||
engineacc = longit_speed * -1
|
||||
end
|
||||
end
|
||||
if math.abs(longit_speed) < 0.2 then
|
||||
stop = true
|
||||
end
|
||||
end
|
||||
end
|
||||
--do not exceed
|
||||
local max_speed = self._max_speed
|
||||
if longit_speed > max_speed then
|
||||
engineacc = engineacc - (longit_speed-max_speed)
|
||||
if engineacc < 0 then engineacc = 0 end
|
||||
end
|
||||
self._acceleration = engineacc
|
||||
else
|
||||
local paddleacc = 0
|
||||
if longit_speed < 1.0 then
|
||||
if ctrl.jump then paddleacc = 0.5 end
|
||||
end
|
||||
if longit_speed > -1.0 then
|
||||
if ctrl.sneak then paddleacc = -0.5 end
|
||||
end
|
||||
self._acceleration = paddleacc
|
||||
end
|
||||
|
||||
local hull_acc = vector.multiply(hull_direction,self._acceleration)
|
||||
retval_accel=vector.add(retval_accel,hull_acc)
|
||||
|
||||
--pitch
|
||||
local pitch_cmd = 0
|
||||
if self._yaw_by_mouse == true then
|
||||
airutils.set_pitch_by_mouse(self, player)
|
||||
else
|
||||
if ctrl.up then pitch_cmd = 1 elseif ctrl.down then pitch_cmd = -1 end
|
||||
airutils.set_pitch(self, pitch_cmd, dtime)
|
||||
end
|
||||
|
||||
-- yaw
|
||||
local yaw_cmd = 0
|
||||
if self._yaw_by_mouse == true then
|
||||
local rot_y = math.deg(player:get_look_horizontal())
|
||||
airutils.set_yaw_by_mouse(self, rot_y)
|
||||
else
|
||||
if ctrl.right then yaw_cmd = 1 elseif ctrl.left then yaw_cmd = -1 end
|
||||
airutils.set_yaw(self, yaw_cmd, dtime)
|
||||
end
|
||||
|
||||
--I'm desperate, center all!
|
||||
if ctrl.right and ctrl.left then
|
||||
self._elevator_angle = 0
|
||||
self._rudder_angle = 0
|
||||
end
|
||||
|
||||
if ctrl.up and ctrl.down and self._last_time_command > 0.5 then
|
||||
self._last_time_command = 0
|
||||
local name = player:get_player_name()
|
||||
if self._yaw_by_mouse == true then
|
||||
minetest.chat_send_player(name, core.colorize('#0000ff', S(" >>> Mouse control disabled.")))
|
||||
self._yaw_by_mouse = false
|
||||
else
|
||||
minetest.chat_send_player(name, core.colorize('#0000ff', S(" >>> Mouse control enabled.")))
|
||||
self._yaw_by_mouse = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if longit_speed > 0 then
|
||||
if ctrl then
|
||||
if not (ctrl.right or ctrl.left) then
|
||||
airutils.rudder_auto_correction(self, longit_speed, dtime)
|
||||
end
|
||||
else
|
||||
airutils.rudder_auto_correction(self, longit_speed, dtime)
|
||||
end
|
||||
if airutils.elevator_auto_correction then
|
||||
self._elevator_angle = airutils.elevator_auto_correction(self, longit_speed, self.dtime, self._max_speed, self._elevator_angle, self._elevator_limit, airutils.ideal_step, 100)
|
||||
end
|
||||
end
|
||||
|
||||
return retval_accel, stop
|
||||
end
|
||||
|
||||
function airutils.set_pitch_by_mouse(self, player)
|
||||
local vehicle_rot = self.object:get_rotation()
|
||||
local rot_x = player:get_look_vertical()-vehicle_rot.x
|
||||
self._elevator_angle = -(rot_x * self._elevator_limit)*(self._pitch_intensity*10)
|
||||
if self._elevator_angle > self._elevator_limit then self._elevator_angle = self._elevator_limit end
|
||||
if self._elevator_angle < -self._elevator_limit then self._elevator_angle = -self._elevator_limit end
|
||||
end
|
||||
|
||||
function airutils.set_pitch(self, dir, dtime)
|
||||
local pitch_factor = self._pitch_intensity or 0.6
|
||||
local multiplier = pitch_factor*(dtime/airutils.ideal_step)
|
||||
if dir == -1 then
|
||||
--minetest.chat_send_all("cabrando")
|
||||
self._elevator_angle = math.max(self._elevator_angle-multiplier,-self._elevator_limit)
|
||||
elseif dir == 1 then
|
||||
--minetest.chat_send_all("picando")
|
||||
self._elevator_angle = math.min(self._elevator_angle+multiplier,self._elevator_limit)
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.set_autopilot_pitch(self, dir, dtime)
|
||||
local pitch_factor = 0.05
|
||||
local multiplier = pitch_factor*(dtime/airutils.ideal_step)
|
||||
if dir == -1 then
|
||||
--minetest.chat_send_all("cabrando")
|
||||
self._elevator_angle = math.max(self._elevator_angle-multiplier,-self._elevator_limit)
|
||||
elseif dir == 1 then
|
||||
--minetest.chat_send_all("picando")
|
||||
self._elevator_angle = math.min(self._elevator_angle+multiplier,self._elevator_limit)
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.set_yaw_by_mouse(self, dir)
|
||||
local rotation = self.object:get_rotation()
|
||||
local rot_y = math.deg(rotation.y)
|
||||
|
||||
local total = math.abs(math.floor(rot_y/360))
|
||||
|
||||
if rot_y < 0 then rot_y = rot_y + (360*total) end
|
||||
if rot_y > 360 then rot_y = rot_y - (360*total) end
|
||||
if rot_y >= 270 and dir <= 90 then dir = dir + 360 end
|
||||
if rot_y <= 90 and dir >= 270 then dir = dir - 360 end
|
||||
|
||||
local intensity = self._yaw_intensity / 10
|
||||
local command = (rot_y - dir) * intensity
|
||||
if command < -90 then command = -90
|
||||
elseif command > 90 then command = 90 end
|
||||
--minetest.chat_send_all("rotation y: "..rot_y.." - dir: "..dir.." - command: "..command)
|
||||
|
||||
self._rudder_angle = (-command * self._rudder_limit)/90
|
||||
end
|
||||
|
||||
function airutils.set_yaw(self, dir, dtime)
|
||||
local yaw_factor = self._yaw_intensity or 25
|
||||
if dir == 1 then
|
||||
self._rudder_angle = math.max(self._rudder_angle-(yaw_factor*dtime),-self._rudder_limit)
|
||||
elseif dir == -1 then
|
||||
self._rudder_angle = math.min(self._rudder_angle+(yaw_factor*dtime),self._rudder_limit)
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.rudder_auto_correction(self, longit_speed, dtime)
|
||||
local factor = 1
|
||||
if self._rudder_angle > 0 then factor = -1 end
|
||||
local correction = (self._rudder_limit*(longit_speed/1000)) * factor * (dtime/airutils.ideal_step)
|
||||
local before_correction = self._rudder_angle
|
||||
local new_rudder_angle = self._rudder_angle + correction
|
||||
if math.sign(before_correction) ~= math.sign(new_rudder_angle) then
|
||||
self._rudder_angle = 0
|
||||
else
|
||||
self._rudder_angle = new_rudder_angle
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.autopilot(self, dtime, hull_direction, longit_speed, accel, curr_pos)
|
||||
|
||||
local retval_accel = accel
|
||||
|
||||
if not self._have_auto_pilot then return end
|
||||
|
||||
local min_attack_angle = self._wing_angle_of_attack or 1.0
|
||||
local flap = self._wing_angle_extra_flaps or 2
|
||||
local max_attack_angle = min_attack_angle + flap --1.8
|
||||
|
||||
--climb
|
||||
local velocity = self.object:get_velocity()
|
||||
local climb_rate = velocity.y * 1.5
|
||||
if climb_rate > 5 then climb_rate = 5 end
|
||||
if climb_rate < -5 then
|
||||
climb_rate = -5
|
||||
end
|
||||
|
||||
self._acceleration = 0
|
||||
local climb_rate_min = 0.2
|
||||
local factor = math.abs(climb_rate * 0.1)
|
||||
if self._engine_running then
|
||||
--engine acceleration calc
|
||||
local engineacc = (self._power_lever * self._max_engine_acc) / 100;
|
||||
--self.engine:set_animation_frame_speed(60 + self._power_lever)
|
||||
|
||||
--increase power lever
|
||||
if climb_rate > climb_rate_min then
|
||||
airutils.powerAdjust(self, dtime, factor, -1)
|
||||
end
|
||||
--decrease power lever
|
||||
if climb_rate < 0 then
|
||||
airutils.powerAdjust(self, dtime, factor, 1)
|
||||
end
|
||||
--do not exceed
|
||||
local max_speed = self._max_speed
|
||||
if longit_speed > max_speed then
|
||||
engineacc = 0
|
||||
if engineacc < 0 then engineacc = 0 end
|
||||
end
|
||||
self._acceleration = engineacc
|
||||
end
|
||||
|
||||
local hull_acc = vector.multiply(hull_direction,self._acceleration)
|
||||
retval_accel=vector.add(retval_accel,hull_acc)
|
||||
|
||||
--decrease power lever
|
||||
if climb_rate < 0 then
|
||||
airutils.set_autopilot_pitch(self, -1, dtime)
|
||||
--core.chat_send_all("cabrando: "..dump(climb_rate))
|
||||
elseif climb_rate > climb_rate_min then
|
||||
airutils.set_autopilot_pitch(self, 1, dtime)
|
||||
--core.chat_send_all("picando: "..dump(climb_rate))
|
||||
end
|
||||
|
||||
--pitch
|
||||
--[[if self._angle_of_attack > max_attack_angle then
|
||||
airutils.set_autopilot_pitch(self, -1, dtime)
|
||||
elseif self._angle_of_attack < min_attack_angle then
|
||||
airutils.set_autopilot_pitch(self, 1, dtime)
|
||||
end]]--
|
||||
|
||||
-- yaw
|
||||
airutils.set_yaw(self, 0, dtime)
|
||||
|
||||
if longit_speed > (self._min_speed or 0) then
|
||||
airutils.rudder_auto_correction(self, longit_speed, dtime)
|
||||
if airutils.elevator_auto_correction then
|
||||
--self._elevator_angle = airutils.elevator_auto_correction(self, longit_speed, self.dtime, self._max_speed, self._elevator_angle, self._elevator_limit, airutils.ideal_step, 500)
|
||||
end
|
||||
end
|
||||
|
||||
return retval_accel
|
||||
end
|
114
mods/airutils/lib_planes/custom_physics.lua
Normal file
|
@ -0,0 +1,114 @@
|
|||
function airutils.physics(self)
|
||||
local friction = self._ground_friction or 0.99
|
||||
local vel=self.object:get_velocity()
|
||||
local new_velocity = vector.new()
|
||||
|
||||
--buoyancy
|
||||
local surface = nil
|
||||
local surfnodename = nil
|
||||
local spos = airutils.get_stand_pos(self)
|
||||
if not spos then return end
|
||||
spos.y = spos.y+0.01
|
||||
-- get surface height
|
||||
local snodepos = airutils.get_node_pos(spos)
|
||||
local surfnode = airutils.nodeatpos(spos)
|
||||
while surfnode and (surfnode.drawtype == 'liquid' or surfnode.drawtype == 'flowingliquid') do
|
||||
surfnodename = surfnode.name
|
||||
surface = snodepos.y +0.5
|
||||
if surface > spos.y+self.height then break end
|
||||
snodepos.y = snodepos.y+1
|
||||
surfnode = airutils.nodeatpos(snodepos)
|
||||
end
|
||||
|
||||
self.isinliquid = surfnodename
|
||||
if surface then -- standing in liquid
|
||||
self.isinliquid = true
|
||||
end
|
||||
local last_accel = vector.new()
|
||||
if self._last_accel then
|
||||
last_accel = vector.new(self._last_accel)
|
||||
end
|
||||
|
||||
if self.isinliquid then
|
||||
self.water_drag = 0.2
|
||||
self.isinliquid = true
|
||||
local height = self.height
|
||||
local submergence = math.min(surface-spos.y,height)/height
|
||||
-- local balance = self.buoyancy*self.height
|
||||
local buoyacc = airutils.gravity*(self.buoyancy-submergence)
|
||||
--local buoyacc = self._baloon_buoyancy*(self.buoyancy-submergence)
|
||||
local accell = {
|
||||
x=-vel.x*self.water_drag,
|
||||
y=buoyacc-(vel.y*math.abs(vel.y)*0.4),
|
||||
z=-vel.z*self.water_drag
|
||||
}
|
||||
if self.buoyancy >= 1 then self._engine_running = false end
|
||||
if last_accel then
|
||||
accell = vector.add(accell,last_accel)
|
||||
end
|
||||
new_velocity = vector.multiply(accell,self.dtime)
|
||||
--airutils.set_acceleration(self.object,accell)
|
||||
--self.object:move_to(self.object:get_pos())
|
||||
else
|
||||
--airutils.set_acceleration(self.object,{x=0,y=airutils.gravity,z=0})
|
||||
self.isinliquid = false
|
||||
|
||||
if last_accel then
|
||||
last_accel.y = last_accel.y + airutils.gravity --gravity here
|
||||
|
||||
new_velocity = vector.multiply(last_accel,self.dtime)
|
||||
end
|
||||
--self.object:set_acceleration({x=0,y=new_accel.y, z=0})
|
||||
end
|
||||
|
||||
if self.isonground and not self.isinliquid then
|
||||
--dumb friction
|
||||
new_velocity = {x=new_velocity.x*friction,
|
||||
y=new_velocity.y,
|
||||
z=new_velocity.z*friction}
|
||||
|
||||
-- bounciness
|
||||
if self.springiness and self.springiness > 0 and self.buoyancy >= 1 then
|
||||
local vnew = vector.new(new_velocity)
|
||||
|
||||
if not self.collided then -- ugly workaround for inconsistent collisions
|
||||
for _,k in ipairs({'y','z','x'}) do
|
||||
if new_velocity[k]==0 and math.abs(self.lastvelocity[k])> 0.1 then
|
||||
vnew[k]=-self.lastvelocity[k]*self.springiness
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not vector.equals(new_velocity,vnew) then
|
||||
self.collided = true
|
||||
else
|
||||
if self.collided then
|
||||
vnew = vector.new(self.lastvelocity)
|
||||
end
|
||||
self.collided = false
|
||||
end
|
||||
new_velocity = vnew
|
||||
end
|
||||
|
||||
--damage if the friction is below .97
|
||||
if self._last_longit_speed then
|
||||
if friction <= 0.97 and self._last_longit_speed > 0 then
|
||||
self.hp_max = self.hp_max - 0.001
|
||||
airutils.setText(self, self._vehicle_name)
|
||||
end --damage the plane if it have hard friction
|
||||
end
|
||||
|
||||
--self.object:set_velocity(new_velocity)
|
||||
--new_velocity = vector.subtract(new_velocity,vel)
|
||||
|
||||
--fix bug with unexpe3cted moving
|
||||
if not self.driver_name and math.abs(vel.x) < 0.2 and math.abs(vel.z) < 0.2 then
|
||||
self.object:set_velocity({x=0,y=airutils.gravity*self.dtime,z=0})
|
||||
if self.wheels then self.wheels:set_animation_frame_speed(0) end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self.object:add_velocity(new_velocity)
|
||||
end
|
||||
|
1033
mods/airutils/lib_planes/entities.lua
Normal file
450
mods/airutils/lib_planes/forms.lua
Normal file
|
@ -0,0 +1,450 @@
|
|||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "global_definitions.lua")
|
||||
local S = airutils.S
|
||||
--------------
|
||||
-- Manual --
|
||||
--------------
|
||||
|
||||
function airutils.getPlaneFromPlayer(player)
|
||||
local seat = player:get_attach()
|
||||
if seat then
|
||||
local plane = seat:get_attach()
|
||||
return plane
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function airutils.pilot_formspec(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj == nil then
|
||||
return
|
||||
end
|
||||
local ent = plane_obj:get_luaentity()
|
||||
|
||||
local flap_is_down = "false"
|
||||
local have_flaps = false
|
||||
if ent._wing_angle_extra_flaps then
|
||||
if ent._wing_angle_extra_flaps > 0 then
|
||||
have_flaps = true
|
||||
end
|
||||
end
|
||||
if have_flaps then
|
||||
if ent._flap then flap_is_down = "true" end
|
||||
end
|
||||
|
||||
local light = "false"
|
||||
if ent._have_landing_lights then
|
||||
if ent._land_light then light = "true" end
|
||||
end
|
||||
|
||||
local autopilot = "false"
|
||||
if ent._have_auto_pilot then
|
||||
if ent._autopilot then autopilot = "true" end
|
||||
end
|
||||
|
||||
local yaw = "false"
|
||||
if ent._yaw_by_mouse then yaw = "true" end
|
||||
|
||||
local eng_status = "false"
|
||||
local eng_status_color = "#ff0000"
|
||||
if ent._engine_running then
|
||||
eng_status = "true"
|
||||
eng_status_color = "#00ff00"
|
||||
end
|
||||
|
||||
local ver_pos = 1.0
|
||||
local basic_form = ""
|
||||
--basic_form = basic_form.."button[1,"..ver_pos..";4,1;turn_on;Start/Stop Engines]"
|
||||
basic_form = basic_form.."checkbox[1,"..ver_pos..";turn_on;"..core.colorize(eng_status_color, S("Start/Stop Engines"))..";"..eng_status.."]"
|
||||
ver_pos = ver_pos + 1.1
|
||||
basic_form = basic_form.."button[1,"..ver_pos..";4,1;hud;" .. S("Show/Hide Gauges") .. "]"
|
||||
ver_pos = ver_pos + 1.1
|
||||
basic_form = basic_form.."button[1,"..ver_pos..";4,1;inventory;" .. S("Show Inventory") .. "]"
|
||||
ver_pos = ver_pos + 1.5
|
||||
|
||||
basic_form = basic_form.."checkbox[1,"..ver_pos..";yaw;" .. S("Yaw by mouse") .. ";"..yaw.."]"
|
||||
ver_pos = ver_pos + 0.5
|
||||
|
||||
basic_form = basic_form.."button[1,"..ver_pos..";4,1;go_out;" .. S("Go Out!") .. "]"
|
||||
|
||||
--form second part
|
||||
local expand_form = false
|
||||
ver_pos = 1.2 --restart in second collumn
|
||||
if have_flaps then
|
||||
basic_form = basic_form.."checkbox[6,"..ver_pos..";flap_is_down;" .. S("Flaps down") .. ";"..flap_is_down.."]"
|
||||
ver_pos = ver_pos + 0.5
|
||||
expand_form = true
|
||||
end
|
||||
|
||||
if ent._have_landing_lights then
|
||||
basic_form = basic_form.."checkbox[6,"..ver_pos..";light;" .. S("Landing Light") .. ";"..light.."]"
|
||||
ver_pos = ver_pos + 0.5
|
||||
expand_form = true
|
||||
end
|
||||
|
||||
if ent._have_auto_pilot then
|
||||
basic_form = basic_form.."checkbox[6,"..ver_pos..";turn_auto_pilot_on;" .. S("Autopilot") .. ";"..autopilot.."]"
|
||||
ver_pos = ver_pos + 0.5
|
||||
expand_form = true
|
||||
end
|
||||
|
||||
if ent._have_copilot and name == ent.driver_name then
|
||||
basic_form = basic_form.."button[6,"..ver_pos..";4,1;copilot_form;" .. S("Co-pilot Manager") .. "]"
|
||||
ver_pos = ver_pos + 1.25
|
||||
expand_form = true
|
||||
end
|
||||
|
||||
if ent._have_adf then
|
||||
basic_form = basic_form.."button[6,"..ver_pos..";4,1;adf_form;" .. S("Adf Manager") .. "]"
|
||||
ver_pos = ver_pos + 1.1
|
||||
expand_form = true
|
||||
end
|
||||
|
||||
if ent._have_manual then
|
||||
basic_form = basic_form.."button[6,5.2;4,1;manual;" .. S("Manual") .. "]"
|
||||
expand_form = true
|
||||
end
|
||||
|
||||
local form_width = 6
|
||||
if expand_form then form_width = 11 end
|
||||
local form = table.concat({
|
||||
"formspec_version[3]",
|
||||
"size["..form_width..",7.2]",
|
||||
}, "")
|
||||
|
||||
minetest.show_formspec(name, "lib_planes:pilot_main", form..basic_form)
|
||||
end
|
||||
|
||||
function airutils.manage_copilot_formspec(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj == nil then
|
||||
return
|
||||
end
|
||||
local ent = plane_obj:get_luaentity()
|
||||
|
||||
local pass_list = ""
|
||||
for k, v in pairs(ent._passengers) do
|
||||
pass_list = pass_list .. v .. ","
|
||||
end
|
||||
|
||||
local basic_form = table.concat({
|
||||
"formspec_version[3]",
|
||||
"size[6,4.5]",
|
||||
}, "")
|
||||
|
||||
basic_form = basic_form.."label[1,1.0;" .. S("Bring a copilot") .. ":]"
|
||||
|
||||
local max_seats = table.getn(ent._seats)
|
||||
if ent._have_copilot and max_seats > 2 then --no need to select if there are only 2 occupants
|
||||
basic_form = basic_form.."dropdown[1,1.5;4,0.6;copilot;"..pass_list..";0;false]"
|
||||
end
|
||||
|
||||
basic_form = basic_form.."button[1,2.5;4,1;pass_control;" .. S("Pass the Control") .. "]"
|
||||
|
||||
minetest.show_formspec(name, "lib_planes:manage_copilot", basic_form)
|
||||
end
|
||||
|
||||
function airutils.adf_formspec(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj == nil then
|
||||
return
|
||||
end
|
||||
local ent = plane_obj:get_luaentity()
|
||||
|
||||
local adf = "false"
|
||||
if ent._adf then adf = "true" end
|
||||
local x = 0
|
||||
local z = 0
|
||||
if ent._adf_destiny then
|
||||
if ent._adf_destiny.x then
|
||||
if type(ent._adf_destiny.x) ~= nil then
|
||||
x = math.floor(ent._adf_destiny.x)
|
||||
end
|
||||
end
|
||||
if ent._adf_destiny.z then
|
||||
if type(ent._adf_destiny.z) ~= nil then
|
||||
z = math.floor(ent._adf_destiny.z)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local basic_form = table.concat({
|
||||
"formspec_version[3]",
|
||||
"size[6,3.5]",
|
||||
}, "")
|
||||
|
||||
basic_form = basic_form.."checkbox[1.0,1.0;adf;" .. S("Auto Direction Find") .. ";"..adf.."]"
|
||||
basic_form = basic_form.."field[1.0,1.7;1.5,0.6;adf_x;pos x;"..x.."]"
|
||||
basic_form = basic_form.."field[2.8,1.7;1.5,0.6;adf_z;pos z;"..z.."]"
|
||||
basic_form = basic_form.."button[4.5,1.7;0.6,0.6;save_adf;" .. S("OK") .. "]"
|
||||
|
||||
minetest.show_formspec(name, "lib_planes:adf_main", basic_form)
|
||||
end
|
||||
|
||||
function airutils.pax_formspec(name)
|
||||
local basic_form = table.concat({
|
||||
"formspec_version[3]",
|
||||
"size[6,5]",
|
||||
}, "")
|
||||
|
||||
basic_form = basic_form.."button[1,1.0;4,1;new_seat;" .. S("Change Seat") .. "]"
|
||||
basic_form = basic_form.."button[1,2.5;4,1;go_out;" .. S("Go Offboard") .. "]"
|
||||
|
||||
minetest.show_formspec(name, "lib_planes:passenger_main", basic_form)
|
||||
end
|
||||
|
||||
function airutils.go_out_confirmation_formspec(name)
|
||||
local basic_form = table.concat({
|
||||
"formspec_version[3]",
|
||||
"size[7,2.2]",
|
||||
}, "")
|
||||
|
||||
basic_form = basic_form.."label[0.5,0.5;" .. S("Do you really want to go offboard now?") .. "]"
|
||||
basic_form = basic_form.."button[1.3,1.0;2,0.8;no;" .. S("No") .. "]"
|
||||
basic_form = basic_form.."button[3.6,1.0;2,0.8;yes;" .. S("Yes") .. "]"
|
||||
|
||||
minetest.show_formspec(name, "lib_planes:go_out_confirmation_form", basic_form)
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname == "lib_planes:go_out_confirmation_form" then
|
||||
local name = player:get_player_name()
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj == nil then
|
||||
minetest.close_formspec(name, "lib_planes:go_out_confirmation_form")
|
||||
return
|
||||
end
|
||||
local ent = plane_obj:get_luaentity()
|
||||
if ent then
|
||||
if fields.yes then
|
||||
airutils.dettach_pax(ent, player, true)
|
||||
end
|
||||
end
|
||||
minetest.close_formspec(name, "lib_planes:go_out_confirmation_form")
|
||||
end
|
||||
if formname == "lib_planes:adf_main" then
|
||||
local name = player:get_player_name()
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj == nil then
|
||||
minetest.chat_send_player(name, core.colorize('#ff0000', S(" >>> There is something wrong with the plane...")))
|
||||
minetest.close_formspec(name, "lib_planes:adf_main")
|
||||
return
|
||||
end
|
||||
local ent = plane_obj:get_luaentity()
|
||||
if ent then
|
||||
if fields.adf then
|
||||
if ent._adf == true then
|
||||
ent._adf = false
|
||||
minetest.chat_send_player(name, core.colorize('#0000ff', S(" >>> ADF deactivated.")))
|
||||
else
|
||||
ent._adf = true
|
||||
minetest.chat_send_player(name, core.colorize('#00ff00', S(" >>> ADF activated.")))
|
||||
end
|
||||
end
|
||||
if fields.save_adf then
|
||||
if not ent._adf_destiny then ent._adf_destiny = {x=0,z=0} end
|
||||
if ent._adf_destiny then
|
||||
if fields.adf_x and fields.adf_z then
|
||||
if tonumber(fields.adf_x, 10) ~= nil and tonumber(fields.adf_z, 10) ~= nil then
|
||||
ent._adf_destiny.x = tonumber(fields.adf_x, 10)
|
||||
ent._adf_destiny.z = tonumber(fields.adf_z, 10)
|
||||
minetest.chat_send_player(name, core.colorize('#00ff00', S(" >>> Destination written successfully.")))
|
||||
else
|
||||
minetest.chat_send_player(name, core.colorize('#ff0000', S(" >>> There is something wrong with the ADF fields values.")))
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name, core.colorize('#ff0000', S(" >>> Both ADF fields must be given to complete the operation.")))
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name, core.colorize('#ff0000', S(" >>> There is something wrong on ADF saving...")))
|
||||
end
|
||||
minetest.close_formspec(name, "lib_planes:adf_main")
|
||||
end
|
||||
if formname == "lib_planes:passenger_main" then
|
||||
local name = player:get_player_name()
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj == nil then
|
||||
minetest.close_formspec(name, "lib_planes:passenger_main")
|
||||
return
|
||||
end
|
||||
local ent = plane_obj:get_luaentity()
|
||||
if ent then
|
||||
if fields.new_seat then
|
||||
airutils.dettach_pax(ent, player)
|
||||
airutils.attach_pax(ent, player)
|
||||
end
|
||||
if fields.go_out then
|
||||
local touching_ground, _ = airutils.check_node_below(plane_obj, 2.5)
|
||||
if ent.isinliquid or touching_ground then --isn't flying?
|
||||
airutils.dettach_pax(ent, player)
|
||||
else
|
||||
airutils.go_out_confirmation_formspec(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
minetest.close_formspec(name, "lib_planes:passenger_main")
|
||||
end
|
||||
if formname == "lib_planes:pilot_main" then
|
||||
local name = player:get_player_name()
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj then
|
||||
local ent = plane_obj:get_luaentity()
|
||||
if fields.turn_on then
|
||||
airutils.start_engine(ent)
|
||||
end
|
||||
if fields.hud then
|
||||
if ent._show_hud == true then
|
||||
ent._show_hud = false
|
||||
else
|
||||
ent._show_hud = true
|
||||
end
|
||||
end
|
||||
if fields.go_out then
|
||||
local touch_point = ent.initial_properties.collisionbox[2]-1.0
|
||||
-----////
|
||||
local pos = plane_obj:get_pos()
|
||||
pos.y = pos.y + touch_point
|
||||
local node_below = minetest.get_node(pos).name
|
||||
local nodedef = minetest.registered_nodes[node_below]
|
||||
local is_on_ground = not nodedef or nodedef.walkable or false -- unknown nodes are solid
|
||||
|
||||
if ent.driver_name == name and ent.owner == ent.driver_name then --just the owner can do this
|
||||
--minetest.chat_send_all(dump(noded))
|
||||
if is_on_ground then --or clicker:get_player_control().sneak then
|
||||
--minetest.chat_send_all(dump("is on ground"))
|
||||
--remove the passengers first
|
||||
local max_seats = table.getn(ent._seats)
|
||||
for i = max_seats,1,-1
|
||||
do
|
||||
--minetest.chat_send_all("index: "..i.." - "..dump(ent._passengers[i]))
|
||||
if ent._passengers[i] then
|
||||
local passenger = minetest.get_player_by_name(ent._passengers[i])
|
||||
if passenger then airutils.dettach_pax(ent, passenger) end
|
||||
end
|
||||
end
|
||||
ent._instruction_mode = false
|
||||
else
|
||||
-- not on ground
|
||||
if ent.co_pilot then
|
||||
--give the control to the pax
|
||||
ent._autopilot = false
|
||||
airutils.transfer_control(ent, true)
|
||||
ent._command_is_given = true
|
||||
ent._instruction_mode = true
|
||||
end
|
||||
end
|
||||
end
|
||||
airutils.dettach_pax(ent, player)
|
||||
end
|
||||
if fields.inventory then
|
||||
if ent._trunk_slots then
|
||||
airutils.show_vehicle_trunk_formspec(ent, player, ent._trunk_slots)
|
||||
end
|
||||
end
|
||||
if fields.flap_is_down then
|
||||
if fields.flap_is_down == "true" then
|
||||
ent._flap = true
|
||||
else
|
||||
ent._flap = false
|
||||
end
|
||||
minetest.sound_play("airutils_collision", {
|
||||
object = ent.object,
|
||||
max_hear_distance = 15,
|
||||
gain = 1.0,
|
||||
fade = 0.0,
|
||||
pitch = 0.5,
|
||||
}, true)
|
||||
end
|
||||
if fields.light then
|
||||
if ent._land_light == true then
|
||||
ent._land_light = false
|
||||
else
|
||||
ent._land_light = true
|
||||
end
|
||||
end
|
||||
if fields.yaw then
|
||||
if ent._yaw_by_mouse == true then
|
||||
ent._yaw_by_mouse = false
|
||||
else
|
||||
ent._yaw_by_mouse = true
|
||||
end
|
||||
end
|
||||
if fields.copilot_form then
|
||||
airutils.manage_copilot_formspec(name)
|
||||
end
|
||||
if fields.adf_form then
|
||||
airutils.adf_formspec(name)
|
||||
end
|
||||
if fields.turn_auto_pilot_on then
|
||||
if ent._autopilot == true then
|
||||
ent._autopilot = false
|
||||
core.chat_send_player(ent.driver_name,S(" >>> Autopilot deactivated"))
|
||||
else
|
||||
ent._autopilot = true
|
||||
core.chat_send_player(ent.driver_name,core.colorize('#00ff00', S(" >>> Autopilot activated")))
|
||||
end
|
||||
end
|
||||
if fields.manual then
|
||||
if ent._have_manual then
|
||||
ent._have_manual(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
minetest.close_formspec(name, "lib_planes:pilot_main")
|
||||
end
|
||||
if formname == "lib_planes:manage_copilot" then
|
||||
local name = player:get_player_name()
|
||||
local plane_obj = airutils.getPlaneFromPlayer(player)
|
||||
if plane_obj == nil then
|
||||
minetest.close_formspec(name, "lib_planes:manage_copilot")
|
||||
return
|
||||
end
|
||||
local ent = plane_obj:get_luaentity()
|
||||
|
||||
if fields.copilot then
|
||||
--look for a free seat first
|
||||
local is_there_a_free_seat = false
|
||||
for i = 2,1,-1
|
||||
do
|
||||
if ent._passengers[i] == nil then
|
||||
is_there_a_free_seat = true
|
||||
break
|
||||
end
|
||||
end
|
||||
--then move the current copilot to a free seat
|
||||
if ent.co_pilot and is_there_a_free_seat then
|
||||
local copilot_player_obj = minetest.get_player_by_name(ent.co_pilot)
|
||||
if copilot_player_obj then
|
||||
airutils.dettach_pax(ent, copilot_player_obj)
|
||||
airutils.attach_pax(ent, copilot_player_obj)
|
||||
else
|
||||
ent.co_pilot = nil
|
||||
end
|
||||
end
|
||||
--so bring the new copilot
|
||||
if ent.co_pilot == nil then
|
||||
local new_copilot_player_obj = minetest.get_player_by_name(fields.copilot)
|
||||
if new_copilot_player_obj then
|
||||
airutils.dettach_pax(ent, new_copilot_player_obj)
|
||||
airutils.attach_pax(ent, new_copilot_player_obj, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
if fields.pass_control then
|
||||
if ent._command_is_given == true then
|
||||
--take the control
|
||||
airutils.transfer_control(ent, false)
|
||||
else
|
||||
--trasnfer the control to student
|
||||
airutils.transfer_control(ent, true)
|
||||
end
|
||||
end
|
||||
minetest.close_formspec(name, "lib_planes:manage_copilot")
|
||||
end
|
||||
|
||||
|
||||
end)
|
70
mods/airutils/lib_planes/fuel_management.lua
Normal file
|
@ -0,0 +1,70 @@
|
|||
function airutils.contains(table, val)
|
||||
for k,v in pairs(table) do
|
||||
if k == val then
|
||||
return v
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function airutils.loadFuel(self, player_name)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
local inv = player:get_inventory()
|
||||
local itmstck=player:get_wielded_item()
|
||||
|
||||
local item_name = ""
|
||||
if itmstck then item_name = itmstck:get_name() end
|
||||
|
||||
local fuel = airutils.contains(airutils.fuel, item_name)
|
||||
if fuel then
|
||||
--local stack = ItemStack(item_name .. " 1")
|
||||
|
||||
if self._energy < self._max_fuel then
|
||||
itmstck:set_count(1)
|
||||
inv:remove_item("main", itmstck)
|
||||
self._energy = self._energy + fuel
|
||||
if self._energy > self._max_fuel then self._energy = self._max_fuel end
|
||||
|
||||
--local energy_indicator_angle = airutils.get_gauge_angle(self._energy)
|
||||
--self.fuel_gauge:set_attach(self.object,'',self._gauge_fuel_position,{x=0,y=0,z=energy_indicator_angle})
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function airutils.consumptionCalc(self, accel)
|
||||
if accel == nil then return end
|
||||
if self._energy > 0 and self._engine_running and accel ~= nil then
|
||||
local divisor = 700000
|
||||
if self._fuel_consumption_divisor then divisor = self._fuel_consumption_divisor end
|
||||
local consumed_power = 0
|
||||
local parent_obj = self.object:get_attach()
|
||||
if not parent_obj then
|
||||
if self._rotor_speed then
|
||||
--is an helicopter
|
||||
consumed_power = 50/divisor --fixed rpm
|
||||
else
|
||||
--is a normal plane
|
||||
consumed_power = self._power_lever/divisor
|
||||
end
|
||||
end
|
||||
--minetest.chat_send_all('consumed: '.. consumed_power)
|
||||
self._energy = self._energy - consumed_power;
|
||||
|
||||
local energy_indicator_angle = airutils.get_gauge_angle(self._energy)
|
||||
if self.fuel_gauge then
|
||||
if self.fuel_gauge:get_luaentity() then
|
||||
self.fuel_gauge:set_attach(self.object,'',self._gauge_fuel_position,{x=0,y=0,z=energy_indicator_angle})
|
||||
end
|
||||
end
|
||||
end
|
||||
if self._energy <= 0 and self._engine_running and accel ~= nil then
|
||||
self._engine_running = false
|
||||
self._autopilot = false
|
||||
if self.sound_handle then minetest.sound_stop(self.sound_handle) end
|
||||
self.object:set_animation_frame_speed(0)
|
||||
end
|
||||
end
|
134
mods/airutils/lib_planes/gauges.lua
Normal file
|
@ -0,0 +1,134 @@
|
|||
--[[
|
||||
local function get_pointer(pointer_angle, gauge_center_x, gauge_center_y, full_pointer)
|
||||
full_pointer = full_pointer or 1
|
||||
local retval = ""
|
||||
local ind_pixel = "airutils_ind_box_2.png"
|
||||
|
||||
local pointer_img_size = 8
|
||||
local pointer_rad = math.rad(pointer_angle)
|
||||
local dim = 2*(pointer_img_size/2)
|
||||
local pos_x = math.sin(pointer_rad) * dim
|
||||
local pos_y = math.cos(pointer_rad) * dim
|
||||
retval = retval..(gauge_center_x+pos_x)..","..(gauge_center_y+pos_y).."="..ind_pixel..":"
|
||||
|
||||
dim = 4*(pointer_img_size/2)
|
||||
pos_x = math.sin(pointer_rad) * dim
|
||||
pos_y = math.cos(pointer_rad) * dim
|
||||
retval = retval..(gauge_center_x+pos_x)..","..(gauge_center_y+pos_y).."="..ind_pixel..":"
|
||||
|
||||
dim = 6*(pointer_img_size/2)
|
||||
pos_x = math.sin(pointer_rad) * dim
|
||||
pos_y = math.cos(pointer_rad) * dim
|
||||
retval = retval..(gauge_center_x+pos_x)..","..(gauge_center_y+pos_y).."="..ind_pixel..":"
|
||||
|
||||
if full_pointer == 1 then
|
||||
dim = 8*(pointer_img_size/2)
|
||||
pos_x = math.sin(pointer_rad) * dim
|
||||
pos_y = math.cos(pointer_rad) * dim
|
||||
retval = retval..(gauge_center_x+pos_x)..","..(gauge_center_y+pos_y).."="..ind_pixel..":"
|
||||
|
||||
dim = 10*(pointer_img_size/2)
|
||||
pos_x = math.sin(pointer_rad) * dim
|
||||
pos_y = math.cos(pointer_rad) * dim
|
||||
retval = retval..(gauge_center_x+pos_x)..","..(gauge_center_y+pos_y).."="..ind_pixel..":"
|
||||
end
|
||||
return retval
|
||||
end
|
||||
]]--
|
||||
|
||||
function airutils.plot_altimeter_gauge(self, scale, place_x, place_y)
|
||||
local bg_width_height = 100
|
||||
local pointer_img = 8
|
||||
local gauge_center = (bg_width_height / 2) - (pointer_img/2)
|
||||
local gauge_center_x = place_x + gauge_center
|
||||
local gauge_center_y = place_y + gauge_center
|
||||
|
||||
|
||||
--altimeter
|
||||
--[[local altitude = (height / 0.32) / 100
|
||||
local hour, minutes = math.modf( altitude )
|
||||
hour = math.fmod (hour, 10)
|
||||
minutes = minutes * 100
|
||||
minutes = (minutes * 100) / 100
|
||||
local minute_angle = (minutes*-360)/100
|
||||
local hour_angle = (hour*-360)/10 + ((minute_angle*36)/360)]]--
|
||||
|
||||
--[[
|
||||
#### `[combine:<w>x<h>:<x1>,<y1>=<file1>:<x2>,<y2>=<file2>:...`
|
||||
|
||||
* `<w>`: width
|
||||
* `<h>`: height
|
||||
* `<x>`: x position
|
||||
* `<y>`: y position
|
||||
* `<file>`: texture to combine
|
||||
|
||||
Creates a texture of size `<w>` times `<h>` and blits the listed files to their
|
||||
specified coordinates.
|
||||
|
||||
]]--
|
||||
|
||||
local altimeter = "^[resize:"..scale.."x"..scale.."^[combine:"..bg_width_height.."x"..bg_width_height..":"
|
||||
..place_x..","..place_y.."=airutils_altimeter_gauge.png:"
|
||||
|
||||
--altimeter = altimeter..get_pointer(minute_angle+180, gauge_center_x, gauge_center_y, 1)
|
||||
--altimeter = altimeter..get_pointer(hour_angle+180, gauge_center_x, gauge_center_y, 0)
|
||||
|
||||
return altimeter
|
||||
end
|
||||
|
||||
function airutils.plot_fuel_gauge(self, scale, place_x, place_y)
|
||||
local bg_width_height = 100
|
||||
local pointer_img = 8
|
||||
local gauge_center = (bg_width_height / 2) - (pointer_img/2)
|
||||
local gauge_center_x = place_x + gauge_center
|
||||
local gauge_center_y = place_y + gauge_center
|
||||
|
||||
--local fuel_percentage = (curr_level*100)/max_level
|
||||
--local fuel_angle = -(fuel_percentage*180)/100
|
||||
--minetest.chat_send_all(dump(fuel_angle))
|
||||
|
||||
local fuel = "^[resize:"..scale.."x"..scale.."^[combine:"..bg_width_height.."x"..bg_width_height..":"
|
||||
..place_x..","..place_y.."=airutils_fuel_gauge.png:"
|
||||
|
||||
--fuel = fuel..get_pointer(fuel_angle-90, gauge_center_x, gauge_center_y, 1)
|
||||
|
||||
return fuel
|
||||
end
|
||||
|
||||
function airutils.plot_speed_gauge(self, scale, place_x, place_y)
|
||||
local bg_width_height = 100
|
||||
local pointer_img = 8
|
||||
local gauge_center = (bg_width_height / 2) - (pointer_img/2)
|
||||
local gauge_center_x = place_x + gauge_center
|
||||
local gauge_center_y = place_y + gauge_center
|
||||
|
||||
--local speed_percentage = (curr_level*100)/max_level
|
||||
--local speed_angle = -(speed_percentage*350)/100
|
||||
--minetest.chat_send_all(dump(fuel_angle))
|
||||
|
||||
local speed = "^[resize:"..scale.."x"..scale.."^[combine:"..bg_width_height.."x"..bg_width_height..":"
|
||||
..place_x..","..place_y.."=airutils_speed_gauge.png:"
|
||||
|
||||
--fuel = fuel..get_pointer(speed_angle-180, gauge_center_x, gauge_center_y, 1)
|
||||
|
||||
return speed
|
||||
end
|
||||
|
||||
function airutils.plot_power_gauge(self, scale, place_x, place_y)
|
||||
local bg_width_height = 100
|
||||
local pointer_img = 8
|
||||
local gauge_center = (bg_width_height / 2) - (pointer_img/2)
|
||||
local gauge_center_x = place_x + gauge_center
|
||||
local gauge_center_y = place_y + gauge_center
|
||||
|
||||
--local speed_percentage = (curr_level*100)/max_level
|
||||
--local speed_angle = -(speed_percentage*350)/100
|
||||
--minetest.chat_send_all(dump(fuel_angle))
|
||||
|
||||
local rpm = "^[resize:"..scale.."x"..scale.."^[combine:"..bg_width_height.."x"..bg_width_height..":"
|
||||
..place_x..","..place_y.."=airutils_rpm_gauge.png:"
|
||||
|
||||
--fuel = fuel..get_pointer(speed_angle-180, gauge_center_x, gauge_center_y, 1)
|
||||
|
||||
return rpm
|
||||
end
|
8
mods/airutils/lib_planes/global_definitions.lua
Normal file
|
@ -0,0 +1,8 @@
|
|||
--
|
||||
-- constants
|
||||
--
|
||||
airutils.vector_up = vector.new(0, 1, 0)
|
||||
|
||||
--set min y-pos above which airplanes are seen on radar
|
||||
airutils.radarMinHeight = 30
|
||||
|
328
mods/airutils/lib_planes/hud.lua
Normal file
|
@ -0,0 +1,328 @@
|
|||
airutils.hud_list = {}
|
||||
local S = airutils.S
|
||||
|
||||
function airutils.animate_gauge(player, ids, prefix, x, y, angle)
|
||||
local angle_in_rad = math.rad(angle + 180)
|
||||
local dim = 10
|
||||
local pos_x = math.sin(angle_in_rad) * dim
|
||||
local pos_y = math.cos(angle_in_rad) * dim
|
||||
player:hud_change(ids[prefix .. "2"], "offset", {x = pos_x + x, y = pos_y + y})
|
||||
dim = 20
|
||||
pos_x = math.sin(angle_in_rad) * dim
|
||||
pos_y = math.cos(angle_in_rad) * dim
|
||||
player:hud_change(ids[prefix .. "3"], "offset", {x = pos_x + x, y = pos_y + y})
|
||||
dim = 30
|
||||
pos_x = math.sin(angle_in_rad) * dim
|
||||
pos_y = math.cos(angle_in_rad) * dim
|
||||
player:hud_change(ids[prefix .. "4"], "offset", {x = pos_x + x, y = pos_y + y})
|
||||
dim = 40
|
||||
pos_x = math.sin(angle_in_rad) * dim
|
||||
pos_y = math.cos(angle_in_rad) * dim
|
||||
player:hud_change(ids[prefix .. "5"], "offset", {x = pos_x + x, y = pos_y + y})
|
||||
dim = 50
|
||||
pos_x = math.sin(angle_in_rad) * dim
|
||||
pos_y = math.cos(angle_in_rad) * dim
|
||||
player:hud_change(ids[prefix .. "6"], "offset", {x = pos_x + x, y = pos_y + y})
|
||||
dim = 60
|
||||
pos_x = math.sin(angle_in_rad) * dim
|
||||
pos_y = math.cos(angle_in_rad) * dim
|
||||
player:hud_change(ids[prefix .. "7"], "offset", {x = pos_x + x, y = pos_y + y})
|
||||
end
|
||||
|
||||
function airutils.update_hud(player, climb, speed, power, fuel)
|
||||
local player_name = player:get_player_name()
|
||||
|
||||
local screen_pos_y = -150
|
||||
local screen_pos_x = 10
|
||||
|
||||
local clb_gauge_x = screen_pos_x + 75
|
||||
local clb_gauge_y = screen_pos_y + 1
|
||||
local sp_gauge_x = screen_pos_x + 170
|
||||
local sp_gauge_y = clb_gauge_y
|
||||
|
||||
local pwr_gauge_x = screen_pos_x + 330
|
||||
local pwr_gauge_y = clb_gauge_y
|
||||
|
||||
local fu_gauge_x = screen_pos_x + 340
|
||||
local fu_gauge_y = clb_gauge_y
|
||||
|
||||
local ids = airutils.hud_list[player_name]
|
||||
if ids then
|
||||
airutils.animate_gauge(player, ids, "clb_pt_", clb_gauge_x, clb_gauge_y, climb)
|
||||
airutils.animate_gauge(player, ids, "sp_pt_", sp_gauge_x, sp_gauge_y, speed)
|
||||
airutils.animate_gauge(player, ids, "pwr_pt_", pwr_gauge_x, pwr_gauge_y, power)
|
||||
airutils.animate_gauge(player, ids, "fu_pt_", fu_gauge_x, fu_gauge_y, fuel)
|
||||
else
|
||||
ids = {}
|
||||
|
||||
ids["title"] = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = screen_pos_x +140, y = screen_pos_y -100},
|
||||
text = S("Flight Information"),
|
||||
alignment = 0,
|
||||
scale = { x = 100, y = 30},
|
||||
number = 0xFFFFFF,
|
||||
})
|
||||
|
||||
ids["bg"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = screen_pos_x, y = screen_pos_y},
|
||||
text = "airutils_hud_panel.png",
|
||||
scale = { x = 0.5, y = 0.5},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
ids["clb_pt_1"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = clb_gauge_x, y = clb_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
ids["clb_pt_2"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = clb_gauge_x, y = clb_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["clb_pt_3"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = clb_gauge_x, y = clb_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["clb_pt_4"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = clb_gauge_x, y = clb_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["clb_pt_5"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = clb_gauge_x, y = clb_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["clb_pt_6"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = clb_gauge_x, y = clb_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["clb_pt_7"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = clb_gauge_x, y = clb_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
ids["sp_pt_1"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = sp_gauge_x, y = sp_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["sp_pt_2"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = sp_gauge_x, y = sp_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["sp_pt_3"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = sp_gauge_x, y = sp_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["sp_pt_4"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = sp_gauge_x, y = sp_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["sp_pt_5"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = sp_gauge_x, y = sp_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["sp_pt_6"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = sp_gauge_x, y = sp_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["sp_pt_7"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = sp_gauge_x, y = sp_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
ids["pwr_pt_1"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = pwr_gauge_x, y = pwr_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
ids["pwr_pt_2"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = pwr_gauge_x, y = pwr_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["pwr_pt_3"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = pwr_gauge_x, y = pwr_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["pwr_pt_4"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = pwr_gauge_x, y = pwr_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["pwr_pt_5"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = pwr_gauge_x, y = pwr_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["pwr_pt_6"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = pwr_gauge_x, y = pwr_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["pwr_pt_7"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = pwr_gauge_x, y = pwr_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
ids["fu_pt_1"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = fu_gauge_x, y = fu_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
ids["fu_pt_2"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = fu_gauge_x, y = fu_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["fu_pt_3"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = fu_gauge_x, y = fu_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["fu_pt_4"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = fu_gauge_x, y = fu_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["fu_pt_5"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = fu_gauge_x, y = fu_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["fu_pt_6"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = fu_gauge_x, y = fu_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
ids["fu_pt_7"] = player:hud_add({
|
||||
hud_elem_type = "image",
|
||||
position = {x = 0, y = 1},
|
||||
offset = {x = fu_gauge_x, y = fu_gauge_y},
|
||||
text = "airutils_ind_box.png",
|
||||
scale = { x = 6, y = 6},
|
||||
alignment = { x = 1, y = 0 },
|
||||
})
|
||||
|
||||
airutils.hud_list[player_name] = ids
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function airutils.remove_hud(player)
|
||||
if player then
|
||||
local player_name = player:get_player_name()
|
||||
--minetest.chat_send_all(player_name)
|
||||
local ids = airutils.hud_list[player_name]
|
||||
if ids then
|
||||
--player:hud_remove(ids["altitude"])
|
||||
--player:hud_remove(ids["time"])
|
||||
for key in pairs(ids) do
|
||||
player:hud_remove(ids[key])
|
||||
end
|
||||
end
|
||||
airutils.hud_list[player_name] = nil
|
||||
end
|
||||
|
||||
end
|
19
mods/airutils/lib_planes/init.lua
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "global_definitions.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "control.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "fuel_management.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "custom_physics.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "utilities.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "entities.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "forms.lua")
|
||||
dofile(minetest.get_modpath("airutils") .. DIR_DELIM .. "lib_planes" .. DIR_DELIM .. "gauges.lua")
|
||||
|
||||
--
|
||||
-- helpers and co.
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- items
|
||||
--
|
1406
mods/airutils/lib_planes/utilities.lua
Normal file
83
mods/airutils/light.lua
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
function airutils.get_xz_from_hipotenuse(orig_x, orig_z, yaw, distance)
|
||||
--cara, o minetest é bizarro, ele considera o eixo no sentido ANTI-HORÁRIO... Então pra equação funcionar, subtrair o angulo de 360 antes
|
||||
yaw = math.rad(360) - yaw
|
||||
local z = (math.cos(yaw)*distance) + orig_z
|
||||
local x = (math.sin(yaw)*distance) + orig_x
|
||||
return x, z
|
||||
end
|
||||
|
||||
minetest.register_node("airutils:light", {
|
||||
drawtype = "airlike",
|
||||
--tile_images = {"airutils_light.png"},
|
||||
inventory_image = minetest.inventorycube("airutils_light.png"),
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
is_ground_content = true,
|
||||
light_propagates = true,
|
||||
sunlight_propagates = true,
|
||||
light_source = 14,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
})
|
||||
|
||||
function airutils.remove_light(self)
|
||||
if self._light_old_pos then
|
||||
--force the remotion of the last light
|
||||
minetest.add_node(self._light_old_pos, {name="air"})
|
||||
self._light_old_pos = nil
|
||||
end
|
||||
end
|
||||
|
||||
function airutils.swap_node(self, pos)
|
||||
local target_pos = pos
|
||||
local have_air = false
|
||||
local node = nil
|
||||
local count = 0
|
||||
while have_air == false and count <= 3 do
|
||||
node = minetest.get_node(target_pos)
|
||||
if node.name == "air" then
|
||||
have_air = true
|
||||
break
|
||||
end
|
||||
count = count + 1
|
||||
target_pos.y = target_pos.y + 1
|
||||
end
|
||||
|
||||
if have_air then
|
||||
minetest.set_node(target_pos, {name='airutils:light'})
|
||||
airutils.remove_light(self)
|
||||
self._light_old_pos = target_pos
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function airutils.put_light(self)
|
||||
local pos = self.object:get_pos()
|
||||
pos.y = pos.y + 1
|
||||
local yaw = self.object:get_yaw()
|
||||
local lx, lz = airutils.get_xz_from_hipotenuse(pos.x, pos.z, yaw, 10)
|
||||
local light_pos = {x=lx, y=pos.y, z=lz}
|
||||
|
||||
local cast = minetest.raycast(pos, light_pos, false, false)
|
||||
local thing = cast:next()
|
||||
local was_set = false
|
||||
while thing do
|
||||
if thing.type == "node" then
|
||||
local ipos = thing.intersection_point
|
||||
if ipos then
|
||||
was_set = airutils.swap_node(self, ipos)
|
||||
end
|
||||
end
|
||||
thing = cast:next()
|
||||
end
|
||||
if was_set == false then
|
||||
local n = minetest.get_node_or_nil(light_pos)
|
||||
if n and n.name == 'air' then
|
||||
airutils.swap_node(self, light_pos)
|
||||
end
|
||||
end
|
||||
end
|
85
mods/airutils/locale/airutils.de.tr
Normal file
|
@ -0,0 +1,85 @@
|
|||
# textdomain: airutils
|
||||
Bio Fuel=Biotreibstoff
|
||||
Biofuel Distiller=Biotreibstoff-Brenner
|
||||
Fuel Distiller=Treibstoff-Destilliergerät
|
||||
Fuel Distiller (FULL)=Treibstoff-Destilliergerät (VOLL)
|
||||
Fuel Distiller @1% done=Treibstoff-Destilliergerät @1% fertig
|
||||
PAPI=PAPI
|
||||
left side=linke Seite
|
||||
right side=rechte Seite
|
||||
right_side=rechte_seite
|
||||
Owned by: @1=Gehört: @1
|
||||
Repair Tool=Reparaturwerkzeug
|
||||
Tug tool for airport=Schleppwerkzeug für den Flughafen
|
||||
@1 is protected by @2.=@1 ist geschützt von @2.
|
||||
@1 is protected.=@1 ist geschützt.
|
||||
Wind Indicator=Windanzeiger
|
||||
>>> The wind direction now is @1= >>> Die Windrichtung ist nun @1
|
||||
Wind Direction Indicator=Windrichtungsanzeiger
|
||||
Node is protected=Block ist geschützt
|
||||
Current hp: = Aktuelle Lp:
|
||||
Nice @1 of @2.@3= Schöne(r/s) @1 von @2.@3
|
||||
>>> The captain got the control.= >>> Der Kaptain übernimmt die Kontrolle.
|
||||
>>> The control is with you now.= >>> Du hast nun die Kontrolle.
|
||||
>>> The control was given.= >>> Die Kontrolle wurde erteilt.
|
||||
Enable/disable explosion blast damage=Explosionsschaden aktivieren/deaktivieren
|
||||
>>> Blast damage by explosion is disabled=Explosionsschaden ist deaktiviert.
|
||||
>>> Blast damage by explosion is enabled=Explosionsschaden ist aktiviert.
|
||||
Transfer the property of a plane to another player=Überträgt die Eigentümerschaft des Fluggerätes an einen anderen Spieler.
|
||||
>>> This plane now is property of: = >>> Dieses Fluggerät ist nun Eigentum von:
|
||||
>>> only the owner or moderators can transfer this airplane= >>> Nur der Eigentümer oder Moderator kann die Eigentümerschaft ändern.
|
||||
>>> the target player must be logged in= >>> der Zielspieler muß eingeloggt sein.
|
||||
>>> you are not inside a plane to perform the command= >>> du sitzt in keinem Fluggerät um dieses Kommando zu geben
|
||||
Ejects from a plane=Wirft dich aus dem Fluggerät
|
||||
>>> you are not inside a plane= >>> du sitzt in keinem Fluggerät
|
||||
Enables/disables the ground effect (for debug purposes)=Ein/Ausschaltet den Bodeneffekt (zur Fehlersuche)
|
||||
>>> Ground effect was turned on.= >>> Bodeneffekt wurde eingeschalten.
|
||||
>>> Ground effect was turned off.=>>> Bodeneffekt wurde ausgeschalten.
|
||||
>>> You need 'server' priv to run this command.= >>> Du brauchst 'server'-rechte um dieses Kommando auszuführen.
|
||||
Enables/disables the lift printing (for debug purposes)=Ein/Ausschalten des Lift schreibens (zur Fehlersuche)
|
||||
>>> Lift printing turned on.= >>> Lift schreiben eingeschalten.
|
||||
>>> Lift printing turned off.= >>> Lift schreiben ausgeschalten.
|
||||
>>> Mouse control disabled.= >>> Mauslenkung ausgeschalten.
|
||||
>>> Mouse control enabled.= >>> Mauslenkung eingeschalten.
|
||||
>>> Autopilot deactivated= >>> Autopilot ausgeschalten
|
||||
>>> Autopilot on= >>> Autopilot eingeschalten
|
||||
>>> Flaps retracted due for overspeed= >>> Klappen eingefahren wegen Hochgeschwindigkeit
|
||||
You need steel ingots in your inventory to perform this repair.=Du brauchst Eisenbarren in einem Inventar um das zu reparieren.
|
||||
Start/Stop Engines=Starte/Stoppe Maschinen
|
||||
Show/Hide Gauges=Blende Messgeräte ein/aus
|
||||
Show Inventory=Zeige Inventar
|
||||
Yaw by mouse=Lenke mit Maus
|
||||
Go Out!=Steig aus!
|
||||
Flaps down=Klappen unten
|
||||
Landing Light=Landelicht
|
||||
Autopilot=Autopilot
|
||||
Co-pilot Manager=Co-Pilot Manager
|
||||
Adf Manager=Adf Manager
|
||||
Manual=Manuell
|
||||
Bring a copilot=Bring einen Copiloten
|
||||
Pass the Control=Übergebe die Kontrolle
|
||||
Auto Direction Find=Automatischer Richtungsfinder
|
||||
OK=OK
|
||||
Change Seat=Wechlse Sitzplatz
|
||||
Go Offboard=Aussteigen
|
||||
Do you really want to go offboard now?=Du willst jetzt wirklich aussteigen?
|
||||
No=Nein
|
||||
Yes=Ja
|
||||
>>> There is something wrong with the plane...= >>> Da stimmt was nicht mit dem Fluggerät
|
||||
>>> ADF deactivated.= >>> ADF deaktiviert
|
||||
>>> ADF activated.= >>> ADF aktiviert.
|
||||
>>> Destination written successfully.= >>> Ziel erfolgreich eingetragen
|
||||
>>> There is something wrong with the ADF fields values.=Mit den Werten der ADF-Felder ist etwas nicht in Ordnung
|
||||
>>> Both ADF fields must be given to complete the operation.= >>> Beide ADF-Felder müssen angegeben werden, damit der Vorgang abgeschlossen werden kann
|
||||
>>> There is something wrong on ADF saving...= >>> Da stimmt etwas nicht mit dem ADF speichern
|
||||
Flight Information=Fluginformation
|
||||
>>> You need the priv= >>> Du brauchst das Recht
|
||||
to fly this plane.=um das Fluggerät zu fliegen.
|
||||
>>> The engine is damaged, start procedure failed.= >>> Die Maschine ist beschädigt, starten fehlgeschlagen.
|
||||
>>> Flap down=>>> Klappen unten
|
||||
>>> Flap up=>>> Klappen oben
|
||||
>>> You cannot claim this scrap yet, wait some minutes.=Du kannst diesen Schrott noch nicht beanspruchen, warte ein paar Minuten
|
||||
Sorry, but this module doesn't work when SkinsDb and Armor are instaled together.=Entschuldige, aber dieses Modul funktioniert nicht, wenn SkinsDb und Armor zusammen installiert ist.
|
||||
Something isn't working...=Etwas funktioniert nicht...
|
||||
Set Player Texture=Wähle Spielertextur
|
||||
The isn't activated as secure. Aborting=Das ist zur Sicherheit nicht aktiviert. Abbruch
|
85
mods/airutils/locale/airutils.fr.tr
Normal file
|
@ -0,0 +1,85 @@
|
|||
# textdomain: airutils
|
||||
Bio Fuel=Biocarburant
|
||||
Biofuel Distiller=Raffineur de Biocarburant
|
||||
Fuel Distiller=Raffineur de Carburant
|
||||
Fuel Distiller (FULL)=Raffineur de Carburant (PLEIN)
|
||||
Fuel Distiller @1% done=Raffineur de Carburant : @1% traité
|
||||
PAPI=PAPI
|
||||
left side=coté gauche
|
||||
right side=coté droit
|
||||
right_side=coté_droit
|
||||
Owned by: @1=Propriété de @1
|
||||
Repair Tool=Outil de Réparation
|
||||
Tug tool for airport=Remorqueur d'aéroport
|
||||
@1 is protected by @2.=@1 est protégé par @2.
|
||||
@1 is protected.=@1 est protégé.
|
||||
Wind Indicator=Girouette
|
||||
>>> The wind direction now is @1= >>> La direction actuelle du vent est @1
|
||||
Wind Direction Indicator=Manche à Air
|
||||
Node is protected=Nœud protégé
|
||||
Current hp: = Points de vie :
|
||||
Nice @1 of @2.@3=Joli(e) @1 de @2.@3
|
||||
>>> The captain got the control.=>>> Le commandant de bord a repris la main.
|
||||
>>> The control is with you now.=>>> Vous avez la main.
|
||||
>>> The control was given.=>>> Vous avez donné la main.
|
||||
Enable/disable explosion blast damage=Activer/Désactiver les dégats d'explosion
|
||||
>>> Blast damage by explosion is disabled=>>> Les dégats d'explosion sont désactivés
|
||||
>>> Blast damage by explosion is enabled=>>> Les dégats d'explosion sont activés
|
||||
Transfer the property of a plane to another player=Transférer la propriéte d'un avion à un autre joueur
|
||||
>>> This plane now is property of: = >>> Cet avion est désormais la propriété de :
|
||||
>>> only the owner or moderators can transfer this airplane= >>> Seuls son propriétaire ou un modérateur peuvent transférer cet avion
|
||||
>>> the target player must be logged in= >>> Le nouveau propriétaire doit être connecté
|
||||
>>> you are not inside a plane to perform the command= >>> Vous devez être dans un avion pour exécuter cette commande
|
||||
Ejects from a plane=Ejectez-vous de l'avion
|
||||
>>> you are not inside a plane= >>> Vous n'êtes pas à l'intérieur d'un avion
|
||||
Enables/disables the ground effect (for debug purposes)=Activer/Désactiver l'effet de sol (pour déboguer)
|
||||
>>> Ground effect was turned on.= >>> L'effet de sol est activé.
|
||||
>>> Ground effect was turned off.= >>> L'effet de sol est désactivé.
|
||||
>>> You need 'server' priv to run this command.= >>> Vous devez avoir le privilège 'server' pour exécuter cette commande.
|
||||
Enables/disables the lift printing (for debug purposes)=Activer/Désactiver le débogage de sustenstation
|
||||
>>> Lift printing turned on.= >>> Débogage de sustenstation activé.
|
||||
>>> Lift printing turned off.= >>> Débogage de sustenstation desactivé.
|
||||
>>> Mouse control disabled.= >>> Commande à la souris désactivée.
|
||||
>>> Mouse control enabled.= >>> Commande à la souris activée.
|
||||
>>> Autopilot deactivated= >>> Autopilote désactivé
|
||||
>>> Autopilot on= >>> Autopilote activé
|
||||
>>> Flaps retracted due for overspeed= >>> Volets rétractés pour cause de sur-vitesse
|
||||
You need steel ingots in your inventory to perform this repair.=Vous avez besoin de lingots d'acier pour réaliser cette réparation.
|
||||
Start/Stop Engines=Démarrer/Arrêter les moteurs
|
||||
Show/Hide Gauges=Montrer/Cacher les Instruments
|
||||
Show Inventory=Montrer l'inventaire
|
||||
Yaw by mouse=Palonnier à la souris
|
||||
Go Out!=Débarquer !
|
||||
Flaps down=Volets déployés
|
||||
Landing Light=Phare d'atterrissage
|
||||
Autopilot=Autopilote
|
||||
Co-pilot Manager=Gestionnaire de copilote
|
||||
Adf Manager=Gestionnaire ADF
|
||||
Manual=Manuel
|
||||
Bring a copilot=Embarquer un copilote
|
||||
Pass the Control=Donner la main
|
||||
Auto Direction Find=ADF
|
||||
OK=OK
|
||||
Change Seat=Échanger les sièges
|
||||
Go Offboard=Débarquer
|
||||
Do you really want to go offboard now?=Voulez-vous vraiment débarquer maintenant ?
|
||||
No=Non
|
||||
Yes=Oui
|
||||
>>> There is something wrong with the plane...= >>> Quelque chose est anormal dans cet avion...
|
||||
>>> ADF deactivated.= >>> ADF désactivé
|
||||
>>> ADF activated.= >>> ADF activé
|
||||
>>> Destination written successfully.= >>> Destination enregistrée.
|
||||
>>> There is something wrong with the ADF fields values.= >>> Quelque chose est anormal dans la configuration de l'ADF.
|
||||
>>> Both ADF fields must be given to complete the operation.= >>> Les deux informations ADF doivent être fournies pour terminer l'opération.
|
||||
>>> There is something wrong on ADF saving...= >>> Quelque chose est anormal dans la sauvegarde de l'ADF...
|
||||
Flight Information=Instruments
|
||||
>>> You need the priv= >>> Vous devez avoir le privilège
|
||||
to fly this plane.=pour piloter cet avion.
|
||||
>>> The engine is damaged, start procedure failed.= >>> Moteur endommagé, Échec du démarrage.
|
||||
>>> Flap down=Volets déployés
|
||||
>>> Flap up=Volets relevés
|
||||
>>> You cannot claim this scrap yet, wait some minutes.= >>> Veuillez attendre quelques minutes pour récupérer ces débris
|
||||
Sorry, but this module doesn't work when SkinsDb and Armor are instaled together.=Désolé, ce module ne fontionne pas avec les mods SkinDb et Armor
|
||||
Something isn't working...=Quelque chose défaille...
|
||||
Set Player Texture=Modifier la texture du joueur
|
||||
The isn't activated as secure. Aborting=Inactif pour raison de sécurité. Interruption.
|