After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,41 @@
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
# Use By Game Blockcolor
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Colors for Nodes, Decorates and Hotbar
|
||||||
|
|
||||||
|
-- 8 Colors
|
||||||
|
|
||||||
|
-- color1 = 292421 -- (Black)
|
||||||
|
-- color2 = 0000FF -- (Blue)
|
||||||
|
-- color3 = 00FF00 -- (Green)
|
||||||
|
-- color4 = F5F5F5 -- (White)
|
||||||
|
-- color5 = FF6103 -- (Orange)
|
||||||
|
-- color6 = FF0000 -- (Red)
|
||||||
|
-- color7 = FFFF00 -- (Yellow)
|
||||||
|
-- color8 = FF69B4 -- (Pink)
|
||||||
|
|
||||||
|
-- End
|
||||||
|
|
||||||
|
default_privs = shout,home,fly,fast,interact
|
||||||
|
creative_mode = true
|
||||||
|
enable_damage = false
|
||||||
|
only_peaceful_mobs = false
|
||||||
|
enable_pvp = false
|
||||||
|
enable_tnt = false
|
||||||
|
disable_fire = false
|
||||||
|
fire_enabled = false
|
||||||
|
|
||||||
|
# extras mod settings
|
||||||
|
playerhotbar = 8
|
||||||
|
playerbox = 1
|
||||||
|
playerboxsize = 128
|
||||||
|
pingkick = 1
|
||||||
|
autorollback = 0
|
||||||
|
isplayer = 0
|
||||||
|
recrafting = 0
|
||||||
|
safepvp = 0
|
||||||
|
|
||||||
|
# player visibility?
|
||||||
|
player_transfer_distance = 50
|
||||||
|
unlimited_player_transfer_distance = false
|
|
@ -0,0 +1,37 @@
|
||||||
|
airboat 0.1.8 by paramat
|
||||||
|
For Minetest 0.4.16 and later. Compatible with MT 5.0.0-dev.
|
||||||
|
Depends: default
|
||||||
|
|
||||||
|
Licenses
|
||||||
|
--------
|
||||||
|
Source code: MIT
|
||||||
|
Media (textures and nodebox design): CC0 1.0
|
||||||
|
|
||||||
|
Note about textures and crafting
|
||||||
|
--------------------------------
|
||||||
|
This mod is fully functional but does not currently have a crafting recipe or
|
||||||
|
detailed textures. The textures are templates for you to add detail to.
|
||||||
|
The airboat is available in the creative inventory or by using the /giveme chat
|
||||||
|
command.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
Third-person camera mode is recommended when travelling for a better view.
|
||||||
|
The airboat can be placed on any node, including liquids. It can land on, and
|
||||||
|
will float in, a liquid.
|
||||||
|
|
||||||
|
Controls
|
||||||
|
--------
|
||||||
|
Right mouse button = Enter or exit airboat when pointing at airboat.
|
||||||
|
Forward = Speed up.
|
||||||
|
Slow down when moving backwards.
|
||||||
|
Forward + backward = Enable cruise mode: Airboat will accelerate to maximum
|
||||||
|
forward speed and remain at that speed without needing to
|
||||||
|
hold the forward key.
|
||||||
|
Backward = Slow down.
|
||||||
|
Speed up when moving backwards.
|
||||||
|
Disable cruise mode.
|
||||||
|
Left = Turn left.
|
||||||
|
Right = Turn right.
|
||||||
|
Jump/up = Ascend.
|
||||||
|
Sneak/down = Descend.
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -0,0 +1,312 @@
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Darkened", "292421", 40, 36, 33},
|
||||||
|
{"blue", "Blue", "0000FF", 0, 0, 255},
|
||||||
|
{"green", "Green", "00FF00", 0, 255, 0},
|
||||||
|
{"white", "White", "F5F5F5", 245, 245, 245},
|
||||||
|
{"orange", "Orange", "FF6103", 255, 97, 3},
|
||||||
|
{"red", "Red", "FF0000", 255, 0, 0},
|
||||||
|
{"yellow", "Yellow", "FFFF00", 255, 255, 0},
|
||||||
|
{"pink", "pink", "FF69B4", 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local description = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
-- Functions
|
||||||
|
|
||||||
|
local function get_sign(i)
|
||||||
|
if i == 0 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return i / math.abs(i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_velocity(v, yaw, y)
|
||||||
|
local x = -math.sin(yaw) * v
|
||||||
|
local z = math.cos(yaw) * v
|
||||||
|
return {x = x, y = y, z = z}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_v(v)
|
||||||
|
return math.sqrt(v.x ^ 2 + v.z ^ 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Airboat entity
|
||||||
|
|
||||||
|
local airboat = {
|
||||||
|
initial_properties = {
|
||||||
|
physical = true,
|
||||||
|
collide_with_objects = false, -- Workaround fix for a MT engine bug
|
||||||
|
collisionbox = {-0.85, -1.5, -0.85, 0.85, 1.5, 0.85},
|
||||||
|
visual = "wielditem",
|
||||||
|
visual_size = {x = 2.0, y = 2.0}, -- Scale up of nodebox is these * 1.5
|
||||||
|
textures = {"airboat:airboat_nodebox" ..color},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Custom fields
|
||||||
|
driver = nil,
|
||||||
|
removed = false,
|
||||||
|
v = 0,
|
||||||
|
vy = 0,
|
||||||
|
rot = 0,
|
||||||
|
auto = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function airboat.on_rightclick(self, clicker)
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = clicker:get_player_name()
|
||||||
|
if self.driver and name == self.driver then
|
||||||
|
-- Detach
|
||||||
|
self.driver = nil
|
||||||
|
self.auto = false
|
||||||
|
clicker:set_detach()
|
||||||
|
default.player_attached[name] = false
|
||||||
|
default.player_set_animation(clicker, "stand" , 30)
|
||||||
|
local pos = clicker:getpos()
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
clicker:setpos(pos)
|
||||||
|
end)
|
||||||
|
elseif not self.driver then
|
||||||
|
-- Attach
|
||||||
|
local attach = clicker:get_attach()
|
||||||
|
if attach and attach:get_luaentity() then
|
||||||
|
local luaentity = attach:get_luaentity()
|
||||||
|
if luaentity.driver then
|
||||||
|
luaentity.driver = nil
|
||||||
|
end
|
||||||
|
clicker:set_detach()
|
||||||
|
end
|
||||||
|
self.driver = name
|
||||||
|
clicker:set_attach(self.object, "",
|
||||||
|
{x = 0, y = -2, z = 0}, {x = 0, y = 0, z = 0})
|
||||||
|
default.player_attached[name] = true
|
||||||
|
minetest.after(0.2, function()
|
||||||
|
default.player_set_animation(clicker, "sit" , 30)
|
||||||
|
end)
|
||||||
|
clicker:set_look_horizontal(self.object:getyaw())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function airboat.on_activate(self, staticdata, dtime_s)
|
||||||
|
self.object:set_armor_groups({immortal = 1})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function airboat.on_punch(self, puncher)
|
||||||
|
if not puncher or not puncher:is_player() or self.removed then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local name = puncher:get_player_name()
|
||||||
|
if self.driver and name == self.driver then
|
||||||
|
-- Detach
|
||||||
|
self.driver = nil
|
||||||
|
puncher:set_detach()
|
||||||
|
default.player_attached[name] = false
|
||||||
|
end
|
||||||
|
if not self.driver then
|
||||||
|
-- Move to inventory
|
||||||
|
self.removed = true
|
||||||
|
local inv = puncher:get_inventory()
|
||||||
|
if not (creative and creative.is_enabled_for
|
||||||
|
and creative.is_enabled_for(name))
|
||||||
|
or not inv:contains_item("main", "airboat:airboat" ..color) then
|
||||||
|
local leftover = inv:add_item("main", "airboat:airboat" ..color)
|
||||||
|
if not leftover:is_empty() then
|
||||||
|
minetest.add_item(self.object:getpos(), leftover)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
self.object:remove()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function airboat.on_step(self, dtime)
|
||||||
|
self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
|
||||||
|
self.vy = self.object:getvelocity().y
|
||||||
|
|
||||||
|
-- Controls
|
||||||
|
if self.driver then
|
||||||
|
local driver_objref = minetest.get_player_by_name(self.driver)
|
||||||
|
if driver_objref then
|
||||||
|
local ctrl = driver_objref:get_player_control()
|
||||||
|
if ctrl.up and ctrl.down then
|
||||||
|
if not self.auto then
|
||||||
|
self.auto = true
|
||||||
|
minetest.chat_send_player(self.driver,
|
||||||
|
"[airboat] Cruise on")
|
||||||
|
end
|
||||||
|
elseif ctrl.down then
|
||||||
|
self.v = self.v - 0.1
|
||||||
|
if self.auto then
|
||||||
|
self.auto = false
|
||||||
|
minetest.chat_send_player(self.driver,
|
||||||
|
"[airboat] Cruise off")
|
||||||
|
end
|
||||||
|
elseif ctrl.up or self.auto then
|
||||||
|
self.v = self.v + 0.1
|
||||||
|
end
|
||||||
|
if ctrl.left then
|
||||||
|
self.rot = self.rot + 0.001
|
||||||
|
elseif ctrl.right then
|
||||||
|
self.rot = self.rot - 0.001
|
||||||
|
end
|
||||||
|
if ctrl.jump then
|
||||||
|
self.vy = self.vy + 0.075
|
||||||
|
elseif ctrl.sneak then
|
||||||
|
self.vy = self.vy - 0.075
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Player left server while driving
|
||||||
|
-- In MT 5.0.0 use 'airboat:on_detach_child()' to do this
|
||||||
|
self.driver = nil
|
||||||
|
self.auto = false
|
||||||
|
minetest.log("warning", "[airboat] Driver left server while" ..
|
||||||
|
" driving. This may cause some 'Pushing ObjectRef to" ..
|
||||||
|
" removed/deactivated object' warnings.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Early return for stationary vehicle
|
||||||
|
if self.v == 0 and self.rot == 0 and self.vy == 0 then
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reduction and limiting of linear speed
|
||||||
|
local s = get_sign(self.v)
|
||||||
|
self.v = self.v - 0.02 * s
|
||||||
|
if s ~= get_sign(self.v) then
|
||||||
|
self.v = 0
|
||||||
|
end
|
||||||
|
if math.abs(self.v) > 6 then
|
||||||
|
self.v = 6 * get_sign(self.v)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reduction and limiting of rotation
|
||||||
|
local sr = get_sign(self.rot)
|
||||||
|
self.rot = self.rot - 0.0003 * sr
|
||||||
|
if sr ~= get_sign(self.rot) then
|
||||||
|
self.rot = 0
|
||||||
|
end
|
||||||
|
if math.abs(self.rot) > 0.015 then
|
||||||
|
self.rot = 0.015 * get_sign(self.rot)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reduction and limiting of vertical speed
|
||||||
|
local sy = get_sign(self.vy)
|
||||||
|
self.vy = self.vy - 0.03 * sy
|
||||||
|
if sy ~= get_sign(self.vy) then
|
||||||
|
self.vy = 0
|
||||||
|
end
|
||||||
|
if math.abs(self.vy) > 4 then
|
||||||
|
self.vy = 4 * get_sign(self.vy)
|
||||||
|
end
|
||||||
|
|
||||||
|
local new_acce = {x = 0, y = 0, z = 0}
|
||||||
|
-- Bouyancy in liquids
|
||||||
|
local p = self.object:getpos()
|
||||||
|
p.y = p.y - 1.5
|
||||||
|
local def = minetest.registered_nodes[minetest.get_node(p).name]
|
||||||
|
if def and (def.liquidtype == "source" or def.liquidtype == "flowing") then
|
||||||
|
new_acce = {x = 0, y = 10, z = 0}
|
||||||
|
end
|
||||||
|
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), self.vy))
|
||||||
|
self.object:setacceleration(new_acce)
|
||||||
|
self.object:setyaw(self.object:getyaw() + (1 + dtime) * self.rot)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_entity("airboat:airboat" ..color , airboat)
|
||||||
|
|
||||||
|
|
||||||
|
-- Craftitem
|
||||||
|
|
||||||
|
minetest.register_craftitem("airboat:airboat" .. color, {
|
||||||
|
description = "Airboat" .. color,
|
||||||
|
inventory_image = "airboat_airboat_inv.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "none.png",
|
||||||
|
wield_scale = {x = 4, y = 4, z = 4},
|
||||||
|
liquids_pointable = true,
|
||||||
|
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local node = minetest.get_node(under)
|
||||||
|
local udef = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
|
-- Run any on_rightclick function of pointed node instead
|
||||||
|
if udef and udef.on_rightclick and
|
||||||
|
not (placer and placer:is_player() and
|
||||||
|
placer:get_player_control().sneak) then
|
||||||
|
return udef.on_rightclick(under, node, placer, itemstack,
|
||||||
|
pointed_thing) or itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
if pointed_thing.type ~= "node" then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
pointed_thing.under.y = pointed_thing.under.y + 2
|
||||||
|
local airboat = minetest.add_entity(pointed_thing.under,
|
||||||
|
"airboat:airboat" ..color)
|
||||||
|
if airboat then
|
||||||
|
if placer then
|
||||||
|
airboat:setyaw(placer:get_look_horizontal())
|
||||||
|
end
|
||||||
|
local player_name = placer and placer:get_player_name() or ""
|
||||||
|
if not (creative and creative.is_enabled_for and
|
||||||
|
creative.is_enabled_for(player_name)) then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- Nodebox for entity wielditem visual
|
||||||
|
|
||||||
|
minetest.register_node("airboat:airboat_nodebox" .. color, {
|
||||||
|
description = "Airboat Nodebox" .. color,
|
||||||
|
tiles = { -- Top, base, right, left, front, back
|
||||||
|
"airboat_airboat_top.png^[colorize:#"..colour..":70",
|
||||||
|
"airboat_airboat_base.png^[colorize:#"..colour..":70",
|
||||||
|
"airboat_airboat_right.png^[colorize:#"..colour..":70",
|
||||||
|
"airboat_airboat_left.png^[colorize:#"..colour..":70",
|
||||||
|
"airboat_airboat_front.png^[colorize:#"..colour..":70",
|
||||||
|
"airboat_airboat_back.png^[colorize:#"..colour..":70",
|
||||||
|
},
|
||||||
|
paramtype = "light",
|
||||||
|
drawtype = "nodebox",
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = { -- Widmin, heimin, lenmin, widmax, heimax, lenmax
|
||||||
|
{-0.271, -0.167, -0.5, 0.271, 0.375, 0.5}, -- Envelope
|
||||||
|
{-0.167, -0.5, -0.25, 0.167, -0.167, 0.25}, -- Gondola
|
||||||
|
{-0.021, 0.375, -0.5, 0.021, 0.5, -0.25}, -- Top fin
|
||||||
|
{-0.021, -0.292, -0.5, 0.021, -0.167, -0.25}, -- Base fin
|
||||||
|
{-0.396, 0.083, -0.5, -0.271, 0.125, -0.25}, -- Left fin
|
||||||
|
{ 0.271, 0.083, -0.5, 0.396, 0.125, -0.25}, -- Right fin
|
||||||
|
},
|
||||||
|
},
|
||||||
|
groups = {not_in_creative_inventory = 1},
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,57 @@
|
||||||
|
License of source code
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (C) 2018 paramat
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
|
||||||
|
License of media (textures)
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||||
|
Paramat
|
||||||
|
|
||||||
|
No Copyright
|
||||||
|
|
||||||
|
The person who associated a work with this deed has dedicated the work to the
|
||||||
|
public domain by waiving all of his or her rights to the work worldwide under
|
||||||
|
copyright law, including all related and neighboring rights, to the extent
|
||||||
|
allowed by law.
|
||||||
|
|
||||||
|
You can copy, modify, distribute and perform the work, even for commercial
|
||||||
|
purposes, all without asking permission. See Other Information below.
|
||||||
|
|
||||||
|
Other Information:
|
||||||
|
|
||||||
|
In no way are the patent or trademark rights of any person affected by CC0, nor
|
||||||
|
are the rights that other persons may have in the work or in how the work is
|
||||||
|
used, such as publicity or privacy rights.
|
||||||
|
|
||||||
|
Unless expressly stated otherwise, the person who associated a work with this
|
||||||
|
deed makes no warranties about the work, and disclaims liability for all uses
|
||||||
|
of the work, to the fullest extent permitted by applicable law.
|
||||||
|
|
||||||
|
When using or citing the work, you should not imply endorsement by the author
|
||||||
|
or the affirmer.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://creativecommons.org/publicdomain/zero/1.0/
|
|
@ -0,0 +1 @@
|
||||||
|
name = airboat
|
After Width: | Height: | Size: 127 B |
After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 131 B |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 127 B |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 100 B |
|
@ -0,0 +1,22 @@
|
||||||
|
Carts (formerly boost_cart)
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Carts, based almost entirely on the mod boost_cart [1], which
|
||||||
|
itself is based on (and fully compatible with) the carts mod [2].
|
||||||
|
|
||||||
|
The model was originally designed by stujones11 [3] (CC-0).
|
||||||
|
|
||||||
|
Cart textures are based on original work from PixelBOX (WTFPL).
|
||||||
|
|
||||||
|
|
||||||
|
[1] https://github.com/SmallJoker/boost_cart/
|
||||||
|
[2] https://github.com/PilzAdam/carts/
|
||||||
|
[3] https://github.com/stujones11/railcart/
|
||||||
|
|
||||||
|
|
||||||
|
Features
|
||||||
|
----------
|
||||||
|
- A fast cart for your railway or roller coaster (up to 7 m/s!)
|
||||||
|
- Boost and brake rails
|
||||||
|
- Rail junction switching with the 'right-left' walking keys
|
||||||
|
- Handbrake with the 'back' key
|
|
@ -0,0 +1,430 @@
|
||||||
|
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1, 40, 36, 33},
|
||||||
|
{"blue", "Color2", color2, 0, 0, 255},
|
||||||
|
{"green", "Color3", color3, 0, 255, 0},
|
||||||
|
{"white", "Color4", color4, 245, 245, 245},
|
||||||
|
{"orange", "Color5", color5, 255, 97, 3},
|
||||||
|
{"red", "Color6", color6, 255, 0, 0},
|
||||||
|
{"yellow", "Color7", color7, 255, 255, 0},
|
||||||
|
{"pink", "Color8", color8, 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
local cart_entity = {
|
||||||
|
physical = false, -- otherwise going uphill breaks
|
||||||
|
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "carts_cart.b3d",
|
||||||
|
visual_size = {x=1, y=1},
|
||||||
|
|
||||||
|
textures = {
|
||||||
|
"carts.png^[colorize:#"..colour..":70"
|
||||||
|
},
|
||||||
|
|
||||||
|
driver = nil,
|
||||||
|
punched = false, -- used to re-send velocity and position
|
||||||
|
velocity = {x=0, y=0, z=0}, -- only used on punch
|
||||||
|
old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch
|
||||||
|
old_pos = nil,
|
||||||
|
old_switch = 0,
|
||||||
|
railtype = nil,
|
||||||
|
attached_items = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cart_entity:on_rightclick(clicker)
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local player_name = clicker:get_player_name()
|
||||||
|
if self.driver and player_name == self.driver then
|
||||||
|
self.driver = nil
|
||||||
|
carts:manage_attachment(clicker, nil)
|
||||||
|
elseif not self.driver then
|
||||||
|
self.driver = player_name
|
||||||
|
carts:manage_attachment(clicker, self.object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cart_entity:on_activate(staticdata, dtime_s)
|
||||||
|
self.object:set_armor_groups({immortal=1})
|
||||||
|
if string.sub(staticdata, 1, string.len("return")) ~= "return" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local data = minetest.deserialize(staticdata)
|
||||||
|
if not data or type(data) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.railtype = data.railtype
|
||||||
|
if data.old_dir then
|
||||||
|
self.old_dir = data.old_dir
|
||||||
|
end
|
||||||
|
if data.old_vel then
|
||||||
|
self.old_vel = data.old_vel
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cart_entity:get_staticdata()
|
||||||
|
return minetest.serialize({
|
||||||
|
railtype = self.railtype,
|
||||||
|
old_dir = self.old_dir,
|
||||||
|
old_vel = self.old_vel
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
if not self.railtype then
|
||||||
|
local node = minetest.get_node(pos).name
|
||||||
|
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
|
||||||
|
end
|
||||||
|
-- Punched by non-player
|
||||||
|
if not puncher or not puncher:is_player() then
|
||||||
|
local cart_dir = carts:get_rail_direction(pos, self.old_dir, nil, nil, self.railtype)
|
||||||
|
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.velocity = vector.multiply(cart_dir, 2)
|
||||||
|
self.punched = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Player digs cart by sneak-punch
|
||||||
|
if puncher:get_player_control().sneak then
|
||||||
|
if self.sound_handle then
|
||||||
|
minetest.sound_stop(self.sound_handle)
|
||||||
|
end
|
||||||
|
-- Detach driver and items
|
||||||
|
if self.driver then
|
||||||
|
if self.old_pos then
|
||||||
|
self.object:setpos(self.old_pos)
|
||||||
|
end
|
||||||
|
local player = minetest.get_player_by_name(self.driver)
|
||||||
|
carts:manage_attachment(player, nil)
|
||||||
|
end
|
||||||
|
for _,obj_ in ipairs(self.attached_items) do
|
||||||
|
if obj_ then
|
||||||
|
obj_:set_detach()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Pick up cart
|
||||||
|
local inv = puncher:get_inventory()
|
||||||
|
if not (creative and creative.is_enabled_for
|
||||||
|
and creative.is_enabled_for(puncher:get_player_name()))
|
||||||
|
or not inv:contains_item("main", "carts:cart" .. color) then
|
||||||
|
local leftover = inv:add_item("main", "carts:cart" .. color)
|
||||||
|
-- If no room in inventory add a replacement cart to the world
|
||||||
|
if not leftover:is_empty() then
|
||||||
|
minetest.add_item(self.object:getpos(), leftover)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- Player punches cart to alter velocity
|
||||||
|
local vel = self.object:getvelocity()
|
||||||
|
if puncher:get_player_name() == self.driver then
|
||||||
|
if math.abs(vel.x + vel.z) > carts.punch_speed_max then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local punch_dir = carts:velocity_to_dir(puncher:get_look_dir())
|
||||||
|
punch_dir.y = 0
|
||||||
|
local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype)
|
||||||
|
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local punch_interval = 1
|
||||||
|
if tool_capabilities and tool_capabilities.full_punch_interval then
|
||||||
|
punch_interval = tool_capabilities.full_punch_interval
|
||||||
|
end
|
||||||
|
time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval)
|
||||||
|
local f = 2 * (time_from_last_punch / punch_interval)
|
||||||
|
|
||||||
|
self.velocity = vector.multiply(cart_dir, f)
|
||||||
|
self.old_dir = cart_dir
|
||||||
|
self.punched = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rail_on_step_event(handler, obj, dtime)
|
||||||
|
if handler then
|
||||||
|
handler(obj, dtime)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- sound refresh interval = 1.0sec
|
||||||
|
local function rail_sound(self, dtime)
|
||||||
|
if not self.sound_ttl then
|
||||||
|
self.sound_ttl = 1.0
|
||||||
|
return
|
||||||
|
elseif self.sound_ttl > 0 then
|
||||||
|
self.sound_ttl = self.sound_ttl - dtime
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.sound_ttl = 1.0
|
||||||
|
if self.sound_handle then
|
||||||
|
local handle = self.sound_handle
|
||||||
|
self.sound_handle = nil
|
||||||
|
minetest.after(0.2, minetest.sound_stop, handle)
|
||||||
|
end
|
||||||
|
local vel = self.object:getvelocity()
|
||||||
|
local speed = vector.length(vel)
|
||||||
|
if speed > 0 then
|
||||||
|
self.sound_handle = minetest.sound_play(
|
||||||
|
"carts_cart_moving", {
|
||||||
|
object = self.object,
|
||||||
|
gain = (speed / carts.speed_max) / 2,
|
||||||
|
loop = true,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_railparams(pos)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
return carts.railparams[node.name] or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rail_on_step(self, dtime)
|
||||||
|
local vel = self.object:getvelocity()
|
||||||
|
if self.punched then
|
||||||
|
vel = vector.add(vel, self.velocity)
|
||||||
|
self.object:setvelocity(vel)
|
||||||
|
self.old_dir.y = 0
|
||||||
|
elseif vector.equals(vel, {x=0, y=0, z=0}) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
local update = {}
|
||||||
|
|
||||||
|
-- stop cart if velocity vector flips
|
||||||
|
if self.old_vel and self.old_vel.y == 0 and
|
||||||
|
(self.old_vel.x * vel.x < 0 or self.old_vel.z * vel.z < 0) then
|
||||||
|
self.old_vel = {x = 0, y = 0, z = 0}
|
||||||
|
self.old_pos = pos
|
||||||
|
self.object:setvelocity(vector.new())
|
||||||
|
self.object:setacceleration(vector.new())
|
||||||
|
rail_on_step_event(get_railparams(pos).on_step, self, dtime)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.old_vel = vector.new(vel)
|
||||||
|
|
||||||
|
if self.old_pos and not self.punched then
|
||||||
|
local flo_pos = vector.round(pos)
|
||||||
|
local flo_old = vector.round(self.old_pos)
|
||||||
|
if vector.equals(flo_pos, flo_old) then
|
||||||
|
-- Do not check one node multiple times
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ctrl, player
|
||||||
|
|
||||||
|
-- Get player controls
|
||||||
|
if self.driver then
|
||||||
|
player = minetest.get_player_by_name(self.driver)
|
||||||
|
if player then
|
||||||
|
ctrl = player:get_player_control()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.old_pos then
|
||||||
|
-- Detection for "skipping" nodes
|
||||||
|
local found_path = carts:pathfinder(
|
||||||
|
pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype
|
||||||
|
)
|
||||||
|
|
||||||
|
if not found_path then
|
||||||
|
-- No rail found: reset back to the expected position
|
||||||
|
pos = vector.new(self.old_pos)
|
||||||
|
update.pos = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local cart_dir = carts:velocity_to_dir(vel)
|
||||||
|
local railparams
|
||||||
|
|
||||||
|
-- dir: New moving direction of the cart
|
||||||
|
-- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node
|
||||||
|
local dir, switch_keys = carts:get_rail_direction(
|
||||||
|
pos, cart_dir, ctrl, self.old_switch, self.railtype
|
||||||
|
)
|
||||||
|
|
||||||
|
local new_acc = {x=0, y=0, z=0}
|
||||||
|
if vector.equals(dir, {x=0, y=0, z=0}) then
|
||||||
|
vel = {x = 0, y = 0, z = 0}
|
||||||
|
pos = vector.round(pos)
|
||||||
|
update.pos = true
|
||||||
|
update.vel = true
|
||||||
|
else
|
||||||
|
-- Direction change detected
|
||||||
|
if not vector.equals(dir, self.old_dir) then
|
||||||
|
vel = vector.multiply(dir, math.abs(vel.x + vel.z))
|
||||||
|
update.vel = true
|
||||||
|
if dir.y ~= self.old_dir.y then
|
||||||
|
pos = vector.round(pos)
|
||||||
|
update.pos = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Center on the rail
|
||||||
|
if dir.z ~= 0 and math.floor(pos.x + 0.5) ~= pos.x then
|
||||||
|
pos.x = math.floor(pos.x + 0.5)
|
||||||
|
update.pos = true
|
||||||
|
end
|
||||||
|
if dir.x ~= 0 and math.floor(pos.z + 0.5) ~= pos.z then
|
||||||
|
pos.z = math.floor(pos.z + 0.5)
|
||||||
|
update.pos = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Slow down or speed up..
|
||||||
|
local acc = dir.y * -4.0
|
||||||
|
|
||||||
|
-- Get rail for corrected position
|
||||||
|
railparams = get_railparams(pos)
|
||||||
|
|
||||||
|
-- no need to check for railparams == nil since we always make it exist.
|
||||||
|
local speed_mod = railparams.acceleration
|
||||||
|
if speed_mod and speed_mod ~= 0 then
|
||||||
|
-- Try to make it similar to the original carts mod
|
||||||
|
acc = acc + speed_mod
|
||||||
|
else
|
||||||
|
-- Handbrake or coast
|
||||||
|
if ctrl and ctrl.down then
|
||||||
|
acc = acc - 3
|
||||||
|
else
|
||||||
|
acc = acc - 0.4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
new_acc = vector.multiply(dir, acc)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Limits
|
||||||
|
local max_vel = carts.speed_max
|
||||||
|
for _, v in pairs({"x","y","z"}) do
|
||||||
|
if math.abs(vel[v]) > max_vel then
|
||||||
|
vel[v] = carts:get_sign(vel[v]) * max_vel
|
||||||
|
new_acc[v] = 0
|
||||||
|
update.vel = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.object:setacceleration(new_acc)
|
||||||
|
self.old_pos = vector.new(pos)
|
||||||
|
if not vector.equals(dir, {x=0, y=0, z=0}) then
|
||||||
|
self.old_dir = vector.new(dir)
|
||||||
|
end
|
||||||
|
self.old_switch = switch_keys
|
||||||
|
|
||||||
|
if self.punched then
|
||||||
|
-- Collect dropped items
|
||||||
|
for _, obj_ in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||||
|
if not obj_:is_player() and
|
||||||
|
obj_:get_luaentity() and
|
||||||
|
not obj_:get_luaentity().physical_state and
|
||||||
|
obj_:get_luaentity().name == "__builtin:item" then
|
||||||
|
|
||||||
|
obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
|
||||||
|
self.attached_items[#self.attached_items + 1] = obj_
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.punched = false
|
||||||
|
update.vel = true
|
||||||
|
end
|
||||||
|
|
||||||
|
railparams = railparams or get_railparams(pos)
|
||||||
|
|
||||||
|
if not (update.vel or update.pos) then
|
||||||
|
rail_on_step_event(railparams.on_step, self, dtime)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local yaw = 0
|
||||||
|
if self.old_dir.x < 0 then
|
||||||
|
yaw = 0.5
|
||||||
|
elseif self.old_dir.x > 0 then
|
||||||
|
yaw = 1.5
|
||||||
|
elseif self.old_dir.z < 0 then
|
||||||
|
yaw = 1
|
||||||
|
end
|
||||||
|
self.object:setyaw(yaw * math.pi)
|
||||||
|
|
||||||
|
local anim = {x=0, y=0}
|
||||||
|
if dir.y == -1 then
|
||||||
|
anim = {x=1, y=1}
|
||||||
|
elseif dir.y == 1 then
|
||||||
|
anim = {x=2, y=2}
|
||||||
|
end
|
||||||
|
self.object:set_animation(anim, 1, 0)
|
||||||
|
|
||||||
|
self.object:setvelocity(vel)
|
||||||
|
if update.pos then
|
||||||
|
self.object:setpos(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- call event handler
|
||||||
|
rail_on_step_event(railparams.on_step, self, dtime)
|
||||||
|
end
|
||||||
|
|
||||||
|
function cart_entity:on_step(dtime)
|
||||||
|
rail_on_step(self, dtime)
|
||||||
|
rail_sound(self, dtime)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_entity("carts:cart" .. color, cart_entity)
|
||||||
|
|
||||||
|
minetest.register_craftitem("carts:cart" .. color, {
|
||||||
|
description = color .. "Cart (Sneak+Click to pick up)",
|
||||||
|
inventory_image = "cart.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "none.png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local node = minetest.get_node(under)
|
||||||
|
local udef = minetest.registered_nodes[node.name]
|
||||||
|
if udef and udef.on_rightclick and
|
||||||
|
not (placer and placer:get_player_control().sneak) then
|
||||||
|
return udef.on_rightclick(under, node, placer, itemstack,
|
||||||
|
pointed_thing) or itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
if not pointed_thing.type == "node" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if carts:is_rail(pointed_thing.under) then
|
||||||
|
minetest.add_entity(pointed_thing.under, "carts:cart" .. color)
|
||||||
|
elseif carts:is_rail(pointed_thing.above) then
|
||||||
|
minetest.add_entity(pointed_thing.above, "carts:cart" .. color)
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.sound_play({name = "default_place_node_metal", gain = 0.5},
|
||||||
|
{pos = pointed_thing.above})
|
||||||
|
|
||||||
|
if not (creative and creative.is_enabled_for
|
||||||
|
and creative.is_enabled_for(placer:get_player_name())) then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -0,0 +1,221 @@
|
||||||
|
function carts:get_sign(z)
|
||||||
|
if z == 0 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return z / math.abs(z)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:manage_attachment(player, obj)
|
||||||
|
if not player then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local status = obj ~= nil
|
||||||
|
local player_name = player:get_player_name()
|
||||||
|
if default.player_attached[player_name] == status then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
default.player_attached[player_name] = status
|
||||||
|
|
||||||
|
if status then
|
||||||
|
player:set_attach(obj, "", {x=0, y=6, z=0}, {x=0, y=0, z=0})
|
||||||
|
player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
|
||||||
|
else
|
||||||
|
player:set_detach()
|
||||||
|
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:velocity_to_dir(v)
|
||||||
|
if math.abs(v.x) > math.abs(v.z) then
|
||||||
|
return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0}
|
||||||
|
else
|
||||||
|
return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:is_rail(pos, railtype)
|
||||||
|
local node = minetest.get_node(pos).name
|
||||||
|
if node == "ignore" then
|
||||||
|
local vm = minetest.get_voxel_manip()
|
||||||
|
local emin, emax = vm:read_from_map(pos, pos)
|
||||||
|
local area = VoxelArea:new{
|
||||||
|
MinEdge = emin,
|
||||||
|
MaxEdge = emax,
|
||||||
|
}
|
||||||
|
local data = vm:get_data()
|
||||||
|
local vi = area:indexp(pos)
|
||||||
|
node = minetest.get_name_from_content_id(data[vi])
|
||||||
|
end
|
||||||
|
if minetest.get_item_group(node, "rail") == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not railtype then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return minetest.get_item_group(node, "connect_to_raillike") == railtype
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:check_front_up_down(pos, dir_, check_up, railtype)
|
||||||
|
local dir = vector.new(dir_)
|
||||||
|
local cur
|
||||||
|
|
||||||
|
-- Front
|
||||||
|
dir.y = 0
|
||||||
|
cur = vector.add(pos, dir)
|
||||||
|
if carts:is_rail(cur, railtype) then
|
||||||
|
return dir
|
||||||
|
end
|
||||||
|
-- Up
|
||||||
|
if check_up then
|
||||||
|
dir.y = 1
|
||||||
|
cur = vector.add(pos, dir)
|
||||||
|
if carts:is_rail(cur, railtype) then
|
||||||
|
return dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Down
|
||||||
|
dir.y = -1
|
||||||
|
cur = vector.add(pos, dir)
|
||||||
|
if carts:is_rail(cur, railtype) then
|
||||||
|
return dir
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
||||||
|
local pos = vector.round(pos_)
|
||||||
|
local cur
|
||||||
|
local left_check, right_check = true, true
|
||||||
|
|
||||||
|
-- Check left and right
|
||||||
|
local left = {x=0, y=0, z=0}
|
||||||
|
local right = {x=0, y=0, z=0}
|
||||||
|
if dir.z ~= 0 and dir.x == 0 then
|
||||||
|
left.x = -dir.z
|
||||||
|
right.x = dir.z
|
||||||
|
elseif dir.x ~= 0 and dir.z == 0 then
|
||||||
|
left.z = dir.x
|
||||||
|
right.z = -dir.x
|
||||||
|
end
|
||||||
|
|
||||||
|
if ctrl then
|
||||||
|
if old_switch == 1 then
|
||||||
|
left_check = false
|
||||||
|
elseif old_switch == 2 then
|
||||||
|
right_check = false
|
||||||
|
end
|
||||||
|
if ctrl.left and left_check then
|
||||||
|
cur = carts:check_front_up_down(pos, left, false, railtype)
|
||||||
|
if cur then
|
||||||
|
return cur, 1
|
||||||
|
end
|
||||||
|
left_check = false
|
||||||
|
end
|
||||||
|
if ctrl.right and right_check then
|
||||||
|
cur = carts:check_front_up_down(pos, right, false, railtype)
|
||||||
|
if cur then
|
||||||
|
return cur, 2
|
||||||
|
end
|
||||||
|
right_check = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Normal
|
||||||
|
cur = carts:check_front_up_down(pos, dir, true, railtype)
|
||||||
|
if cur then
|
||||||
|
return cur
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Left, if not already checked
|
||||||
|
if left_check then
|
||||||
|
cur = carts:check_front_up_down(pos, left, false, railtype)
|
||||||
|
if cur then
|
||||||
|
return cur
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Right, if not already checked
|
||||||
|
if right_check then
|
||||||
|
cur = carts:check_front_up_down(pos, right, false, railtype)
|
||||||
|
if cur then
|
||||||
|
return cur
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Backwards
|
||||||
|
if not old_switch then
|
||||||
|
cur = carts:check_front_up_down(pos, {
|
||||||
|
x = -dir.x,
|
||||||
|
y = dir.y,
|
||||||
|
z = -dir.z
|
||||||
|
}, true, railtype)
|
||||||
|
if cur then
|
||||||
|
return cur
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {x=0, y=0, z=0}
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype)
|
||||||
|
local pos = vector.round(pos_)
|
||||||
|
local pf_pos = vector.round(old_pos)
|
||||||
|
local pf_dir = vector.new(old_dir)
|
||||||
|
|
||||||
|
for i = 1, 3 do
|
||||||
|
if vector.equals(pf_pos, pos) then
|
||||||
|
-- Success! Cart moved on correctly
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype)
|
||||||
|
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
|
||||||
|
-- No way forwards
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
pf_pos = vector.add(pf_pos, pf_dir)
|
||||||
|
end
|
||||||
|
-- Cart not found
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:register_rail(name, def_overwrite, railparams)
|
||||||
|
local def = {
|
||||||
|
drawtype = "raillike",
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
is_ground_content = false,
|
||||||
|
walkable = false,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||||
|
},
|
||||||
|
sounds = default.node_sound_metal_defaults()
|
||||||
|
}
|
||||||
|
for k, v in pairs(def_overwrite) do
|
||||||
|
def[k] = v
|
||||||
|
end
|
||||||
|
if not def.inventory_image then
|
||||||
|
def.wield_image = def.tiles[1]
|
||||||
|
def.inventory_image = def.tiles[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
if railparams then
|
||||||
|
carts.railparams[name] = table.copy(railparams)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_node(name, def)
|
||||||
|
end
|
||||||
|
|
||||||
|
function carts:get_rail_groups(additional_groups)
|
||||||
|
-- Get the default rail groups and add more when a table is given
|
||||||
|
local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1}
|
||||||
|
if type(additional_groups) == "table" then
|
||||||
|
for k, v in pairs(additional_groups) do
|
||||||
|
groups[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return groups
|
||||||
|
end
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
carts = {}
|
||||||
|
carts.modpath = minetest.get_modpath("carts")
|
||||||
|
carts.railparams = {}
|
||||||
|
|
||||||
|
-- Maximal speed of the cart in m/s (min = -1)
|
||||||
|
carts.speed_max = 7
|
||||||
|
-- Set to -1 to disable punching the cart from inside (min = -1)
|
||||||
|
carts.punch_speed_max = 5
|
||||||
|
|
||||||
|
|
||||||
|
dofile(carts.modpath.."/functions.lua")
|
||||||
|
dofile(carts.modpath.."/rails.lua")
|
||||||
|
|
||||||
|
-- Support for non-default games
|
||||||
|
if not default.player_attached then
|
||||||
|
default.player_attached = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
dofile(carts.modpath.."/cart_entity.lua")
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
License of source code
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (C) 2012-2016 PilzAdam
|
||||||
|
Copyright (C) 2014-2016 SmallJoker
|
||||||
|
Copyright (C) 2012-2016 Various Minetest developers and contributors
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
|
||||||
|
Licenses of media
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
CC-0, see: https://creativecommons.org/share-your-work/public-domain/cc0/, except
|
||||||
|
if other license is mentioned.
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
---------
|
||||||
|
Originally from PixelBOX (Gambit):
|
||||||
|
carts_cart_side.png
|
||||||
|
carts_cart_top.png
|
||||||
|
carts_cart_front.png*
|
||||||
|
carts_cart.png*
|
||||||
|
|
||||||
|
sofar + stujones11:
|
||||||
|
carts_cart.b3d and carts_cart.blend
|
||||||
|
|
||||||
|
hexafraction, modified by sofar
|
||||||
|
carts_rail_*.png
|
||||||
|
|
||||||
|
http://www.freesound.org/people/YleArkisto/sounds/253159/ - YleArkisto - CC-BY-3.0
|
||||||
|
carts_cart_moving.*.ogg
|
|
@ -0,0 +1,44 @@
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1, 40, 36, 33},
|
||||||
|
{"blue", "Color2", color2, 0, 0, 255},
|
||||||
|
{"green", "Color3", color3, 0, 255, 0},
|
||||||
|
{"white", "Color4", color4, 245, 245, 245},
|
||||||
|
{"orange", "Color5", color5, 255, 97, 3},
|
||||||
|
{"red", "Color6", color6, 255, 0, 0},
|
||||||
|
{"yellow", "Color7", color7, 255, 255, 0},
|
||||||
|
{"pink", "Color8", color8, 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
minetest.register_alias("carts:rail", "carts:railwhite")
|
||||||
|
|
||||||
|
carts:register_rail("carts:rail" .. color, {
|
||||||
|
description = color .. "rail",
|
||||||
|
inventory_image = "carts_rail_straight_pwr.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "color_hand" .. color .. ".png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
tiles = {
|
||||||
|
"carts_rail_straight_pwr.png^[colorize:#"..colour..":70", "carts_rail_curved_pwr.png^[colorize:#"..colour..":70",
|
||||||
|
"carts_rail_t_junction_pwr.png^[colorize:#"..colour..":70",
|
||||||
|
"carts_rail_crossing_pwr.png^[colorize:#"..colour..":70"
|
||||||
|
},
|
||||||
|
groups = carts:get_rail_groups(),
|
||||||
|
}, {acceleration = 5})
|
||||||
|
|
||||||
|
end
|
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 160 B |
After Width: | Height: | Size: 209 B |
After Width: | Height: | Size: 216 B |
After Width: | Height: | Size: 154 B |
After Width: | Height: | Size: 244 B |
|
@ -0,0 +1,34 @@
|
||||||
|
driftcar 0.1.12 by paramat
|
||||||
|
For Minetest 0.4.16 and later. Compatible with Minetest 5.0.0-dev.
|
||||||
|
Depends: default
|
||||||
|
|
||||||
|
Licenses
|
||||||
|
--------
|
||||||
|
Source code: MIT
|
||||||
|
Media (textures and car nodebox): CC BY-SA 3.0
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
A vehicle using some physics modelling for more realistic behaviour.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
Due to client->server->client control delay this mod is best used in
|
||||||
|
singleplayer or in local multiplayer.
|
||||||
|
Intensive mods that cause long server lags, such as Lua mapgen mods, will affect
|
||||||
|
the responsiveness of the vehicle, even in singleplayer.
|
||||||
|
|
||||||
|
There is no crafting recipe, the vehicle can be found in the creative inventory.
|
||||||
|
Third-person camera mode is recommended when driving for a better view.
|
||||||
|
If parameter 'AVIEW' in the 'init.lua' file is set to 'true', view is
|
||||||
|
automatically set to vehicle velocity direction.
|
||||||
|
|
||||||
|
Controls
|
||||||
|
--------
|
||||||
|
Right mouse button = Enter or exit car when pointing at car.
|
||||||
|
Forward = Speed up.
|
||||||
|
Slow down when moving backwards.
|
||||||
|
Backward = Slow down.
|
||||||
|
Speed up when moving backwards.
|
||||||
|
Left = Rotate anticlockwise.
|
||||||
|
Right = Rotate clockwise.
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -0,0 +1,469 @@
|
||||||
|
-- Parameters
|
||||||
|
|
||||||
|
local AVIEW = false -- Autorotate view to velocity direction
|
||||||
|
local GRIP = 6 -- Maximum linear and lateral acceleration, in nodes/s^2
|
||||||
|
local SZTORQ = 16 -- Car speed where motor torque drops to zero, in nodes/s
|
||||||
|
local DRAG = 0.03 -- Air drag
|
||||||
|
local ROLRES = 0.3 -- Rolling resistence
|
||||||
|
local GRAV = 9.81 -- Acceleration of gravity, in nodes/s^2
|
||||||
|
-- Turn parameters, in radians/s or radians/s^2
|
||||||
|
local TINIT = 0.36 -- Initial turn speed on first control input
|
||||||
|
local TACC = 0.12 -- Turn acceleration on control input
|
||||||
|
local TMAX = 2.4 -- Maximum turn speed
|
||||||
|
local TDEC = 0.24 -- Turn deceleration on no control input
|
||||||
|
|
||||||
|
-- End of parameters
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Darkened", "292421", 40, 36, 33},
|
||||||
|
{"blue", "Blue", "0000FF", 0, 0, 255},
|
||||||
|
{"green", "Green", "00FF00", 0, 255, 0},
|
||||||
|
{"white", "White", "F5F5F5", 245, 245, 245},
|
||||||
|
{"orange", "Orange", "FF6103", 255, 97, 3},
|
||||||
|
{"red", "Red", "FF0000", 255, 0, 0},
|
||||||
|
{"yellow", "Yellow", "FFFF00", 255, 255, 0},
|
||||||
|
{"pink", "pink", "FF69B4", 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local name = source_list[i][1]
|
||||||
|
local description = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
-- Constants
|
||||||
|
|
||||||
|
local sztorqmf = SZTORQ - 4
|
||||||
|
|
||||||
|
|
||||||
|
-- Functions
|
||||||
|
|
||||||
|
local function get_sign(n)
|
||||||
|
if n == 0 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return n / math.abs(n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_vecmag(vec)
|
||||||
|
return math.sqrt(vec.x ^ 2 + vec.z ^ 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_theta(vec) -- returns 0 to PI * 2
|
||||||
|
if vec.z == 0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if vec.z < 0 then
|
||||||
|
return math.atan(-vec.x / vec.z) + math.pi
|
||||||
|
end
|
||||||
|
if vec.x > 0 then
|
||||||
|
return math.atan(-vec.x / vec.z) + math.pi * 2
|
||||||
|
end
|
||||||
|
return math.atan(-vec.x / vec.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_veccomp(vecmag, theta, y)
|
||||||
|
local x = -math.sin(theta) * vecmag
|
||||||
|
local z = math.cos(theta) * vecmag
|
||||||
|
return {x = x, y = y, z = z}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function wrap_yaw(yaw) -- wrap to 0 to PI * 2
|
||||||
|
local fmod = math.fmod(yaw, math.pi * 2)
|
||||||
|
if fmod < 0 then
|
||||||
|
return fmod + math.pi * 2
|
||||||
|
end
|
||||||
|
return fmod
|
||||||
|
end
|
||||||
|
|
||||||
|
local function angbet(theta1, theta2) -- theta1 relative to theta2, -PI to PI
|
||||||
|
local ang = theta1 - theta2
|
||||||
|
if ang < -math.pi then
|
||||||
|
return ang + math.pi * 2
|
||||||
|
end
|
||||||
|
if ang > math.pi then
|
||||||
|
return ang - math.pi * 2
|
||||||
|
end
|
||||||
|
return ang
|
||||||
|
end
|
||||||
|
|
||||||
|
local function add_smoke_particle(pos, player_name)
|
||||||
|
minetest.add_particle({
|
||||||
|
pos = pos,
|
||||||
|
velocity = {x = 0, y = 0, z = 0},
|
||||||
|
acceleration = {x = 0, y = 0, z = 0},
|
||||||
|
expirationtime = 0.25,
|
||||||
|
size = 2.8,
|
||||||
|
collisiondetection = false,
|
||||||
|
collision_removal = false,
|
||||||
|
vertical = false,
|
||||||
|
texture = "driftcar_smoke.png",
|
||||||
|
playername = player_name,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Entity
|
||||||
|
|
||||||
|
local car = {
|
||||||
|
initial_properties = {
|
||||||
|
physical = true,
|
||||||
|
collide_with_objects = false, -- Fixes a MT 0.4.16 engine bug
|
||||||
|
collisionbox = {-0.53, -0.75, -0.53, 0.53, 0.75, 0.53},
|
||||||
|
visual = "wielditem",
|
||||||
|
visual_size = {x = 1.0, y = 1.0}, -- Scale up of nodebox is these * 1.5
|
||||||
|
textures = {"driftcar:driftcar_nodebox" .. name},
|
||||||
|
stepheight = 0.6,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Custom fields
|
||||||
|
driver = nil,
|
||||||
|
removed = false,
|
||||||
|
rot = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
function car.on_rightclick(self, clicker)
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = clicker:get_player_name()
|
||||||
|
if self.driver and name == self.driver then
|
||||||
|
-- Detach
|
||||||
|
self.driver = nil
|
||||||
|
clicker:set_detach()
|
||||||
|
default.player_attached[name] = false
|
||||||
|
default.player_set_animation(clicker, "stand" , 30)
|
||||||
|
local pos = clicker:getpos()
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
clicker:setpos(pos)
|
||||||
|
end)
|
||||||
|
elseif not self.driver then
|
||||||
|
-- Attach
|
||||||
|
local attach = clicker:get_attach()
|
||||||
|
if attach and attach:get_luaentity() then
|
||||||
|
local luaentity = attach:get_luaentity()
|
||||||
|
if luaentity.driver then
|
||||||
|
luaentity.driver = nil
|
||||||
|
end
|
||||||
|
clicker:set_detach()
|
||||||
|
end
|
||||||
|
self.driver = name
|
||||||
|
clicker:set_attach(self.object, "",
|
||||||
|
{x = 0, y = -1, z = 0}, {x = 0, y = -1, z = 0})
|
||||||
|
default.player_attached[name] = true
|
||||||
|
minetest.after(0.2, function()
|
||||||
|
default.player_set_animation(clicker, "sit" , 30)
|
||||||
|
end)
|
||||||
|
clicker:set_look_horizontal(self.object:getyaw())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function car.on_activate(self, staticdata, dtime_s)
|
||||||
|
self.object:set_armor_groups({immortal = 1})
|
||||||
|
end
|
||||||
|
|
||||||
|
function car.on_punch(self, puncher)
|
||||||
|
if not puncher or not puncher:is_player() or self.removed then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local name = puncher:get_player_name()
|
||||||
|
if self.driver and name == self.driver then
|
||||||
|
-- Detach
|
||||||
|
self.driver = nil
|
||||||
|
puncher:set_detach()
|
||||||
|
default.player_attached[name] = false
|
||||||
|
end
|
||||||
|
if not self.driver then
|
||||||
|
-- Move to inventory
|
||||||
|
self.removed = true
|
||||||
|
local inv = puncher:get_inventory()
|
||||||
|
if not (creative and creative.is_enabled_for
|
||||||
|
and creative.is_enabled_for(name))
|
||||||
|
or not inv:contains_item("main", "driftcar:driftcar" .. name) then
|
||||||
|
|
||||||
|
end
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
self.object:remove()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function car.on_step(self, dtime)
|
||||||
|
local vel = self.object:getvelocity()
|
||||||
|
local velmag = get_vecmag(vel)
|
||||||
|
-- Early return for near-stationary vehicle with no driver
|
||||||
|
if not self.driver and velmag < 0.01 and vel.y == 0 then
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
self.object:setvelocity({x = 0, y = 0, z = 0})
|
||||||
|
self.object:setacceleration({x = 0, y = 0, z = 0})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Angle of yaw relative to velocity, -PI to PI
|
||||||
|
local yawrtvel = angbet(
|
||||||
|
wrap_yaw(self.object:getyaw()),
|
||||||
|
get_theta(vel)
|
||||||
|
)
|
||||||
|
-- Velocity component linear to car
|
||||||
|
local linvel = math.cos(yawrtvel) * velmag
|
||||||
|
-- Touch ground bool
|
||||||
|
local under_pos = self.object:getpos()
|
||||||
|
under_pos.y = under_pos.y - 1.4
|
||||||
|
local node_under = minetest.get_node(under_pos)
|
||||||
|
local nodedef_under = minetest.registered_nodes[node_under.name]
|
||||||
|
local touch = nodedef_under.walkable
|
||||||
|
|
||||||
|
-- Torque acceleration applied linear to car
|
||||||
|
local taccmag = 0
|
||||||
|
|
||||||
|
-- Controls
|
||||||
|
if self.driver and touch then
|
||||||
|
local driver_objref = minetest.get_player_by_name(self.driver)
|
||||||
|
if driver_objref then
|
||||||
|
local ctrl = driver_objref:get_player_control()
|
||||||
|
if ctrl.up or ctrl.down then
|
||||||
|
-- Torque multiplier applied above 4nps to replicate reduction of
|
||||||
|
-- motor torque with rotation speed.
|
||||||
|
local torm = 1
|
||||||
|
local abslinvel = math.abs(linvel)
|
||||||
|
if abslinvel > 4 then
|
||||||
|
torm = (SZTORQ - abslinvel) / sztorqmf
|
||||||
|
end
|
||||||
|
|
||||||
|
if ctrl.up then
|
||||||
|
taccmag = GRIP * torm
|
||||||
|
elseif ctrl.down then
|
||||||
|
taccmag = -GRIP * torm
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Player left server while driving
|
||||||
|
-- In MT 5.0.0 use 'airboat:on_detach_child()' to do this
|
||||||
|
self.driver = nil
|
||||||
|
minetest.log("warning", "[driftcar] Driver left server while" ..
|
||||||
|
" driving. This may cause some 'Pushing ObjectRef to" ..
|
||||||
|
" removed/deactivated object' warnings.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Early return for near-stationary vehicle with driver
|
||||||
|
if taccmag == 0 and velmag < 0.01 and vel.y == 0 then
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
self.object:setvelocity({x = 0, y = 0, z = 0})
|
||||||
|
self.object:setacceleration({x = 0, y = 0, z = 0})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Allows fast reduction of turn when no turn control
|
||||||
|
local noturnctrl = true
|
||||||
|
|
||||||
|
if self.driver and touch then
|
||||||
|
local driver_objref = minetest.get_player_by_name(self.driver)
|
||||||
|
if driver_objref then
|
||||||
|
local ctrl = driver_objref:get_player_control()
|
||||||
|
if ctrl.left then
|
||||||
|
if self.rot == 0 then
|
||||||
|
self.rot = TINIT
|
||||||
|
else
|
||||||
|
self.rot = self.rot + TACC
|
||||||
|
end
|
||||||
|
noturnctrl = false
|
||||||
|
elseif ctrl.right then
|
||||||
|
if self.rot == 0 then
|
||||||
|
self.rot = -TINIT
|
||||||
|
else
|
||||||
|
self.rot = self.rot - TACC
|
||||||
|
end
|
||||||
|
noturnctrl = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if AVIEW then
|
||||||
|
driver_objref:set_look_horizontal(get_theta(vel))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Player left server while driving
|
||||||
|
-- In MT 5.0.0 use 'airboat:on_detach_child()' to do this
|
||||||
|
self.driver = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If no turn control adjust turn towards zero
|
||||||
|
local sr = get_sign(self.rot)
|
||||||
|
if noturnctrl and touch then
|
||||||
|
self.rot = self.rot - TDEC * sr
|
||||||
|
if sr ~= get_sign(self.rot) then
|
||||||
|
self.rot = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Limit turn
|
||||||
|
if math.abs(self.rot) > TMAX then
|
||||||
|
self.rot = TMAX * get_sign(self.rot)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Acceleration caused by 4 Forces
|
||||||
|
|
||||||
|
-- 1. Drag is proportional to velocity, assuming laminar flow
|
||||||
|
local dragacc = vector.multiply(vel, -DRAG)
|
||||||
|
|
||||||
|
-- 2. Rolling resistence is constant
|
||||||
|
local rraccmag = 0
|
||||||
|
if touch then
|
||||||
|
if linvel > 0 then
|
||||||
|
rraccmag = -ROLRES
|
||||||
|
elseif linvel < 0 then
|
||||||
|
rraccmag = ROLRES
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--local rracc = get_veccomp(rraccmag, self.object:getyaw(), 0)
|
||||||
|
|
||||||
|
-- 3. Wheel torque acceleration
|
||||||
|
--local tacc = get_veccomp(taccmag, self.object:getyaw(), 0)
|
||||||
|
|
||||||
|
-- Combine taccmag and rraccmag since same direction
|
||||||
|
local trracc = get_veccomp(taccmag + rraccmag, self.object:getyaw(), 0)
|
||||||
|
|
||||||
|
-- 4. Tire lateral friction
|
||||||
|
-- Velocity component lateral to car
|
||||||
|
local tlfacc = {x = 0, y = 0, z = 0}
|
||||||
|
if touch then
|
||||||
|
local latvel = math.sin(yawrtvel) * velmag
|
||||||
|
local tlfaccmag = math.min(math.max(latvel * 32, -GRIP), GRIP)
|
||||||
|
tlfacc = get_veccomp(tlfaccmag, self.object:getyaw() + math.pi / 2, 0)
|
||||||
|
|
||||||
|
-- Tire smoke
|
||||||
|
if self.driver and math.random() < -0.05 + math.abs(latvel) / 30 then
|
||||||
|
local opos = self.object:getpos()
|
||||||
|
opos.y = opos.y - 0.5
|
||||||
|
local yaw = self.object:getyaw()
|
||||||
|
local yaw1 = yaw + math.pi * 0.25
|
||||||
|
local yaw2 = yaw + math.pi * 0.75
|
||||||
|
|
||||||
|
local srcomp1x = -math.sin(yaw1)
|
||||||
|
local srcomp1z = math.cos(yaw1)
|
||||||
|
local srcomp2x = -math.sin(yaw2)
|
||||||
|
local srcomp2z = math.cos(yaw2)
|
||||||
|
|
||||||
|
add_smoke_particle({
|
||||||
|
x = opos.x + srcomp1x,
|
||||||
|
y = opos.y,
|
||||||
|
z = opos.z + srcomp1z
|
||||||
|
}, self.driver)
|
||||||
|
add_smoke_particle({
|
||||||
|
x = opos.x - srcomp1x,
|
||||||
|
y = opos.y,
|
||||||
|
z = opos.z - srcomp1z
|
||||||
|
}, self.driver)
|
||||||
|
add_smoke_particle({
|
||||||
|
x = opos.x + srcomp2x,
|
||||||
|
y = opos.y,
|
||||||
|
z = opos.z + srcomp2z
|
||||||
|
}, self.driver)
|
||||||
|
add_smoke_particle({
|
||||||
|
x = opos.x - srcomp2x,
|
||||||
|
y = opos.y,
|
||||||
|
z = opos.z - srcomp2z
|
||||||
|
}, self.driver)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local new_acc = {
|
||||||
|
x = trracc.x + dragacc.x + tlfacc.x,
|
||||||
|
y = trracc.y + dragacc.y + tlfacc.y - GRAV,
|
||||||
|
z = trracc.z + dragacc.z + tlfacc.z,
|
||||||
|
}
|
||||||
|
-- Turn multiplier
|
||||||
|
local turm = 1
|
||||||
|
-- Reduce turn below 4nps
|
||||||
|
if velmag < 4 then
|
||||||
|
turm = velmag / 4
|
||||||
|
end
|
||||||
|
-- Limit dtime to avoid too much turn
|
||||||
|
dtime = math.min(dtime, 0.2)
|
||||||
|
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
self.object:setvelocity(self.object:getvelocity())
|
||||||
|
self.object:setacceleration(new_acc)
|
||||||
|
self.object:setyaw(wrap_yaw(self.object:getyaw() + self.rot * dtime * turm))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Register entity
|
||||||
|
|
||||||
|
minetest.register_entity("driftcar:driftcar" .. name, car)
|
||||||
|
|
||||||
|
-- Craftitem
|
||||||
|
|
||||||
|
minetest.register_craftitem("driftcar:driftcar" .. name, {
|
||||||
|
description = "Drift Car" .. name,
|
||||||
|
inventory_image = "cars.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "none.png",
|
||||||
|
wield_scale = {x = 2, y = 2, z = 2},
|
||||||
|
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local node = minetest.get_node(under)
|
||||||
|
local udef = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
|
-- Run any on_rightclick function of pointed node instead
|
||||||
|
if udef and udef.on_rightclick and
|
||||||
|
not (placer and placer:is_player() and
|
||||||
|
placer:get_player_control().sneak) then
|
||||||
|
return udef.on_rightclick(under, node, placer, itemstack,
|
||||||
|
pointed_thing) or itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
if pointed_thing.type ~= "node" then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
pointed_thing.under.y = pointed_thing.under.y + 1.25
|
||||||
|
local car = minetest.add_entity(pointed_thing.under,
|
||||||
|
"driftcar:driftcar" .. name)
|
||||||
|
if car then
|
||||||
|
if placer then
|
||||||
|
car:setyaw(placer:get_look_horizontal())
|
||||||
|
end
|
||||||
|
local player_name = placer and placer:get_player_name() or ""
|
||||||
|
if not (creative and creative.is_enabled_for and
|
||||||
|
creative.is_enabled_for(player_name)) then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- Nodebox
|
||||||
|
|
||||||
|
minetest.register_node("driftcar:driftcar_nodebox" ..name, {
|
||||||
|
description = "Drift Car Nodebox" ..name,
|
||||||
|
tiles = { -- Top, base, right, left, front, back
|
||||||
|
"driftcar_top.png^[colorize:#"..colour..":70",
|
||||||
|
"driftcar_base.png^[colorize:#"..colour..":70",
|
||||||
|
"driftcar_right.png^[colorize:#"..colour..":70",
|
||||||
|
"driftcar_left.png^[colorize:#"..colour..":70",
|
||||||
|
"driftcar_front.png^[colorize:#"..colour..":70",
|
||||||
|
"driftcar_back.png^[colorize:#"..colour..":70",
|
||||||
|
},
|
||||||
|
paramtype = "light",
|
||||||
|
drawtype = "nodebox",
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = { -- Widmin, heimin, lenmin, widmax, heimax, lenmax
|
||||||
|
{-0.5, 0.125, -0.5, 0.5, 0.5, 0.4375}, -- Upper
|
||||||
|
{-0.5, -0.375, -0.5, 0.5, 0.125, 0.5}, -- Lower
|
||||||
|
{-0.5, -0.5, -0.5, -0.3125, -0.375, -0.1875}, -- Wheels
|
||||||
|
{0.3125, -0.5, -0.5, 0.5, -0.375, -0.1875},
|
||||||
|
{-0.5, -0.5, 0.1875, -0.3125, -0.375, 0.5},
|
||||||
|
{0.3125, -0.5, 0.1875, 0.5, -0.375, 0.5},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
groups = {not_in_creative_inventory = 1},
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,61 @@
|
||||||
|
License of source code
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (C) 2018 paramat
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
|
||||||
|
License of media (textures)
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
|
Copyright (C) 2018 paramat
|
||||||
|
|
||||||
|
You are free to:
|
||||||
|
|
||||||
|
Share — copy and redistribute the material in any medium or format
|
||||||
|
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
|
||||||
|
|
||||||
|
The licensor cannot revoke these freedoms as long as you follow the license terms.
|
||||||
|
|
||||||
|
Under the following terms:
|
||||||
|
|
||||||
|
Attribution — You must give appropriate credit, provide a link to the license, and
|
||||||
|
indicate if changes were made. You may do so in any reasonable manner, but not in any way
|
||||||
|
that suggests the licensor endorses you or your use.
|
||||||
|
|
||||||
|
ShareAlike — If you remix, transform, or build upon the material, you must distribute
|
||||||
|
your contributions under the same license as the original.
|
||||||
|
|
||||||
|
No additional restrictions — You may not apply legal terms or technological measures that
|
||||||
|
legally restrict others from doing anything the license permits.
|
||||||
|
|
||||||
|
Notices:
|
||||||
|
|
||||||
|
You do not have to comply with the license for elements of the material in the public
|
||||||
|
domain or where your use is permitted by an applicable exception or limitation.
|
||||||
|
No warranties are given. The license may not give you all of the permissions necessary
|
||||||
|
for your intended use. For example, other rights such as publicity, privacy, or moral
|
||||||
|
rights may limit how you use the material.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
http://creativecommons.org/licenses/by-sa/3.0/
|
|
@ -0,0 +1 @@
|
||||||
|
name = driftcar
|
After Width: | Height: | Size: 158 B |
After Width: | Height: | Size: 208 B |
After Width: | Height: | Size: 146 B |
After Width: | Height: | Size: 204 B |
After Width: | Height: | Size: 202 B |
After Width: | Height: | Size: 96 B |
After Width: | Height: | Size: 102 B |
|
@ -0,0 +1,125 @@
|
||||||
|
# Minetest mod: Flying Carpet
|
||||||
|
by Wuzzy
|
||||||
|
|
||||||
|
Version: 0.6.0
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
Quickly explore the vast terrain with the magical flying carpet. But only the skilled users can master its speed, the fools will crash and hurt themselves.
|
||||||
|
|
||||||
|
The carpet flies fast horizontally, but very slowly is it able to move vertically. It constantly reduces your mana resources (if Mana mod is enabled) and will wear out over time.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
The mod does not depend on anything but it adds some features if certain mods
|
||||||
|
are available:
|
||||||
|
|
||||||
|
* `default` and `wool` (in Minetest Game): Adds a crafting recipe
|
||||||
|
* `mana`: Using the flying carpet costs mana
|
||||||
|
* `doc_items`: Adds in-game help for the flying carpet
|
||||||
|
* `doc_identifier`: Support for the lookup tool
|
||||||
|
|
||||||
|
Obtaining
|
||||||
|
---------
|
||||||
|
In Minetest Game (and most similar subgames), you can craft the flying carpet using the
|
||||||
|
following recipe:
|
||||||
|
|
||||||
|
Red Wool, Yellow Wool, Red Wool
|
||||||
|
Mese Crystal, Gold Ingot, Mese Crystal
|
||||||
|
|
||||||
|
In MineClone 2, replace the mese cystals with redstone.
|
||||||
|
|
||||||
|
Subgames other than Minetest Game *might* work if they have been forked from it.
|
||||||
|
If you use an entirely different subgame, you might be able to obtain it in a different
|
||||||
|
way provided by the subgame. If all else fails, you can obtain it by “cheating”, using
|
||||||
|
the server command “`/giveme flying_carpet:carpet`” (requires “`give`” privilege).
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
Look to the desired initial flight direction and place the carpet on any flat surface which is not inside a liquid. Make sure it has enough space (3×2×3), then place it.
|
||||||
|
|
||||||
|
Right-click the carpet to sit on it and depart. Note you can not enter the flying carpet if you are currently in any other vehicle (e.g. boat).
|
||||||
|
You can also not enter a flying carpet if it is going fast.
|
||||||
|
|
||||||
|
The flying carpet has a basic movement speed which the flying carpet is aiming to reach; thus, the carpet flies without your intervention. Use the speed keys to change the speed for a while; they apply only for as long as you hold down the keys. As soon as you release the keys, the carpet will go back to its basic speed again.
|
||||||
|
|
||||||
|
Flying the carpet is a bit tricky, because it flies fast, you can't fully brake and the turning speed is rather low. Be careful not to crash into the landscape!
|
||||||
|
|
||||||
|
If the carpet is under a certain critical speed, it loses its magic and just drops on the ground.
|
||||||
|
There is a short “grace period” at the beginning of the flight where this minimum speed limit does not apply.
|
||||||
|
You can tell by the color of the particles emitted by the flying carpet whether you are critically slow. If the particles are yellow, everything is okay,
|
||||||
|
but if they become red this means the carpet is going dangerously slow and you should speed up; if you slow down even more you might risk for the flying carpet
|
||||||
|
to fail.
|
||||||
|
|
||||||
|
The flying carpet also fails immediately if you crash into the landscape.
|
||||||
|
If you crash while being fast, you may also take damage. There is also fall damage, but with the carpet it is greatly reduced compared to a “normal” drop.
|
||||||
|
Your carpet will also stop working if your mana resources are depleted (only if Mana mod is installed and active).
|
||||||
|
When your carpet stopped working, you have to collect the carpet (punch it) and place it again.
|
||||||
|
|
||||||
|
If you fly directly down onto a flat solid ground, your flying carpet will come to a halt quickly due to
|
||||||
|
friction.
|
||||||
|
|
||||||
|
Your carpet can not fly into liquids from above, but it can fly into them from the side or even below.
|
||||||
|
But the speed in liquids is greatly reduced and your carpet will likely fail.
|
||||||
|
|
||||||
|
## Long-term usage
|
||||||
|
Your carpet is not indestructible! Long flights, scratching and crashes will wear out the carpet over
|
||||||
|
time and it might get destroyed eventually.
|
||||||
|
|
||||||
|
Crash-landing at high speeds will deal major damage, so you should avoid crashing at all costs.
|
||||||
|
Sliding on the surface will deal a minor wear but it is often negligible.
|
||||||
|
|
||||||
|
A constant wear is also caused by flying, but very slowly.
|
||||||
|
|
||||||
|
If you always fly perfectly, you could use a single flying carpet for about 12 hours. Fly safe to make
|
||||||
|
the most of your flying carpet!
|
||||||
|
|
||||||
|
On high wear levels, the carpet will emit black particles behind it which will increase in number
|
||||||
|
with its wear. As long there are only a few black particles, you're still good as long as you don't
|
||||||
|
crash-land. You should get a replacement soon. If the number of black particles is about the
|
||||||
|
same as the yellow/red particles, the wear has reached a very high level.
|
||||||
|
|
||||||
|
On a critical wear level, the carpet will emit a very annoying loud noise while flying. This is the final
|
||||||
|
warning, you will have roughly five minutes worth of flight until the carpet finally disintegrates under
|
||||||
|
your feet! You should land as soon as possible.
|
||||||
|
|
||||||
|
Additionally, a flying carpet will disintegrate and is lost forever if it stands still and has no user
|
||||||
|
for 1 minute.
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
* Up: Hold down to speed up
|
||||||
|
* Down: Hold down to slow down
|
||||||
|
* Left: Turn left
|
||||||
|
* Right: Turn right
|
||||||
|
* Jump: Ascend
|
||||||
|
* Sneak: Descend
|
||||||
|
* Right click carpet: Sit on carpet / Get off the carpet
|
||||||
|
* Punch carpet:
|
||||||
|
* While flying: Stop flying immediately
|
||||||
|
* While not flying: Take it
|
||||||
|
|
||||||
|
Note: Collecting and entering a flying carpet is not possible while it is moving fast.
|
||||||
|
|
||||||
|
## Licenses
|
||||||
|
This mod free software.
|
||||||
|
|
||||||
|
### License of source code
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
### Authors and licenses of media files
|
||||||
|
- `flying_carpet_model.obj`: Wuzzy, MIT License
|
||||||
|
- `flying_carpet_flight.ogg`: MIT License
|
||||||
|
- `flying_carpet_out_of_energy.ogg`: by p0ss, CC BY-SA 3.0
|
||||||
|
- `flying_carpet_almost_dead.ogg`: by John, MIT License
|
||||||
|
- `flying_carpet_place.ogg`: Unknown authors and Wuzzy (compilation of Public Domain sounds), MIT License
|
||||||
|
- `flying_carpet_take.ogg`: Julien Matthey, modified by Wuzzy, MIT License
|
||||||
|
- `flying_carpet_surface.png`: Roman Zacharij and Wuzzy, MIT License
|
||||||
|
- `flying_carpet_wield.png`: Roman Zacharij and Wuzzy, MIT License
|
||||||
|
- `flying_carpet_inventory.png`: Roman Zacharij and Wuzzy, MIT License
|
||||||
|
- `flying_carpet_slide.ogg`: crcavol, MIT License
|
||||||
|
- `flying_carpet_magic_smoke.png`: Wuzzy, MIT License
|
||||||
|
- `flying_carpet_smoke.png.png`: Wuzzy. MIT License
|
||||||
|
- `flying_carpet_star.png`: Wuzzy, MIT License
|
||||||
|
- `flying_carpet_star_warning.png`: Wuzzy, MIT License
|
||||||
|
- `flying_carpet_star_death_warning.png`: Wuzzy, MIT License
|
||||||
|
- `flying_carpet_death.png`: Wuzzy, MIT License
|
||||||
|
|
||||||
|
### License references
|
||||||
|
* [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
|
|
@ -0,0 +1,7 @@
|
||||||
|
hotairballoon = {}
|
||||||
|
|
||||||
|
--If you want to be available only through /giveme or at admin shops, set this to false.
|
||||||
|
hotairballoon.crafts = true
|
||||||
|
|
||||||
|
--If you want to be only one use, set this to true.
|
||||||
|
hotairballoon.one_use = false
|
|
@ -0,0 +1,187 @@
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1, 40, 36, 33},
|
||||||
|
{"blue", "Color2", color2, 0, 0, 255},
|
||||||
|
{"green", "Color3", color3, 0, 255, 0},
|
||||||
|
{"white", "Color4", color4, 245, 245, 245},
|
||||||
|
{"orange", "Color5", color5, 255, 97, 3},
|
||||||
|
{"red", "Color6", color6, 255, 0, 0},
|
||||||
|
{"yellow", "Color7", color7, 255, 255, 0},
|
||||||
|
{"pink", "Color8", color8, 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
dofile(minetest.get_modpath("hotairballoon") .. "/config.lua")
|
||||||
|
|
||||||
|
local function get_sign(i)
|
||||||
|
if i == 0 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return i/math.abs(i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local carpet = {
|
||||||
|
physical = true,
|
||||||
|
collisionbox = {-.99,-0.1,-.99, .99,0.5,.99},
|
||||||
|
collide_with_objects = true,
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "hotair.b3d",
|
||||||
|
textures = {"hotair_w.png^[colorize:#"..colour..":70"},
|
||||||
|
driver = nil,
|
||||||
|
yaw=0,
|
||||||
|
vx=0,
|
||||||
|
vy=0,
|
||||||
|
vz=0,
|
||||||
|
}
|
||||||
|
|
||||||
|
function carpet:on_rightclick(clicker)
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = clicker:get_player_name()
|
||||||
|
if self.driver and clicker == self.driver then
|
||||||
|
clicker:set_detach()
|
||||||
|
self.driver = nil
|
||||||
|
default.player_attached[name] = false
|
||||||
|
default.player_set_animation(clicker, "stand" , 10)
|
||||||
|
if hotairballoon.one_use == true then
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
elseif not self.driver then
|
||||||
|
self.driver = clicker
|
||||||
|
clicker:set_attach(self.object, "", {x=-4,y=10.1,z=0}, {x=0,y=90,z=0})
|
||||||
|
default.player_attached[name] = true
|
||||||
|
minetest.after(0.2, function()
|
||||||
|
default.player_set_animation(clicker, "sit" , 10)
|
||||||
|
end)
|
||||||
|
self.object:setyaw(clicker:get_look_yaw()-math.pi/2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function carpet:on_activate(staticdata, dtime_s)
|
||||||
|
self.object:set_armor_groups({immortal = 1})
|
||||||
|
if staticdata then
|
||||||
|
self.v = tonumber(staticdata)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function carpet:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
||||||
|
if not self.driver then self.object:remove() end
|
||||||
|
if puncher and puncher:is_player() and not self.driver and not minetest.setting_getbool("creative_mode") then
|
||||||
|
puncher:get_inventory():add_item("main", "hotairballoon:hotair" .. color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function carpet:on_step(dtime)
|
||||||
|
if self.driver then
|
||||||
|
self.yaw = self.driver:get_look_yaw()
|
||||||
|
local yaw = self.object:getyaw()
|
||||||
|
self.vx = self.object:getvelocity().x
|
||||||
|
self.vy = self.object:getvelocity().y
|
||||||
|
self.vz = self.object:getvelocity().z
|
||||||
|
local ctrl = self.driver:get_player_control()
|
||||||
|
--Forward/backward
|
||||||
|
if ctrl.up then
|
||||||
|
self.vx = self.vx + math.cos(yaw)*0.4
|
||||||
|
self.vz = self.vz + math.sin(yaw)*0.4
|
||||||
|
end
|
||||||
|
if ctrl.down then
|
||||||
|
self.vx = self.vx-math.cos(yaw)*0.4
|
||||||
|
self.vz = self.vz-math.sin(yaw)*0.4
|
||||||
|
end
|
||||||
|
--Left/right
|
||||||
|
if ctrl.left then
|
||||||
|
self.object:setyaw(self.object:getyaw()+math.pi/60+dtime*math.pi/60)
|
||||||
|
end
|
||||||
|
if ctrl.right then
|
||||||
|
self.object:setyaw(self.object:getyaw()-math.pi/60-dtime*math.pi/60)
|
||||||
|
end
|
||||||
|
--up/down
|
||||||
|
if ctrl.jump then
|
||||||
|
if self.vy < 1.5 then
|
||||||
|
self.vy = self.vy+0.3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ctrl.sneak then
|
||||||
|
if self.vy>-1.5 then
|
||||||
|
self.vy = self.vy-0.6
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--
|
||||||
|
end
|
||||||
|
if self.vx==0 and self.vz==0 and self.vy==0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--Decelerating
|
||||||
|
local sx=get_sign(self.vx)
|
||||||
|
self.vx = self.vx - 0.02*sx
|
||||||
|
local sz=get_sign(self.vz)
|
||||||
|
self.vz = self.vz - 0.02*sz
|
||||||
|
local sy=get_sign(self.vy)
|
||||||
|
self.vy = self.vy-0.01*sy
|
||||||
|
|
||||||
|
--Stop
|
||||||
|
if sx ~= get_sign(self.vx) then
|
||||||
|
self.vx = 0
|
||||||
|
end
|
||||||
|
if sz ~= get_sign(self.vz) then
|
||||||
|
self.vz = 0
|
||||||
|
end
|
||||||
|
if sy ~= get_sign(self.vy) then
|
||||||
|
self.vy = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--Speed limit
|
||||||
|
if math.abs(self.vx) > 87 then
|
||||||
|
self.vx = 87*get_sign(self.vx)
|
||||||
|
end
|
||||||
|
if math.abs(self.vz) > 87 then
|
||||||
|
self.vz = 87*get_sign(self.vz)
|
||||||
|
end
|
||||||
|
if math.abs(self.vy) > 87 then
|
||||||
|
self.vz = 87*get_sign(self.vy)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.object:setvelocity({x=self.vx, y=self.vy,z=self.vz})
|
||||||
|
end
|
||||||
|
minetest.register_entity("hotairballoon:hotair" .. color , carpet)
|
||||||
|
|
||||||
|
minetest.register_craftitem("hotairballoon:hotair" .. color, {
|
||||||
|
description = color .."Hot Air Balloon",
|
||||||
|
inventory_image = "hotair_inv.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "none.png",
|
||||||
|
liquids_pointable = false,
|
||||||
|
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
if pointed_thing.type ~= "node" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if minetest.get_node(pointed_thing.above).name ~= "air" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
pointed_thing.under.y = pointed_thing.under.y + 1
|
||||||
|
minetest.add_entity(pointed_thing.under, "hotairballoon:hotair" .. color)
|
||||||
|
if not minetest.setting_getbool("creative_mode") then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
After Width: | Height: | Size: 128 B |
After Width: | Height: | Size: 5.3 KiB |
|
@ -0,0 +1,15 @@
|
||||||
|
Hovercraft for Minetest [hovercraft]
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Source Code: Copyright (C) 2013 Stuart Jones - LGPL
|
||||||
|
|
||||||
|
Tetxures: Copyright (C) 2013 Stuart Jones - CC-BY-SA
|
||||||
|
|
||||||
|
Models: Copyright (C) 2013 Stuart Jones - CC-BY-SA
|
||||||
|
|
||||||
|
Sounds: freesound.org
|
||||||
|
|
||||||
|
Rocket Boost Engine Loop by qubodup - CC0
|
||||||
|
CARTOON-BING-LOW by kantouth - CC-BY-3.0
|
||||||
|
All other sounds: Copyright Stuart Jones - CC-BY-SA
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
Hovercraft for Minetest [hovercraft]
|
||||||
|
====================================
|
||||||
|
|
||||||
|
A fun alternative mode of transport for Minetest.
|
||||||
|
|
||||||
|
Controls
|
||||||
|
========
|
||||||
|
|
||||||
|
Forward (W) Thrust
|
||||||
|
Jump (Space) Jump
|
||||||
|
Mouse Move Rotate
|
||||||
|
Sneak (Shift) Sit (only visible in multiplayer)
|
||||||
|
|
||||||
|
Know Issues
|
||||||
|
===========
|
||||||
|
|
||||||
|
'Bouncing' into thin air: This can simply be the result of server lag,
|
||||||
|
even in singleplayer mode, the client and server can get out of sync.
|
||||||
|
Solution, be patient, allow the environment to fully load before preceding.
|
||||||
|
|
||||||
|
Problems with bouncing in air and generally getting stuck, being pulled
|
||||||
|
underwater and all manner of other weirdness can also be caused by a rather
|
||||||
|
nasty entity duplication bug in minetest itself. The only solution here is
|
||||||
|
to track down and remove any duplicate entities or by running /clearobjects
|
||||||
|
|
||||||
|
Entity Duplication: See above. This usually occurs when you move a given
|
||||||
|
distance from where the entity was originally placed. The only solution
|
||||||
|
right now is to restrict the hovercraft to a certain area. For example,
|
||||||
|
create a sunken race track the hovercraft cannot physically escape from.
|
|
@ -0,0 +1,2 @@
|
||||||
|
default
|
||||||
|
color
|
|
@ -0,0 +1,184 @@
|
||||||
|
hover = {}
|
||||||
|
|
||||||
|
function hover:register_hovercraft(name, def)
|
||||||
|
minetest.register_entity(name, {
|
||||||
|
wield_image = "none.png",
|
||||||
|
physical = true,
|
||||||
|
collisionbox = {-0.8,0,-0.8, 0.8,1.2,0.8},
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "hovercraft.x",
|
||||||
|
textures = def.textures,
|
||||||
|
max_speed = def.max_speed,
|
||||||
|
acceleration = def.acceleration,
|
||||||
|
deceleration = def.deceleration,
|
||||||
|
jump_velocity = def.jump_velocity,
|
||||||
|
fall_velocity = def.fall_velocity,
|
||||||
|
bounce = def.bounce,
|
||||||
|
player = nil,
|
||||||
|
sound = nil,
|
||||||
|
thrust = 0,
|
||||||
|
velocity = {x=0, y=0, z=0},
|
||||||
|
last_pos = {x=0, y=0, z=0},
|
||||||
|
timer = 0,
|
||||||
|
on_activate = function(self, staticdata, dtime_s)
|
||||||
|
self.object:set_armor_groups({immortal=1})
|
||||||
|
self.object:set_animation({x=0, y=24}, 30)
|
||||||
|
end,
|
||||||
|
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||||
|
if self.player then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.sound then
|
||||||
|
minetest.sound_stop(self.sound)
|
||||||
|
end
|
||||||
|
self.object:remove()
|
||||||
|
if puncher and puncher:is_player() then
|
||||||
|
puncher:get_inventory():add_item("main", name)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_rightclick = function(self, clicker)
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
if self.player and clicker == self.player then
|
||||||
|
if self.sound then
|
||||||
|
minetest.sound_stop(self.sound)
|
||||||
|
minetest.sound_play("hovercraft_thrust_fade", {object = self.object})
|
||||||
|
self.sound = nil
|
||||||
|
end
|
||||||
|
self.thrust = 0
|
||||||
|
self.player = nil
|
||||||
|
self.object:set_animation({x=0, y=0}, 30)
|
||||||
|
clicker:set_animation({x=0, y=0})
|
||||||
|
clicker:set_detach()
|
||||||
|
elseif not self.player then
|
||||||
|
self.player = clicker
|
||||||
|
clicker:set_attach(self.object, "", {x=-2,y=16.5,z=0}, {x=0,y=90,z=0})
|
||||||
|
clicker:set_animation({x=81, y=81})
|
||||||
|
local yaw = clicker:get_look_yaw()
|
||||||
|
self.object:setyaw(yaw)
|
||||||
|
self.yaw = yaw
|
||||||
|
pos.y = pos.y + 0.5
|
||||||
|
minetest.sound_play("hovercraft_jump", {object = self.object})
|
||||||
|
self.object:set_animation({x=0, y=0})
|
||||||
|
end
|
||||||
|
self.last_pos = vector.new(pos)
|
||||||
|
self.object:setpos(pos)
|
||||||
|
end,
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
self.timer = self.timer + dtime
|
||||||
|
if self.player then
|
||||||
|
local yaw = self.player:get_look_yaw()
|
||||||
|
if not yaw then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.object:setyaw(yaw)
|
||||||
|
local ctrl = self.player:get_player_control()
|
||||||
|
if ctrl.up then
|
||||||
|
if self.thrust < self.max_speed then
|
||||||
|
self.thrust = self.thrust + self.acceleration
|
||||||
|
end
|
||||||
|
local velocity = hover:get_velocity(self.thrust, self.velocity.y, 0, yaw)
|
||||||
|
if velocity.x <= self.velocity.x - self.acceleration then
|
||||||
|
self.velocity.x = self.velocity.x - self.acceleration
|
||||||
|
elseif velocity.x >= self.velocity.x + self.acceleration then
|
||||||
|
self.velocity.x = self.velocity.x + self.acceleration
|
||||||
|
end
|
||||||
|
if velocity.z <= self.velocity.z - self.acceleration then
|
||||||
|
self.velocity.z = self.velocity.z - self.acceleration
|
||||||
|
elseif velocity.z >= self.velocity.z + self.acceleration then
|
||||||
|
self.velocity.z = self.velocity.z + self.acceleration
|
||||||
|
end
|
||||||
|
if not self.sound then
|
||||||
|
self.object:set_animation({x=25, y=75}, 30)
|
||||||
|
self.sound = minetest.sound_play("hovercraft_thrust_loop", {
|
||||||
|
object = self.object,
|
||||||
|
loop = true,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
elseif self.thrust > 0 then
|
||||||
|
self.thrust = self.thrust - 0.1
|
||||||
|
if self.sound then
|
||||||
|
minetest.sound_stop(self.sound)
|
||||||
|
minetest.sound_play("hovercraft_thrust_fade", {object = self.object})
|
||||||
|
self.sound = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.object:set_animation({x=0, y=0})
|
||||||
|
self.thrust = 0
|
||||||
|
end
|
||||||
|
if ctrl.jump and self.velocity.y == 0 then
|
||||||
|
self.velocity.y = self.jump_velocity
|
||||||
|
self.timer = 0
|
||||||
|
minetest.sound_play("hovercraft_jump", {object = self.object})
|
||||||
|
end
|
||||||
|
if ctrl.sneak then
|
||||||
|
self.player:set_animation({x=81, y=81})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
if self.timer > 0.5 then
|
||||||
|
local node = minetest.env:get_node({x=pos.x, y=pos.y-0.5, z=pos.z})
|
||||||
|
if node.name == "air" or node.name == "ignore" then
|
||||||
|
self.velocity.y = 0 - self.fall_velocity
|
||||||
|
else
|
||||||
|
self.velocity.y = 0
|
||||||
|
pos.y = math.floor(pos.y) + 0.5
|
||||||
|
self.object:setpos(pos)
|
||||||
|
end
|
||||||
|
self.timer = 0
|
||||||
|
end
|
||||||
|
if self.last_pos.x == pos.x and math.abs(self.velocity.x) > 0.5 then
|
||||||
|
self.velocity.x = self.velocity.x * (0 - self.bounce)
|
||||||
|
self.thrust = 0
|
||||||
|
minetest.sound_play("hovercraft_bounce", {object = self.object})
|
||||||
|
end
|
||||||
|
if self.last_pos.z == pos.z and math.abs(self.velocity.z) > 0.5 then
|
||||||
|
self.velocity.z = self.velocity.z * (0 - self.bounce)
|
||||||
|
self.thrust = 0
|
||||||
|
minetest.sound_play("hovercraft_bounce", {object = self.object})
|
||||||
|
end
|
||||||
|
self.last_pos = vector.new(pos)
|
||||||
|
if self.thrust < 1 then
|
||||||
|
if self.velocity.x > self.deceleration then
|
||||||
|
self.velocity.x = self.velocity.x - self.deceleration
|
||||||
|
elseif self.velocity.x < 0 - self.deceleration then
|
||||||
|
self.velocity.x = self.velocity.x + self.deceleration
|
||||||
|
else
|
||||||
|
self.velocity.x = 0
|
||||||
|
end
|
||||||
|
if self.velocity.z > self.deceleration then
|
||||||
|
self.velocity.z = self.velocity.z - self.deceleration
|
||||||
|
elseif self.velocity.z < 0 - self.deceleration then
|
||||||
|
self.velocity.z = self.velocity.z + self.deceleration
|
||||||
|
else
|
||||||
|
self.velocity.z = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.object:setvelocity(self.velocity)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_craftitem(name, {
|
||||||
|
description = def.description,
|
||||||
|
wield_image = "none.png",
|
||||||
|
inventory_image = def.inventory_image,
|
||||||
|
liquids_pointable = true,
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
if pointed_thing.type ~= "node" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
pointed_thing.under.y = pointed_thing.under.y + 0.5
|
||||||
|
minetest.env:add_entity(pointed_thing.under, name)
|
||||||
|
itemstack:take_item()
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function hover:get_velocity(vx, vy, vz, yaw)
|
||||||
|
local x = math.cos(yaw) * vx + math.cos(math.pi / 2 + yaw) * vz
|
||||||
|
local z = math.sin(yaw) * vx + math.sin(math.pi / 2 + yaw) * vz
|
||||||
|
return {x=x, y=vy, z=z}
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1, 40, 36, 33},
|
||||||
|
{"blue", "Color2", color2, 0, 0, 255},
|
||||||
|
{"green", "Color3", color3, 0, 255, 0},
|
||||||
|
{"white", "Color4", color4, 245, 245, 245},
|
||||||
|
{"orange", "Color5", color5, 255, 97, 3},
|
||||||
|
{"red", "Color6", color6, 255, 0, 0},
|
||||||
|
{"yellow", "Color7", color7, 255, 255, 0},
|
||||||
|
{"pink", "Color8", color8, 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
dofile(minetest.get_modpath("hovercraft").."/hover.lua")
|
||||||
|
|
||||||
|
hover:register_hovercraft("hovercraft:hover_" .. color,{
|
||||||
|
description = color .."Hovercraft",
|
||||||
|
textures = {"hovercraft.png^[colorize:#"..colour..":70"},
|
||||||
|
wield_image = "none.png",
|
||||||
|
inventory_image = "hovercraft_inv.png^[colorize:#"..colour..":70",
|
||||||
|
max_speed = 10,
|
||||||
|
acceleration = 0.25,
|
||||||
|
deceleration = 0.05,
|
||||||
|
jump_velocity = 4.0,
|
||||||
|
fall_velocity = 1.0,
|
||||||
|
bounce = 0.5,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
After Width: | Height: | Size: 620 B |
After Width: | Height: | Size: 184 B |
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
Spaceship'Mod by Mrchiantos
|
||||||
|
|
||||||
|
spaceship'Model by Viktor Hahn (Viktor.Hahn@web.de)
|
||||||
|
airboat 0.1.8 by paramat
|
||||||
|
|
||||||
|
For Minetest 0.4.16 and later. Compatible with MT 5.0.0-dev.
|
||||||
|
Depends: default
|
||||||
|
|
||||||
|
Licenses
|
||||||
|
--------
|
||||||
|
Source code: MIT
|
||||||
|
Spaceship Model : CC By 3.0
|
||||||
|
Media (textures and nodebox design): CC0 1.0
|
||||||
|
|
||||||
|
Note about textures and crafting
|
||||||
|
--------------------------------
|
||||||
|
This mod is fully functional but does not currently have a crafting recipe or
|
||||||
|
detailed textures. The textures are templates for you to add detail to.
|
||||||
|
The airboat is available in the creative inventory or by using the /giveme chat
|
||||||
|
command.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
Third-person camera mode is recommended when travelling for a better view.
|
||||||
|
The airboat can be placed on any node, including liquids. It can land on, and
|
||||||
|
will float in, a liquid.
|
||||||
|
|
||||||
|
Controls
|
||||||
|
--------
|
||||||
|
Right mouse button = Enter or exit airboat when pointing at airboat.
|
||||||
|
Forward = Speed up.
|
||||||
|
Slow down when moving backwards.
|
||||||
|
Forward + backward = Enable cruise mode: Airboat will accelerate to maximum
|
||||||
|
forward speed and remain at that speed without needing to
|
||||||
|
hold the forward key.
|
||||||
|
Backward = Slow down.
|
||||||
|
Speed up when moving backwards.
|
||||||
|
Disable cruise mode.
|
||||||
|
Left = Turn left.
|
||||||
|
Right = Turn right.
|
||||||
|
Jump/up = Ascend.
|
||||||
|
Sneak/down = Descend.
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -0,0 +1,294 @@
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Darkened", "292421"},
|
||||||
|
{"blue", "Blue", "0000FF"},
|
||||||
|
{"green", "Green", "00FF00"},
|
||||||
|
{"white", "White", "F5F5F5"},
|
||||||
|
{"orange", "Orange", "FF6103"},
|
||||||
|
{"red", "Red", "FF0000"},
|
||||||
|
{"yellow", "Yellow", "FFFF00"},
|
||||||
|
{"pink", "pink", "FF69B4"}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local description = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
|
||||||
|
-- Functions
|
||||||
|
|
||||||
|
local function get_sign(i)
|
||||||
|
if i == 0 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return i / math.abs(i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_velocity(v, yaw, y)
|
||||||
|
local x = -math.sin(yaw) * v
|
||||||
|
local z = math.cos(yaw) * v
|
||||||
|
return {x = x, y = y, z = z}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_v(v)
|
||||||
|
return math.sqrt(v.x ^ 2 + v.z ^ 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Spaceship entity
|
||||||
|
|
||||||
|
local spaceship = {
|
||||||
|
initial_properties = {
|
||||||
|
physical = true,
|
||||||
|
collide_with_objects = false, -- Workaround fix for a MT engine bug
|
||||||
|
collisionbox = {-2, -1.5, -2.25, 2, 1.5, 3.5},
|
||||||
|
visual = "wielditem",
|
||||||
|
visual_size = {x = 0.25, y = 0.25}, -- Scale up of nodebox is these * 1.5
|
||||||
|
textures = {"spaceship:spaceship_nodebox" ..color},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Custom fields
|
||||||
|
driver = nil,
|
||||||
|
removed = false,
|
||||||
|
v = 0,
|
||||||
|
vy = 0,
|
||||||
|
rot = 0,
|
||||||
|
auto = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function spaceship.on_rightclick(self, clicker)
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = clicker:get_player_name()
|
||||||
|
if self.driver and name == self.driver then
|
||||||
|
-- Detach
|
||||||
|
self.driver = nil
|
||||||
|
self.auto = false
|
||||||
|
clicker:set_detach()
|
||||||
|
default.player_attached[name] = false
|
||||||
|
default.player_set_animation(clicker, "stand" , 30)
|
||||||
|
local pos = clicker:getpos()
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
clicker:setpos(pos)
|
||||||
|
end)
|
||||||
|
elseif not self.driver then
|
||||||
|
-- Attach
|
||||||
|
local attach = clicker:get_attach()
|
||||||
|
if attach and attach:get_luaentity() then
|
||||||
|
local luaentity = attach:get_luaentity()
|
||||||
|
if luaentity.driver then
|
||||||
|
luaentity.driver = nil
|
||||||
|
end
|
||||||
|
clicker:set_detach()
|
||||||
|
end
|
||||||
|
self.driver = name
|
||||||
|
clicker:set_attach(self.object, "",
|
||||||
|
{x = 0, y = -2, z = 0}, {x = 0, y = 0, z = 0})
|
||||||
|
default.player_attached[name] = true
|
||||||
|
minetest.after(0.2, function()
|
||||||
|
default.player_set_animation(clicker, "sit" , 30)
|
||||||
|
end)
|
||||||
|
clicker:set_look_horizontal(self.object:getyaw())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function spaceship.on_activate(self, staticdata, dtime_s)
|
||||||
|
self.object:set_armor_groups({immortal = 1})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function spaceship.on_punch(self, puncher)
|
||||||
|
if not puncher or not puncher:is_player() or self.removed then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local name = puncher:get_player_name()
|
||||||
|
if self.driver and name == self.driver then
|
||||||
|
-- Detach
|
||||||
|
self.driver = nil
|
||||||
|
puncher:set_detach()
|
||||||
|
default.player_attached[name] = false
|
||||||
|
end
|
||||||
|
if not self.driver then
|
||||||
|
-- Move to inventory
|
||||||
|
self.removed = true
|
||||||
|
local inv = puncher:get_inventory()
|
||||||
|
if not (creative and creative.is_enabled_for
|
||||||
|
and creative.is_enabled_for(name))
|
||||||
|
or not inv:contains_item("main", "spaceship:spaceship" ..color) then
|
||||||
|
local leftover = inv:add_item("main", "spaceship:spaceship" ..color)
|
||||||
|
if not leftover:is_empty() then
|
||||||
|
minetest.add_item(self.object:getpos(), leftover)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
self.object:remove()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function spaceship.on_step(self, dtime)
|
||||||
|
self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
|
||||||
|
self.vy = self.object:getvelocity().y
|
||||||
|
|
||||||
|
-- Controls
|
||||||
|
if self.driver then
|
||||||
|
local driver_objref = minetest.get_player_by_name(self.driver)
|
||||||
|
if driver_objref then
|
||||||
|
local ctrl = driver_objref:get_player_control()
|
||||||
|
if ctrl.up and ctrl.down then
|
||||||
|
if not self.auto then
|
||||||
|
self.auto = true
|
||||||
|
minetest.chat_send_player(self.driver,
|
||||||
|
"[spaceship] Cruise on")
|
||||||
|
end
|
||||||
|
elseif ctrl.down then
|
||||||
|
self.v = self.v - 0.1
|
||||||
|
if self.auto then
|
||||||
|
self.auto = false
|
||||||
|
minetest.chat_send_player(self.driver,
|
||||||
|
"[spaceship] Cruise off")
|
||||||
|
end
|
||||||
|
elseif ctrl.up or self.auto then
|
||||||
|
self.v = self.v + 0.1
|
||||||
|
end
|
||||||
|
if ctrl.left then
|
||||||
|
self.rot = self.rot + 0.001
|
||||||
|
elseif ctrl.right then
|
||||||
|
self.rot = self.rot - 0.001
|
||||||
|
end
|
||||||
|
if ctrl.jump then
|
||||||
|
self.vy = self.vy + 0.075
|
||||||
|
elseif ctrl.sneak then
|
||||||
|
self.vy = self.vy - 0.075
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Player left server while driving
|
||||||
|
-- In MT 5.0.0 use 'spaceship:on_detach_child()' to do this
|
||||||
|
self.driver = nil
|
||||||
|
self.auto = false
|
||||||
|
minetest.log("warning", "[spaceship] Driver left server while" ..
|
||||||
|
" driving. This may cause some 'Pushing ObjectRef to" ..
|
||||||
|
" removed/deactivated object' warnings.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Early return for stationary vehicle
|
||||||
|
if self.v == 0 and self.rot == 0 and self.vy == 0 then
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reduction and limiting of linear speed
|
||||||
|
local s = get_sign(self.v)
|
||||||
|
self.v = self.v - 0.02 * s
|
||||||
|
if s ~= get_sign(self.v) then
|
||||||
|
self.v = 0
|
||||||
|
end
|
||||||
|
if math.abs(self.v) > 6 then
|
||||||
|
self.v = 6 * get_sign(self.v)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reduction and limiting of rotation
|
||||||
|
local sr = get_sign(self.rot)
|
||||||
|
self.rot = self.rot - 0.0003 * sr
|
||||||
|
if sr ~= get_sign(self.rot) then
|
||||||
|
self.rot = 0
|
||||||
|
end
|
||||||
|
if math.abs(self.rot) > 0.015 then
|
||||||
|
self.rot = 0.015 * get_sign(self.rot)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reduction and limiting of vertical speed
|
||||||
|
local sy = get_sign(self.vy)
|
||||||
|
self.vy = self.vy - 0.03 * sy
|
||||||
|
if sy ~= get_sign(self.vy) then
|
||||||
|
self.vy = 0
|
||||||
|
end
|
||||||
|
if math.abs(self.vy) > 4 then
|
||||||
|
self.vy = 4 * get_sign(self.vy)
|
||||||
|
end
|
||||||
|
|
||||||
|
local new_acce = {x = 0, y = 0, z = 0}
|
||||||
|
-- Bouyancy in liquids
|
||||||
|
local p = self.object:getpos()
|
||||||
|
p.y = p.y - 1.5
|
||||||
|
local def = minetest.registered_nodes[minetest.get_node(p).name]
|
||||||
|
if def and (def.liquidtype == "source" or def.liquidtype == "flowing") then
|
||||||
|
new_acce = {x = 0, y = 10, z = 0}
|
||||||
|
end
|
||||||
|
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), self.vy))
|
||||||
|
self.object:setacceleration(new_acce)
|
||||||
|
self.object:setyaw(self.object:getyaw() + (1 + dtime) * self.rot)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_entity("spaceship:spaceship" ..color , spaceship)
|
||||||
|
|
||||||
|
|
||||||
|
-- Craftitem
|
||||||
|
|
||||||
|
minetest.register_craftitem("spaceship:spaceship" .. color, {
|
||||||
|
description = "spaceship" .. color,
|
||||||
|
inventory_image = "spaceship_spaceship_inv.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "none.png",
|
||||||
|
wield_scale = {x = 4, y = 4, z = 4},
|
||||||
|
liquids_pointable = true,
|
||||||
|
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local node = minetest.get_node(under)
|
||||||
|
local udef = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
|
-- Run any on_rightclick function of pointed node instead
|
||||||
|
if udef and udef.on_rightclick and
|
||||||
|
not (placer and placer:is_player() and
|
||||||
|
placer:get_player_control().sneak) then
|
||||||
|
return udef.on_rightclick(under, node, placer, itemstack,
|
||||||
|
pointed_thing) or itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
if pointed_thing.type ~= "node" then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
pointed_thing.under.y = pointed_thing.under.y + 2
|
||||||
|
local spaceship = minetest.add_entity(pointed_thing.under,
|
||||||
|
"spaceship:spaceship" ..color)
|
||||||
|
if spaceship then
|
||||||
|
if placer then
|
||||||
|
spaceship:setyaw(placer:get_look_horizontal())
|
||||||
|
end
|
||||||
|
local player_name = placer and placer:get_player_name() or ""
|
||||||
|
if not (creative and creative.is_enabled_for and
|
||||||
|
creative.is_enabled_for(player_name)) then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- Nodebox for entity wielditem visual
|
||||||
|
|
||||||
|
minetest.register_node("spaceship:spaceship_nodebox" .. color, {
|
||||||
|
description = "Spaceship Nodebox" .. color,
|
||||||
|
tiles = { -- Top, base, right, left, front, back
|
||||||
|
"color_white.png^[colorize:#"..colour..":70",
|
||||||
|
},
|
||||||
|
paramtype = "light",
|
||||||
|
drawtype = "mesh",
|
||||||
|
mesh = "spaceship.obj",
|
||||||
|
groups = {not_in_creative_inventory = 1},
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,65 @@
|
||||||
|
License of model spaceship
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
This work, made by Viktor Hahn (Viktor.Hahn@web.de), is
|
||||||
|
licensed under the Creative Commons Attribution 3.0 Unported License.
|
||||||
|
http://creativecommons.org/licenses/by/3.0/
|
||||||
|
|
||||||
|
|
||||||
|
License of source code
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (C) 2018 paramat
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
|
||||||
|
License of media (textures)
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||||
|
Paramat
|
||||||
|
|
||||||
|
No Copyright
|
||||||
|
|
||||||
|
The person who associated a work with this deed has dedicated the work to the
|
||||||
|
public domain by waiving all of his or her rights to the work worldwide under
|
||||||
|
copyright law, including all related and neighboring rights, to the extent
|
||||||
|
allowed by law.
|
||||||
|
|
||||||
|
You can copy, modify, distribute and perform the work, even for commercial
|
||||||
|
purposes, all without asking permission. See Other Information below.
|
||||||
|
|
||||||
|
Other Information:
|
||||||
|
|
||||||
|
In no way are the patent or trademark rights of any person affected by CC0, nor
|
||||||
|
are the rights that other persons may have in the work or in how the work is
|
||||||
|
used, such as publicity or privacy rights.
|
||||||
|
|
||||||
|
Unless expressly stated otherwise, the person who associated a work with this
|
||||||
|
deed makes no warranties about the work, and disclaims liability for all uses
|
||||||
|
of the work, to the fullest extent permitted by applicable law.
|
||||||
|
|
||||||
|
When using or citing the work, you should not imply endorsement by the author
|
||||||
|
or the affirmer.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://creativecommons.org/publicdomain/zero/1.0/
|
|
@ -0,0 +1 @@
|
||||||
|
name = spaceship
|
After Width: | Height: | Size: 333 B |
After Width: | Height: | Size: 91 B |
After Width: | Height: | Size: 327 B |
|
@ -0,0 +1,2 @@
|
||||||
|
# minetest-surfboard
|
||||||
|
Surfboard mod for Minetest. https://minetest.net/
|
|
@ -0,0 +1,15 @@
|
||||||
|
Surfboards, forked from boats by archfan
|
||||||
|
========================
|
||||||
|
See license.txt for license information.
|
||||||
|
|
||||||
|
Authors of source code
|
||||||
|
----------------------
|
||||||
|
Originally by PilzAdam (MIT)
|
||||||
|
Various Minetest developers and contributors (MIT)
|
||||||
|
|
||||||
|
Authors of media (textures and model)
|
||||||
|
-------------------------------------
|
||||||
|
Textures: Zeg9 (CC BY-SA 3.0)
|
||||||
|
Model: thetoon and Zeg9 (CC BY-SA 3.0),
|
||||||
|
modified by PavelS(SokolovPavel) (CC BY-SA 3.0),
|
||||||
|
modified by sofar (CC BY-SA 3.0)
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -0,0 +1,264 @@
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Darkened", "292421", 40, 36, 33},
|
||||||
|
{"blue", "Blue", "0000FF", 0, 0, 255},
|
||||||
|
{"green", "Green", "00FF00", 0, 255, 0},
|
||||||
|
{"white", "White", "F5F5F5", 245, 245, 245},
|
||||||
|
{"orange", "Orange", "FF6103", 255, 97, 3},
|
||||||
|
{"red", "Red", "FF0000", 255, 0, 0},
|
||||||
|
{"yellow", "Yellow", "FFFF00", 255, 255, 0},
|
||||||
|
{"pink", "pink", "FF69B4", 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local description = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Helper functions
|
||||||
|
--
|
||||||
|
|
||||||
|
local function is_water(pos)
|
||||||
|
local nn = minetest.get_node(pos).name
|
||||||
|
return minetest.get_item_group(nn, "water") ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_sign(i)
|
||||||
|
if i == 0 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return i / math.abs(i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_velocity(v, yaw, y)
|
||||||
|
local x = -math.sin(yaw) * v
|
||||||
|
local z = math.cos(yaw) * v
|
||||||
|
return {x = x, y = y, z = z}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_v(v)
|
||||||
|
return math.sqrt(v.x ^ 2 + v.z ^ 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Boat entity
|
||||||
|
--
|
||||||
|
|
||||||
|
local surfboard = {
|
||||||
|
physical = true,
|
||||||
|
-- Warning: Do not change the position of the collisionbox top surface,
|
||||||
|
-- lowering it causes the surfboard to fall through the world if underwater
|
||||||
|
collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5},
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "surfboard.x",
|
||||||
|
textures = {"color_white.png^[colorize:#"..colour..":70"},
|
||||||
|
driver = nil,
|
||||||
|
v = 0,
|
||||||
|
last_v = 0,
|
||||||
|
removed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function surfboard.on_rightclick(self, clicker)
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = clicker:get_player_name()
|
||||||
|
if self.driver and clicker == self.driver then
|
||||||
|
self.driver = nil
|
||||||
|
clicker:set_detach()
|
||||||
|
default.player_attached[name] = false
|
||||||
|
default.player_set_animation(clicker, "stand" , 30)
|
||||||
|
local pos = clicker:getpos()
|
||||||
|
pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
clicker:setpos(pos)
|
||||||
|
end)
|
||||||
|
elseif not self.driver then
|
||||||
|
local attach = clicker:get_attach()
|
||||||
|
if attach and attach:get_luaentity() then
|
||||||
|
local luaentity = attach:get_luaentity()
|
||||||
|
if luaentity.driver then
|
||||||
|
luaentity.driver = nil
|
||||||
|
end
|
||||||
|
clicker:set_detach()
|
||||||
|
end
|
||||||
|
self.driver = clicker
|
||||||
|
clicker:set_attach(self.object, "",
|
||||||
|
{x = 0, y = 10, z = 0}, {x = 0, y = 0, z = 0})
|
||||||
|
default.player_attached[name] = true
|
||||||
|
minetest.after(0.2, function()
|
||||||
|
default.player_set_animation(clicker, "stand" , 0)
|
||||||
|
end)
|
||||||
|
clicker:set_look_horizontal(self.object:getyaw())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function surfboard.on_activate(self, staticdata, dtime_s)
|
||||||
|
self.object:set_armor_groups({immortal = 1})
|
||||||
|
if staticdata then
|
||||||
|
self.v = tonumber(staticdata)
|
||||||
|
end
|
||||||
|
self.last_v = self.v
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function surfboard.get_staticdata(self)
|
||||||
|
return tostring(self.v)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function surfboard.on_punch(self, puncher)
|
||||||
|
if not puncher or not puncher:is_player() or self.removed then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.driver and puncher == self.driver then
|
||||||
|
self.driver = nil
|
||||||
|
puncher:set_detach()
|
||||||
|
default.player_attached[puncher:get_player_name()] = false
|
||||||
|
end
|
||||||
|
if not self.driver then
|
||||||
|
self.removed = true
|
||||||
|
local inv = puncher:get_inventory()
|
||||||
|
-- delay remove to ensure player is detached
|
||||||
|
minetest.after(0.1, function()
|
||||||
|
self.object:remove()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function surfboard.on_step(self, dtime)
|
||||||
|
self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
|
||||||
|
if self.driver then
|
||||||
|
local ctrl = self.driver:get_player_control()
|
||||||
|
local yaw = self.object:getyaw()
|
||||||
|
if ctrl.up then
|
||||||
|
self.v = self.v + 0.1
|
||||||
|
elseif ctrl.down then
|
||||||
|
self.v = self.v - 0.1
|
||||||
|
end
|
||||||
|
if ctrl.left then
|
||||||
|
if self.v < 0 then
|
||||||
|
self.object:setyaw(yaw - (1 + dtime) * 0.03)
|
||||||
|
else
|
||||||
|
self.object:setyaw(yaw + (1 + dtime) * 0.03)
|
||||||
|
end
|
||||||
|
elseif ctrl.right then
|
||||||
|
if self.v < 0 then
|
||||||
|
self.object:setyaw(yaw + (1 + dtime) * 0.03)
|
||||||
|
else
|
||||||
|
self.object:setyaw(yaw - (1 + dtime) * 0.03)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local velo = self.object:getvelocity()
|
||||||
|
if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local s = get_sign(self.v)
|
||||||
|
self.v = self.v - 0.02 * s
|
||||||
|
if s ~= get_sign(self.v) then
|
||||||
|
self.object:setvelocity({x = 0, y = 0, z = 0})
|
||||||
|
self.v = 0
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if math.abs(self.v) > 5 then
|
||||||
|
self.v = 5 * get_sign(self.v)
|
||||||
|
end
|
||||||
|
|
||||||
|
local p = self.object:getpos()
|
||||||
|
p.y = p.y - 0.5
|
||||||
|
local new_velo
|
||||||
|
local new_acce = {x = 0, y = 0, z = 0}
|
||||||
|
if not is_water(p) then
|
||||||
|
local nodedef = minetest.registered_nodes[minetest.get_node(p).name]
|
||||||
|
if (not nodedef) or nodedef.walkable then
|
||||||
|
self.v = 0
|
||||||
|
new_acce = {x = 0, y = 1, z = 0}
|
||||||
|
else
|
||||||
|
new_acce = {x = 0, y = -9.8, z = 0}
|
||||||
|
end
|
||||||
|
new_velo = get_velocity(self.v, self.object:getyaw(),
|
||||||
|
self.object:getvelocity().y)
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
else
|
||||||
|
p.y = p.y + 1
|
||||||
|
if is_water(p) then
|
||||||
|
local y = self.object:getvelocity().y
|
||||||
|
if y >= 5 then
|
||||||
|
y = 5
|
||||||
|
elseif y < 0 then
|
||||||
|
new_acce = {x = 0, y = 20, z = 0}
|
||||||
|
else
|
||||||
|
new_acce = {x = 0, y = 5, z = 0}
|
||||||
|
end
|
||||||
|
new_velo = get_velocity(self.v, self.object:getyaw(), y)
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
else
|
||||||
|
new_acce = {x = 0, y = 0, z = 0}
|
||||||
|
if math.abs(self.object:getvelocity().y) < 1 then
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
pos.y = math.floor(pos.y) + 0.5
|
||||||
|
self.object:setpos(pos)
|
||||||
|
new_velo = get_velocity(self.v, self.object:getyaw(), 0)
|
||||||
|
else
|
||||||
|
new_velo = get_velocity(self.v, self.object:getyaw(),
|
||||||
|
self.object:getvelocity().y)
|
||||||
|
self.object:setpos(self.object:getpos())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.object:setvelocity(new_velo)
|
||||||
|
self.object:setacceleration(new_acce)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_entity("surfboard:board" .. color, surfboard)
|
||||||
|
|
||||||
|
minetest.register_craftitem("surfboard:board" .. color, {
|
||||||
|
description = "Surfboard" .. color,
|
||||||
|
inventory_image = "surfboard.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "none.png^[colorize:#"..colour..":70",
|
||||||
|
wield_scale = {x = 2, y = 2, z = 1},
|
||||||
|
liquids_pointable = true,
|
||||||
|
groups = {flammable = 2},
|
||||||
|
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local node = minetest.get_node(under)
|
||||||
|
local udef = minetest.registered_nodes[node.name]
|
||||||
|
if udef and udef.on_rightclick and
|
||||||
|
not (placer and placer:get_player_control().sneak) then
|
||||||
|
return udef.on_rightclick(under, node, placer, itemstack,
|
||||||
|
pointed_thing) or itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
if pointed_thing.type ~= "node" then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
if not is_water(pointed_thing.under) then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
pointed_thing.under.y = pointed_thing.under.y + 0.5
|
||||||
|
boat = minetest.add_entity(pointed_thing.under, "surfboard:board" .. color)
|
||||||
|
if boat then
|
||||||
|
boat:setyaw(placer:get_look_horizontal())
|
||||||
|
if not (creative and creative.is_enabled_for
|
||||||
|
and creative.is_enabled_for(placer:get_player_name())) then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,63 @@
|
||||||
|
License of source code
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (C) 2012-2016 PilzAdam
|
||||||
|
Copyright (C) 2012-2016 Various Minetest developers and contributors
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
|
||||||
|
Licenses of media (textures and model)
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||||
|
Copyright (C) 2012-2016 Zeg9
|
||||||
|
Copyright (C) 2012-2016 thetoon
|
||||||
|
Copyright (C) 2012-2016 PavelS(SokolovPavel)
|
||||||
|
Copyright (C) 2016 sofar (sofar@foo-projects.org)
|
||||||
|
|
||||||
|
You are free to:
|
||||||
|
Share — copy and redistribute the material in any medium or format.
|
||||||
|
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
|
||||||
|
The licensor cannot revoke these freedoms as long as you follow the license terms.
|
||||||
|
|
||||||
|
Under the following terms:
|
||||||
|
|
||||||
|
Attribution — You must give appropriate credit, provide a link to the license, and
|
||||||
|
indicate if changes were made. You may do so in any reasonable manner, but not in any way
|
||||||
|
that suggests the licensor endorses you or your use.
|
||||||
|
|
||||||
|
ShareAlike — If you remix, transform, or build upon the material, you must distribute
|
||||||
|
your contributions under the same license as the original.
|
||||||
|
|
||||||
|
No additional restrictions — You may not apply legal terms or technological measures that
|
||||||
|
legally restrict others from doing anything the license permits.
|
||||||
|
|
||||||
|
Notices:
|
||||||
|
|
||||||
|
You do not have to comply with the license for elements of the material in the public
|
||||||
|
domain or where your use is permitted by an applicable exception or limitation.
|
||||||
|
No warranties are given. The license may not give you all of the permissions necessary
|
||||||
|
for your intended use. For example, other rights such as publicity, privacy, or moral
|
||||||
|
rights may limit how you use the material.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
http://creativecommons.org/licenses/by-sa/3.0/
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
Textures:
|
||||||
|
Original torch textures from minetest_game/default
|
||||||
|
Recoloured textures and edits by Shara RedCat
|
||||||
|
|
||||||
|
Torch model:
|
||||||
|
License: CC-BY 3.0
|
||||||
|
Attribution: BlockMen, from https://github.com/BlockMen/torches
|
||||||
|
|
||||||
|
Code:
|
||||||
|
License: MIT (https://opensource.org/licenses/MIT)
|
||||||
|
By Shara RedCat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Shara RedCat
|
||||||
|
|
||||||
|
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.
|
|
@ -0,0 +1,2 @@
|
||||||
|
default
|
||||||
|
color
|
|
@ -0,0 +1,3 @@
|
||||||
|
local modpath = minetest.get_modpath("abritorch").. DIR_DELIM
|
||||||
|
|
||||||
|
dofile(modpath.."torches.lua")
|
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 91 B |
|
@ -0,0 +1,134 @@
|
||||||
|
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1, 40, 36, 33},
|
||||||
|
{"blue", "Color2", color2, 0, 0, 255},
|
||||||
|
{"green", "Color3", color3, 0, 255, 0},
|
||||||
|
{"white", "Color4", color4, 245, 245, 245},
|
||||||
|
{"orange", "Color5", color5, 255, 97, 3},
|
||||||
|
{"red", "Color6", color6, 255, 0, 0},
|
||||||
|
{"yellow", "Color7", color7, 255, 255, 0},
|
||||||
|
{"pink", "Color8", color8, 255, 105, 180}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local name = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
local red = source_list[i][4]
|
||||||
|
local green = source_list[i][5]
|
||||||
|
local blue = source_list[i][6]
|
||||||
|
|
||||||
|
local enable_ceiling = true
|
||||||
|
|
||||||
|
minetest.register_craftitem("abritorch:torch_" .. name, {
|
||||||
|
description = desc.." Torch",
|
||||||
|
inventory_image = "torch.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "color_hand" .. name .. ".png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
liquids_pointable = false,
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local above = pointed_thing.above
|
||||||
|
local under = pointed_thing.under
|
||||||
|
local wdir = minetest.dir_to_wallmounted({x = under.x - above.x, y = under.y - above.y, z = under.z - above.z})
|
||||||
|
if wdir < 1 and not enable_ceiling then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
local fakestack = itemstack
|
||||||
|
local retval = false
|
||||||
|
if wdir <= 1 then
|
||||||
|
retval = fakestack:set_name("abritorch:floor_"..name)
|
||||||
|
else
|
||||||
|
retval = fakestack:set_name("abritorch:wall_"..name)
|
||||||
|
end
|
||||||
|
if not retval then
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
itemstack, retval = minetest.item_place(fakestack, placer, pointed_thing, param2)
|
||||||
|
itemstack:set_name("abritorch:torch_"..name)
|
||||||
|
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("abritorch:floor_"..name, {
|
||||||
|
description = desc.." Torch",
|
||||||
|
inventory_image = "torch.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "color_hand" .. name .. ".png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
drawtype = "mesh",
|
||||||
|
mesh = "torch_floor.obj",
|
||||||
|
tiles = {
|
||||||
|
{
|
||||||
|
name = "abritorch_torch_on_floor_animated_white.png^[colorize:#"..colour..":70",
|
||||||
|
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "wallmounted",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
light_source = 13,
|
||||||
|
groups = {choppy=2, dig_immediate=3, flammable=1, not_in_creative_inventory=1, attached_node=1, torch=1},
|
||||||
|
selection_box = {
|
||||||
|
type = "wallmounted",
|
||||||
|
wall_top = {-1/16, -2/16, -1/16, 1/16, 0.5, 1/16},
|
||||||
|
wall_bottom = {-1/16, -0.5, -1/16, 1/16, 2/16, 1/16},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("abritorch:wall_"..name, {
|
||||||
|
inventory_image = "torch.png^[colorize:#"..colour..":70",
|
||||||
|
wield_image = "color_hand" .. name .. ".png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
drawtype = "mesh",
|
||||||
|
mesh = "torch_wall.obj",
|
||||||
|
tiles = {
|
||||||
|
{
|
||||||
|
name = "abritorch_torch_on_floor_animated_white.png^[colorize:#"..colour..":70",
|
||||||
|
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "wallmounted",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
light_source = 13,
|
||||||
|
groups = {choppy=2, dig_immediate=3, flammable=1, not_in_creative_inventory=1, attached_node=1, torch=1},
|
||||||
|
selection_box = {
|
||||||
|
type = "wallmounted",
|
||||||
|
wall_top = {-0.1, -0.1, -0.1, 0.1, 0.5, 0.1},
|
||||||
|
wall_bottom = {-0.1, -0.5, -0.1, 0.1, 0.1, 0.1},
|
||||||
|
wall_side = {-0.5, -0.3, -0.1, -0.2, 0.3, 0.1},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = {"abritorch:torch_"..name},
|
||||||
|
interval = 1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos)
|
||||||
|
local n = minetest.get_node(pos)
|
||||||
|
local def = minetest.registered_nodes[n.name]
|
||||||
|
if n and def then
|
||||||
|
local wdir = n.param2
|
||||||
|
local node_name = "abritorch:wall_"..name
|
||||||
|
if wdir < 1 and not enable_ceiling then
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
return
|
||||||
|
elseif wdir <= 1 then
|
||||||
|
node_name = "abritorch:floor_"..name
|
||||||
|
end
|
||||||
|
minetest.set_node(pos, {name = node_name, param2 = wdir})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
Beacon in Block (LGPLv2.1) (Mrchiantos)
|
||||||
|
|
||||||
|
This mod is made with Beacon'Mod and Block in Block
|
||||||
|
|
||||||
|
Beacon (WTFPL) : https://forum.minetest.net/viewtopic.php?t=12041 (AgentNagel42)
|
||||||
|
|
||||||
|
Block in Block (LGPLv2.1) : https://github.com/TumeniNodes/block_in_block (TuemiNodes)
|
||||||
|
|
||||||
|
Calinou (CC BY-SA 3.0): default_glass_detail.png
|
|
@ -0,0 +1,40 @@
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1},
|
||||||
|
{"blue", "Color2", color2},
|
||||||
|
{"green", "Color3", color3},
|
||||||
|
{"white", "Color4", color4},
|
||||||
|
{"orange", "Color5", color5},
|
||||||
|
{"red", "Color6", color6},
|
||||||
|
{"yellow", "Color7", color7},
|
||||||
|
{"pink", "Color8", color8}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = {"beacon:" .. color},
|
||||||
|
interval = 5,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos)
|
||||||
|
pos.y = pos.y + 1
|
||||||
|
minetest.add_node(pos, {name="beacon:"..color.."base"})
|
||||||
|
for i=1,179 do
|
||||||
|
minetest.add_node({x=pos.x, y=pos.y+i, z=pos.z}, {name="beacon:"..color.."beam"})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,73 @@
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1},
|
||||||
|
{"blue", "Color2", color2},
|
||||||
|
{"green", "Color3", color3},
|
||||||
|
{"white", "Color4", color4},
|
||||||
|
{"orange", "Color5", color5},
|
||||||
|
{"red", "Color6", color6},
|
||||||
|
{"yellow", "Color7", color7},
|
||||||
|
{"pink", "Color8", color8}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
|
||||||
|
--Blue Beam
|
||||||
|
minetest.register_node("beacon:"..color.."base", {
|
||||||
|
visual_scale = 1.0,
|
||||||
|
drawtype = "plantlike",
|
||||||
|
tiles = {"beam.png^[colorize:#"..colour..":70" },
|
||||||
|
paramtype = "light",
|
||||||
|
walkable = false,
|
||||||
|
diggable = false,
|
||||||
|
light_source = 13,
|
||||||
|
groups = {not_in_creative_inventory=1}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("beacon:"..color.."beam", {
|
||||||
|
visual_scale = 1.0,
|
||||||
|
drawtype = "plantlike",
|
||||||
|
tiles = {"beam.png^[colorize:#"..colour..":70"},
|
||||||
|
paramtype = "light",
|
||||||
|
walkable = false,
|
||||||
|
diggable = false,
|
||||||
|
light_source = 50,
|
||||||
|
groups = {not_in_creative_inventory=1}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = {"beacon:"..color.."base"}, --makes small particles emanate from the beginning of a beam
|
||||||
|
interval = 1,
|
||||||
|
chance = 2,
|
||||||
|
action = function(pos, node)
|
||||||
|
minetest.add_particlespawner(
|
||||||
|
32, --amount
|
||||||
|
4, --time
|
||||||
|
{x=pos.x-0.25, y=pos.y-0.25, z=pos.z-0.25}, --minpos
|
||||||
|
{x=pos.x+0.25, y=pos.y+0.25, z=pos.z+0.25}, --maxpos
|
||||||
|
{x=-0.8, y=-0.8, z=-0.8}, --minvel
|
||||||
|
{x=0.8, y=0.8, z=0.8}, --maxvel
|
||||||
|
{x=0,y=0,z=0}, --minacc
|
||||||
|
{x=0,y=0,z=0}, --maxacc
|
||||||
|
0.5, --minexptime
|
||||||
|
1, --maxexptime
|
||||||
|
1, --minsize
|
||||||
|
2, --maxsize
|
||||||
|
false, --collisiondetection
|
||||||
|
"particle.png^[colorize:#"..colour..":70" --texture
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -0,0 +1 @@
|
||||||
|
Mix of 2 mods : Beacon and Block in block
|
|
@ -0,0 +1,97 @@
|
||||||
|
--Beacons v1.1 for minetest // block_in_block | October 2018 TumeniNodes
|
||||||
|
|
||||||
|
--load other scripts
|
||||||
|
dofile(minetest.get_modpath("beacon").."/beaminit.lua")
|
||||||
|
dofile(minetest.get_modpath("beacon").."/beamgen.lua")
|
||||||
|
|
||||||
|
color1 = minetest.setting_get("color1") or "292421"
|
||||||
|
color2 = minetest.setting_get("color2") or "0000FF"
|
||||||
|
color3 = minetest.setting_get("color3") or "00FF00"
|
||||||
|
color4 = minetest.setting_get("color4") or "F5F5F5"
|
||||||
|
color5 = minetest.setting_get("color5") or "FF6103"
|
||||||
|
color6 = minetest.setting_get("color6") or "FF0000"
|
||||||
|
color7 = minetest.setting_get("color7") or "FFFF00"
|
||||||
|
color8 = minetest.setting_get("color8") or "FF69B4"
|
||||||
|
|
||||||
|
local source_list = {
|
||||||
|
{"black", "Color1", color1},
|
||||||
|
{"blue", "Color2", color2},
|
||||||
|
{"green", "Color3", color3},
|
||||||
|
{"white", "Color4", color4},
|
||||||
|
{"orange", "Color5", color5},
|
||||||
|
{"red", "Color6", color6},
|
||||||
|
{"yellow", "Color7", color7},
|
||||||
|
{"pink", "Color8", color8}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(source_list) do
|
||||||
|
local color = source_list[i][1]
|
||||||
|
local desc = source_list[i][2]
|
||||||
|
local colour = source_list[i][3]
|
||||||
|
|
||||||
|
--code for "unactivated beacon"
|
||||||
|
minetest.register_node("beacon:empty", {
|
||||||
|
description = "Unactivated Beacon",
|
||||||
|
wield_image = "color_handwhite.png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
inventory_image = 'beaconoff.png^[colorize:#'..colour..':70',
|
||||||
|
tiles = {"color_white.png", "default_glass.png"},
|
||||||
|
light_source = 3,
|
||||||
|
groups = {cracky=3,oddly_breakable_by_hand=3},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("beacon:off" .. color , {
|
||||||
|
description = "Beacon" .. color,
|
||||||
|
drawtype = "mesh",
|
||||||
|
light_source = 13,
|
||||||
|
mesh = "block_in_block.obj",
|
||||||
|
wield_image = "color_hand" .. color .. ".png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
inventory_image = 'beaconoff.png^[colorize:#'..colour..':70',
|
||||||
|
tiles = {"color_white.png^[colorize:#"..colour..":70","default_glass.png"},
|
||||||
|
paramtype = "light",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {cracky = 3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_destruct = function(pos)
|
||||||
|
for i=1,180 do
|
||||||
|
minetest.remove_node({x=pos.x, y=pos.y+i, z=pos.z})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("beacon:" .. color , {
|
||||||
|
description = "Beacon" .. color,
|
||||||
|
drawtype = "mesh",
|
||||||
|
light_source = 13,
|
||||||
|
mesh = "block_in_block.obj",
|
||||||
|
wield_image = "color_hand" .. color .. ".png",
|
||||||
|
wield_scale = {x=1,y=1,z=0.5},
|
||||||
|
inventory_image = 'beaconon.png^[colorize:#'..colour..':70',
|
||||||
|
tiles = {"color_white.png^[colorize:#"..colour..":70", "default_glass.png"},
|
||||||
|
paramtype = "light",
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {cracky = 3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_destruct = function(pos)
|
||||||
|
for i=1,180 do
|
||||||
|
minetest.remove_node({x=pos.x, y=pos.y+i, z=pos.z})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
print("[OK] Beacons")
|
|
@ -0,0 +1 @@
|
||||||
|
name = beacon
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Blender MTL File: 'block_in_block.blend'
|
||||||
|
# Material Count: 2
|
||||||
|
|
||||||
|
newmtl Material.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.042654 0.137327 0.640000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Kd /home/paul/Homer/minetest/games/minetest_game/mods/default/textures/default_obsidian_glass.png
|
||||||
|
|
||||||
|
newmtl Material.002
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.283146 0.640000 0.030032
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
map_Kd /home/paul/Homer/minetest/games/minetest_game/mods/default/textures/default_gold_block.png
|
After Width: | Height: | Size: 164 B |
After Width: | Height: | Size: 333 B |
After Width: | Height: | Size: 158 B |
After Width: | Height: | Size: 128 B |
|
@ -0,0 +1,47 @@
|
||||||
|
===BEDS MOD for MINETEST-C55===
|
||||||
|
by PilzAdam & thefamilygrog66
|
||||||
|
|
||||||
|
Introduction:
|
||||||
|
This mods brings beds to Minetest. You can use them to sleep at night
|
||||||
|
to prevent attacks by evil mobs.
|
||||||
|
|
||||||
|
How to install:
|
||||||
|
Unzip the archive an place it in minetest-base-directory/mods/minetest/
|
||||||
|
if you have a windows client or a linux run-in-place client. If you have
|
||||||
|
a linux system-wide instalation place it in ~/.minetest/mods/minetest/.
|
||||||
|
If you want to install this mod only in one world create the folder
|
||||||
|
worldmods/ in your worlddirectory.
|
||||||
|
For further information or help see:
|
||||||
|
http://wiki.minetest.com/wiki/Installing_Mods
|
||||||
|
|
||||||
|
How to use the mod:
|
||||||
|
Craft a bed like this:
|
||||||
|
white wool white wool white wool
|
||||||
|
stick stick
|
||||||
|
After placing it anywhere you can go to sleep with a leftklick with your
|
||||||
|
hand on the bed. If it is night a chatmessage wishs you "Good night" and
|
||||||
|
you sleep until the next morning. To go outside the bed it is recommended
|
||||||
|
to hit the bed again with a leftklick (it also works if you just go away
|
||||||
|
but its not so safe).
|
||||||
|
After dying the player will respawn at the last bed he has slept.
|
||||||
|
|
||||||
|
License:
|
||||||
|
Sourcecode: WTFPL (see below)
|
||||||
|
Graphics: WTFPL (see below)
|
||||||
|
|
||||||
|
See also:
|
||||||
|
http://minetest.net/
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|