new mod: air balloon

This commit is contained in:
Sergei Mozhaisky 2020-01-15 20:08:13 +00:00
parent ad9dc6df7e
commit 8d60282644
18 changed files with 1234 additions and 0 deletions

View File

@ -0,0 +1,57 @@
This mod adds craftable and ridable hot air balloons to minetest.
Controls:
right click with coal lump: increase heat and buoyancy (*)
right click without coal: enter or leave balloon
left, right, up, down (default WASD): accelerate the balloon
sneak (default shift): decrease heat, lowering buoyancy
jump (default space): turn the balloon towards where the player is looking
optional dependencies:
default, bucket (enable crafting recipe 1 if installed together)
mcl_core, mcl_mobitems, mcl_buckets (enable crafting recipe 2 if installed together)
Crafting recipe 1 (Minetest Game and most derivatives):
[P] := paper
[W] := wood
[L] := lava bucket
[ ] := nothing
[P][P][P]
[P][L][P]
[ ][W][ ]
Crafting recipe 2 (MineClone 2):
[L] := leather
[W] := wood
[V] := lava bucket
[S] := string
[L][L][L]
[L][V][L]
[S][W][S]
(*)any item with the "coal" group works for fuel. Higher coal group means higher heat
Note that coal blocks and ore from the default mod don't have the coal group
See license.txt for proper license information.
Author of code
----------------------------------------
NetherEran (LGPL v2.1)
Authors of media (models, textures)
----------------------------------------
Textures
--------
NetherEran (CC BY-SA 3.0):
hot_air_balloons_balloon.png
hot_air_balloons_balloon_flame.png
hot_air_balloons_balloon_model.png --Contains default_wood.png (by BlockMen) and default_aspen_wood.png (by sofar) (derived from default_pine_wood by paramat)
Models
--------
NetherEran (CC BY-SA 3.0):
ballon.blend (= hot_air_balloons_balloon.obj)

View File

@ -0,0 +1,101 @@
--localize things for better performance
local serialize = minetest.serialize
local add_entity = minetest.add_entity
local after = minetest.after
--for storing which players left while in a balloon
local storage = minetest.get_mod_storage()
local absent_ballooners = minetest.deserialize(storage:get_string("absent_ballooners")) or {}
--putting leaving people into storage
local leave_while_ballooning = function(player)
local parent = player:get_attach()
if parent and not parent:is_player()
then
local balloon_type = parent:get_luaentity().balloon_type
if balloon_type
then
--remove() only works if someone else is in the area,
--hence the need for mark_for_deletion
parent:remove()
absent_ballooners[player:get_player_name()] = balloon_type
end
end
end
--same as on_leave but for all players at once
local on_shutdown = function()
local connected_players = minetest.get_connected_players()
for i, p in ipairs(connected_players)
do
leave_while_ballooning(p)
end
storage:set_string("absent_ballooners", serialize(absent_ballooners))
end
--putting leaving people into storage and saving storage
local on_leave = function(player)
leave_while_ballooning(player)
storage:set_string("absent_ballooners", serialize(absent_ballooners))
end
minetest.register_on_leaveplayer(on_leave)
minetest.register_on_shutdown(on_shutdown)
--checking if player who joined was ballooning when they left
--if so spawn a new balloon and set them as attachment
local on_join = function(player)
if player
then
local name = player:get_player_name()
if absent_ballooners[name]
then
local pos = player:get_pos()
--for compatibility with version 1.1 of the mod
if absent_ballooners[name] == true
then
absent_ballooners[name] = "hot_air_balloons:balloon"
end
--minetest doesn't seem to like add_entity on init so a minetest.after is used
--player is set as pilot in on_activate
after(2,
function()
--concatenating "P" with name signals that player should be set as attach
add_entity(pos, absent_ballooners[name], "P" .. name)
end)
end
end
end
minetest.register_on_joinplayer(on_join)
--called in on_activate if balloon was spawned to rescue an absent ballooner
local set_rescue = function(self, playername)
local player = minetest.get_player_by_name(playername)
self.pilot = playername
if not player --player logged off right away
then
self.object:remove()
return
end
player:set_attach(self.object, "",
{x = 0, y = 1, z = 0}, {x = 0, y = 0, z = 0})
absent_ballooners[playername] = nil
end
--set as get_staticdata
local mark_for_deletion = function(self)
if self.pilot
then
--pilot logged off while ballooning, deleting balloon on next activation
return "R"
else
--normally save and load balloon
return ""
end
end
return set_rescue, mark_for_deletion

30
hot_air_balloons/api.txt Normal file
View File

@ -0,0 +1,30 @@
API functions:
hot_air_balloons.get_entity(name, mesh_name, texture_name)
arguments:
'name': string in the format "modname:entityname"
'mesh_name': string in the format "modname_meshFileName"
'texture_name': string in the format "modname_textureFileName"
Example usage: minetest.register_entity(hot_air_balloons.get_entity(foo, raa, see))
you can also store the values in a local variable and change the fields of the entity definition table before registering the entity.
passing the entity name to the function is used when a balloon pilot logs off
hot_air_balloons.get_item(name, description, texture, object_name)
arguments:
'name': string in the format "modname:itemname"
'description': string that appears in the tooltip. Use minetest.translate with this.
'texture': string in the format "modname_textureFileName"
'object_name' is the name specified in hot_air_balloons.get_entity
Example usage: minetest.register_craftitem(hot_air_balloons.get_item(foo, raa, see, mon))
returns an item name and an item definition table
as with get_entity you can store the item definition table and change its fields before registering the item.
explanation of the custom fields of the entitiy definition table:
pilot: stores the player name of the pilot or nil if there is no pilot
heat: integer in the interval [0, 12000)
Decides wether to fly up or down
balloon_type: entity name of the balloon, e.g."hot_air_balloons:balloon".
used to make the balloon log off and log back in together with its pilot

View File

@ -0,0 +1,62 @@
--This file adds crafting recipes depending on which dependencies are installed
if minetest.get_modpath("default") and
minetest.get_modpath("bucket")
then
minetest.register_craft(
{
output = "hot_air_balloons:item",
recipe =
{
{"default:paper", "default:paper", "default:paper"},
{"default:paper", "bucket:bucket_lava", "default:paper"},
{"", "group:wood", "" },
},
})
minetest.register_craft(
{
type = "fuel",
recipe = "hot_air_balloons:item",
burntime = 20,
})
return
end
if minetest.get_modpath("mcl_buckets") and
minetest.get_modpath("mcl_mobitems") and
minetest.get_modpath("mcl_core")
then
minetest.register_craft(
{
output = "hot_air_balloons:item",
recipe =
{
{"mcl_mobitems:leather", "mcl_mobitems:leather", "mcl_mobitems:leather"},
{"mcl_mobitems:leather", "bucket:bucket_lava", "mcl_mobitems:leather"},
{"mcl_mobitems:string", "group:wood", "mcl_mobitems:string" },
},
})
minetest.register_craft(
{
type = "fuel",
recipe = "hot_air_balloons:item",
burntime = 20,
})
return
end
--[[
minetest.register_craft(
{
type = "aircraft"
}
]]
--make balloon work with mcl2 creative mode
--announce in chat if no crafting recipe was added.
minetest.after(2,
function()
minetest.chat_send_all("Optional dependencies for hot_air_balloons are missing so no crafting recipe was added.\n"..
"Install either 'default' and 'bucket' or 'mcl_core', 'mcl_mobitems' 'and mcl_buckets' if this bothers you.\n"..
"All other functions of the mod should be unaffected by this.")
end)

View File

@ -0,0 +1,5 @@
default?
bucket?
mcl_buckets?
mcl_mobitems?
mcl_core?

221
hot_air_balloons/init.lua Normal file
View File

@ -0,0 +1,221 @@
--localize functions for better performance
local string_byte = string.byte
local string_sub = string.sub
local get_item_group = minetest.get_item_group
local add_particlespawner = minetest.add_particlespawner
local add_item = minetest.add_item
local get_node = minetest.get_node
local add_entity = minetest.add_entity
local modpath = minetest.get_modpath("hot_air_balloons")
local set_rescue, mark_for_deletion_if_piloted = dofile(modpath .. "/absent_ballooner_rescuing.lua")
local handle_movement = dofile(modpath .. "/movement.lua")
local is_in_creative = function(name)
return creative and creative.is_enabled_for
and creative.is_enabled_for(name)
end
local get_fire_particle = function (pos)
pos.y = pos.y + 3
return {
amount = 3,
time = 1,
minpos = pos,
maxpos = pos,
minvel = {x = 0, y = 1, z = 0},
maxvel = {x = 0, y = 1, z = 0},
minexptime = 1,
maxexptime = 1,
minsize = 10,
maxsize = 5,
collisiondetection = false,
vertical = false,
texture = "hot_air_balloons_flame.png"
}
end
local add_heat = function(self, player)
local item_stack = player:get_wielded_item()
local item_name = item_stack:get_name()
local group_coal = get_item_group(item_name, "coal")
if group_coal == 0
then
return false
end
local heat = self.heat
heat = heat + 1200 * group_coal --1 min until heat is back to original
if heat < 12000 --cap heat at 12000 (10 min)
then
self.heat = heat
--adding particle effect
local pos = self.object:get_pos()
add_particlespawner(get_fire_particle(pos))
if not is_in_creative(player:get_player_name())
then
item_stack:take_item()
player:set_wielded_item(item_stack)
end
end
return true
end
--global table, has fields get_entity_def and get_item_def
--custom balloons right now turn into normal ones when the pilot leaves
hot_air_balloons = {}
hot_air_balloons.get_entity = function(name, mesh_name, texture_name)
return
name,
{
initial_properties =
{
hp_max = 1,
physical = true,
weight = 5,
collisionbox = {-0.65, -0.01, -0.65, 0.65, 1.11, 0.65},
visual = "mesh",
mesh = "hot_air_balloons_balloon.obj",
textures = {"hot_air_balloons_balloon_model.png"},
is_visible = true,
makes_footstep_sound = false,
automatic_rotate = false,
backface_culling = false,
},
heat = 0,
balloon_type = name,
on_step = function(self, dtime)
--decrease heat, move
if self.heat > 0
then
self.heat = self.heat - 1
end
handle_movement(self)
end,
on_rightclick = function (self, clicker)
--if hoding coal, increase heat, else mount/dismount
if not clicker or not clicker:is_player()
then
return
end
--checking if clicker is holding coal
--heating balloon and returning if yes
if add_heat(self, clicker)
then
return
end
--if not holding coal:
local playername = clicker:get_player_name()
if self.pilot and self.pilot == playername
then
self.pilot = nil
clicker:set_detach()
elseif not self.pilot
then
--attach
self.pilot = playername
clicker:set_attach(self.object, "",
{x = 0, y = 1, z = 0}, {x = 0, y = 0, z = 0})
end
end,
--if pilot leaves start sinking and prepare for next pilot
on_detach_child = function(self, child)
self.heat = 0
self.object:setvelocity({x = 0, y = 0, z = 0})
end,
on_activate = function(self, staticdata, dtime_s)
self.object:set_armor_groups({punch_operable = 1})
--so balloons don't get lost
self.object:setvelocity({x = 0, y = 0, z = 0})
--checking if balloon was spawned from item or unloaded without pilot
if staticdata == ""
then
return
end
--checking if balloon should despawn when pilot logged off
local first_char = string_byte(staticdata)
--ballooner logged off, balloon will respawn when ballooner logs back in
if first_char == 82 --chr 82 = R
then
self.object:remove()
return
--absent ballooner logged back in
elseif first_char == 80 --chr 80 = P
then
set_rescue(self, string_sub(staticdata, 2))
end
end,
get_staticdata = mark_for_deletion_if_piloted,
on_punch = function(self, puncher) --drop balloon item
if self.pilot
then
return
elseif not (puncher and puncher:is_player())
then
return
else
self.object:remove()
local inv = puncher:get_inventory()
if not is_in_creative(puncher:get_player_name())
or not inv:contains_item("main", "hot_air_balloons:item")
then
local leftover = inv:add_item("main", "hot_air_balloons:item")
if not leftover:is_empty()
then
add_item(self.object:get_pos(), leftover)
end
end
end
end,
}
end
hot_air_balloons.get_item = function(name, description, texture, object_name)
return
name,
{
description = description,
inventory_image = texture,
stack_max = 1,
liquids_pointable = true,
groups = {flammable = 2},
on_place =
function (itemstack, placer, pointed_thing)
--places balloon if the clicked thing is a node and the above node is air
if pointed_thing.type == "node"
and get_node (pointed_thing.above).name == "air"
then
if not is_in_creative(placer:get_player_name())
then
itemstack:take_item()
end
local pos_to_place = pointed_thing.above
pos_to_place.y = pos_to_place.y - 0.5 --subtracting 0.5 to place on ground
add_entity(pointed_thing.above, object_name)
end
--add remaining items to inventory
return itemstack
end
}
end
--registering the balloon entity, item and recepies
minetest.register_entity(hot_air_balloons.get_entity(
"hot_air_balloons:balloon",
"hot_air_balloons_balloon.obj",
"hot_air_balloons_balloon_model.png"))
minetest.register_craftitem(hot_air_balloons.get_item(
"hot_air_balloons:item",
minetest.translate("hot_air_balloons", "Hot Air Balloon"),
"hot_air_balloons_balloon.png",
"hot_air_balloons:balloon"))
dofile(modpath .. "/craft.lua")

View File

@ -0,0 +1,54 @@
License of source code
----------------------
GNU Lesser General Public License, version 2.1
Copyright (C) 2019 NetherEran
This program is free software; you can redistribute it and/or modify it under the terms
of the GNU Lesser General Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details:
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
Licenses of media (textures, models and sounds)
-----------------------------------------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
Copyright (C) 2010-2018:
NetherEran
BlockMen
sofar
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/

View File

@ -0,0 +1,2 @@
# textdomain:hot_air_balloons
Hot Air Balloon=Heißluftballon

View File

@ -0,0 +1,2 @@
# textdomain:hot_air_balloons
Hot Air Balloon=Globo Aerostático

View File

@ -0,0 +1,2 @@
# textdomain:hot_air_balloons
Hot Air Balloon=Balon cu aer cald

View File

@ -0,0 +1,4 @@
name = hot_air_balloons
author = Eran
description = Adds craftable and controllable hot air balloons.
optional_depends = default, bucket, mcl_buckets, mcl_mobitems, mcl_core

Binary file not shown.

View File

@ -0,0 +1,485 @@
# Blender v2.79 (sub 0) OBJ File: 'balloon.blend'
# www.blender.org
mtllib hot_air_balloons_balloon.mtl
o Cube.001
v -19.500000 44.216793 19.500000
v -19.500000 83.216797 19.500000
v -19.500000 44.216793 -19.500000
v -19.500000 83.216797 -19.500000
v 19.500000 44.216793 19.500000
v 19.500000 83.216797 19.500000
v 19.500000 44.216793 -19.500000
v 19.500000 83.216797 -19.500000
v -6.500000 0.016788 6.500000
v 6.500000 0.016788 6.500000
v -6.500000 0.016788 -6.500000
v 6.500000 0.016788 -6.500000
v -6.500000 1.441189 6.500000
v 6.500000 1.441189 6.500000
v -6.500000 1.441189 -6.500000
v 6.500000 1.441189 -6.500000
v -6.500000 0.016788 -4.550000
v -6.500000 0.016788 4.550000
v 6.500000 0.016788 4.550000
v 6.500000 0.016788 -4.550000
v -6.500000 1.441189 -4.550000
v -6.500000 1.441189 4.550000
v 6.500000 1.441189 4.550000
v 6.500000 1.441189 -4.550000
v -4.550000 0.016788 6.500000
v 4.550000 0.016788 6.500000
v 4.550000 0.016788 -6.500000
v -4.550000 0.016788 -6.500000
v -4.550000 1.441189 6.500000
v 4.550000 1.441189 6.500000
v 4.550000 1.441189 -6.500000
v -4.550000 1.441189 -6.500000
v 4.550000 1.441189 4.550000
v -4.550000 1.441189 4.550000
v -4.550000 1.441189 -4.550000
v -4.550000 0.016788 4.550000
v 4.550000 0.016788 4.550000
v -4.550000 0.016788 -4.550000
v 4.550000 0.016788 -4.550000
v 6.500000 11.077995 6.500000
v -6.500000 11.077995 6.500000
v 6.500000 11.077995 6.500000
v -6.500000 11.077995 -6.500000
v -6.500000 11.077995 6.500000
v 6.500000 11.077995 -6.500000
v 4.550000 11.077995 4.550000
v 4.550000 11.077995 -4.550000
v -4.550000 11.077995 -4.550000
v -4.550000 11.077995 -4.550000
v -4.550000 1.441189 -4.550000
v 4.550000 1.441189 -4.550000
v 4.550000 11.077995 -4.550000
v -4.550000 11.077995 4.550000
v 4.550000 1.441189 4.550000
v 6.500000 1.441189 -6.500000
v 4.550000 11.077995 4.550000
v -4.550000 11.077995 -6.500000
v -6.500000 1.441189 -6.500000
v 4.550000 11.077995 -6.500000
v 4.550000 11.077995 6.500000
v -4.550000 11.077995 6.500000
v 6.500000 11.077995 -4.550000
v 6.500000 1.441189 6.500000
v 6.500000 11.077995 4.550000
v -6.500000 11.077995 4.550000
v -6.500000 11.077995 -4.550000
v -6.500000 1.441189 6.500000
v 6.500000 11.077995 -6.500000
v -6.500000 11.077995 -6.500000
v 5.586319 8.609333 -5.559702
v 11.988016 44.915165 -12.060156
v 5.537368 8.331722 -7.158404
v 11.939065 44.637550 -13.658857
v 7.185020 8.327442 -5.559702
v 13.586718 44.633270 -12.060156
v 7.136070 8.049831 -7.158404
v 13.537767 44.355656 -13.658857
v -5.586318 8.609333 -5.559702
v -11.988014 44.915165 -12.060155
v -5.537367 8.331722 -7.158404
v -11.939065 44.637554 -13.658857
v -7.185020 8.327442 -5.559702
v -13.586717 44.633270 -12.060155
v -7.136071 8.049831 -7.158404
v -13.537764 44.355656 -13.658857
v 5.586319 8.609337 5.559702
v 11.988015 44.915161 12.060157
v 5.537368 8.331722 7.158404
v 11.939065 44.637547 13.658860
v 7.185020 8.327442 5.559702
v 13.586717 44.633270 12.060157
v 7.136070 8.049831 7.158404
v 13.537766 44.355652 13.658860
v -5.586318 8.609337 5.559702
v -11.988016 44.915161 12.060155
v -5.537367 8.331722 7.158405
v -11.939065 44.637550 13.658857
v -7.185019 8.327442 5.559704
v -13.586717 44.633266 12.060157
v -7.136071 8.049831 7.158405
v -13.537766 44.355652 13.658860
vt 0.666667 0.666667
vt 0.333333 0.666667
vt 0.333333 0.333333
vt 0.666667 0.333333
vt 0.000000 1.000000
vt 0.000000 0.666667
vt 0.333333 0.666667
vt 0.333333 1.000000
vt 0.333333 0.333333
vt 0.000000 0.333333
vt 0.000000 0.000000
vt 0.333333 0.000000
vt 0.333333 0.333333
vt 0.333333 0.000000
vt 0.666667 0.000000
vt 0.666667 0.333333
vt 0.000000 0.666667
vt 0.000000 0.333333
vt 0.333333 0.666667
vt 0.666667 0.000000
vt 1.000000 0.000000
vt 1.000000 0.333333
vt 0.666667 0.333333
vt 0.350615 0.683822
vt 0.333949 0.683822
vt 0.333949 0.667155
vt 0.350615 0.667155
vt 0.761207 0.649225
vt 0.761207 0.665892
vt 0.749033 0.665892
vt 0.749033 0.649225
vt 0.761207 0.427778
vt 0.761207 0.444444
vt 0.749033 0.444444
vt 0.749033 0.427778
vt 0.538985 0.761111
vt 0.538985 0.777778
vt 0.526810 0.777778
vt 0.526810 0.761111
vt 0.667442 0.461111
vt 0.667442 0.444444
vt 0.679616 0.444444
vt 0.679616 0.461111
vt 0.667442 0.555556
vt 0.667442 0.538889
vt 0.679616 0.538889
vt 0.679616 0.555556
vt 0.761207 0.555556
vt 0.761207 0.572222
vt 0.749033 0.572222
vt 0.749033 0.555556
vt 0.761207 0.650000
vt 0.749033 0.650000
vt 0.749420 0.427778
vt 0.749420 0.444444
vt 0.667054 0.444444
vt 0.667054 0.427778
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.445060 0.683822
vt 0.428393 0.683822
vt 0.428393 0.667155
vt 0.445060 0.667155
vt 0.428393 0.777778
vt 0.350615 0.777778
vt 0.350615 0.761111
vt 0.428393 0.761111
vt 0.350615 0.683333
vt 0.428393 0.683333
vt 0.445060 0.777778
vt 0.445060 0.761111
vt 0.445060 0.683333
vt 0.749420 0.555556
vt 0.749420 0.572222
vt 0.667054 0.572222
vt 0.667054 0.555556
vt 0.616763 0.749521
vt 0.538985 0.749521
vt 0.538985 0.667155
vt 0.616763 0.667155
vt 0.750035 0.334724
vt 0.750035 0.351390
vt 0.667669 0.351390
vt 0.667669 0.334724
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.538985 0.667362
vt 0.538985 0.684029
vt 0.526810 0.684029
vt 0.526810 0.667362
vt 0.538985 0.683333
vt 0.526810 0.683333
vt 0.761822 0.334724
vt 0.761822 0.351390
vt 0.749648 0.351390
vt 0.749648 0.334724
vt 0.761207 0.350000
vt 0.749033 0.350000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.333949 0.777778
vt 0.333949 0.761111
vt 0.333949 0.683333
vt 0.744444 0.749033
vt 0.666667 0.749033
vt 0.666667 0.666667
vt 0.744444 0.666667
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.744444 0.666667
vt 0.822222 0.666667
vt 0.822222 0.749033
vt 0.744444 0.749033
vt 0.444445 0.777778
vt 0.444445 0.761111
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.616763 0.777778
vt 0.616763 0.666667
vt 0.633429 0.666667
vt 0.633429 0.777778
vt 0.616763 0.831398
vt 0.538985 0.831398
vt 0.538985 0.749033
vt 0.616763 0.749033
vt 0.444445 0.683333
vt 0.749420 0.650000
vt 0.667054 0.650000
vt 0.678841 0.538889
vt 0.678841 0.461111
vt 0.761207 0.461111
vt 0.761207 0.538889
vt 0.749420 0.649225
vt 0.749420 0.665892
vt 0.667054 0.665892
vt 0.667054 0.649225
vt 0.678841 0.555556
vt 0.761207 0.555556
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.678841 0.444444
vt 0.761207 0.444444
vt 0.749420 0.350000
vt 0.667054 0.350000
vt 0.000000 0.000000
vt 0.000000 0.000000
vt 0.444445 0.684029
vt 0.444445 0.667362
vt 0.633429 0.666667
vt 0.650096 0.666667
vt 0.650096 0.777778
vt 0.633429 0.777778
vt 0.744444 0.749033
vt 0.761111 0.749033
vt 0.761111 0.826810
vt 0.744444 0.826810
vt 0.777778 0.749033
vt 0.777778 0.826810
vt 0.761111 0.826810
vt 0.761111 0.749033
vt 0.666667 0.749033
vt 0.744444 0.749033
vt 0.744444 0.826810
vt 0.666667 0.826810
vt 0.858286 0.648647
vt 0.858286 0.333406
vt 0.872154 0.333333
vt 0.872154 0.648574
vt 0.941529 0.333333
vt 0.941529 0.648427
vt 0.927654 0.648427
vt 0.927654 0.333333
vt 0.844417 0.333406
vt 0.844417 0.648647
vt 0.830549 0.648574
vt 0.830549 0.333333
vt 0.955404 0.333333
vt 0.955404 0.648427
vt 0.941529 0.648427
vt 0.941529 0.333333
vt 0.650096 0.694844
vt 0.663754 0.695262
vt 0.663754 0.708933
vt 0.650096 0.708515
vt 0.663754 0.722603
vt 0.650096 0.723022
vt 0.650096 0.709351
vt 0.663754 0.708933
vt 0.844417 0.333333
vt 0.858286 0.333406
vt 0.858286 0.648647
vt 0.844417 0.648574
vt 0.913779 0.333333
vt 0.927654 0.333333
vt 0.927654 0.648427
vt 0.913779 0.648427
vt 0.830549 0.648574
vt 0.816681 0.648647
vt 0.816681 0.333406
vt 0.830549 0.333333
vt 0.886029 0.648427
vt 0.872154 0.648427
vt 0.872154 0.333333
vt 0.886029 0.333333
vt 0.650096 0.694844
vt 0.650096 0.681174
vt 0.663754 0.680755
vt 0.663754 0.694426
vt 0.650096 0.750781
vt 0.650096 0.737110
vt 0.663754 0.737528
vt 0.663754 0.751199
vt 0.802812 0.648647
vt 0.788944 0.648574
vt 0.788944 0.333333
vt 0.802812 0.333406
vt 0.886029 0.648427
vt 0.899904 0.648427
vt 0.899904 0.963520
vt 0.886029 0.963520
vt 0.762184 0.333406
vt 0.776052 0.333333
vt 0.776052 0.648574
vt 0.762183 0.648647
vt 0.913779 0.648426
vt 0.899904 0.648427
vt 0.899904 0.333333
vt 0.913779 0.333333
vt 0.650096 0.765288
vt 0.650096 0.751617
vt 0.663754 0.751199
vt 0.663754 0.764869
vt 0.650096 0.680337
vt 0.650096 0.666667
vt 0.663754 0.667085
vt 0.663754 0.680755
vt 0.816681 0.333333
vt 0.816681 0.648574
vt 0.802812 0.648647
vt 0.802812 0.333406
vt 0.886029 0.648427
vt 0.886029 0.333333
vt 0.899904 0.333333
vt 0.899904 0.648426
vt 0.788944 0.333406
vt 0.788944 0.648647
vt 0.775075 0.648574
vt 0.775075 0.333333
vt 0.872154 0.963520
vt 0.872154 0.648427
vt 0.886029 0.648427
vt 0.886029 0.963520
vt 0.650096 0.723022
vt 0.663754 0.723440
vt 0.663754 0.737110
vt 0.650096 0.736692
vt 0.774865 0.662317
vt 0.761207 0.662735
vt 0.761207 0.649065
vt 0.774865 0.648647
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -0.9848 0.1736 0.0000
vn -0.0302 -0.1710 -0.9848
vn 0.9848 -0.1736 0.0000
vn 0.0302 0.1710 0.9848
vn -0.1710 -0.9698 0.1736
vn 0.1710 0.9698 -0.1736
vn 0.9848 0.1736 -0.0000
vn 0.0302 -0.1710 -0.9848
vn -0.9848 -0.1736 -0.0000
vn -0.0302 0.1710 0.9848
vn 0.1710 -0.9698 0.1736
vn -0.1710 0.9698 -0.1737
vn -0.0302 -0.1710 0.9848
vn 0.0302 0.1710 -0.9848
vn -0.1710 -0.9698 -0.1736
vn 0.1710 0.9698 0.1737
vn 0.0302 -0.1710 0.9848
vn -0.0302 0.1710 -0.9848
vn 0.1710 -0.9698 -0.1736
vn -0.1710 0.9698 0.1736
usemtl None
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/17/5 7/18/5 5/13/5 1/19/5
f 8/20/6 4/21/6 2/22/6 6/23/6
f 39/24/5 27/25/5 12/26/5 20/27/5
f 18/28/1 9/29/1 13/30/1 22/31/1
f 28/32/2 11/33/2 15/34/2 32/35/2
f 26/36/4 10/37/4 14/38/4 30/39/4
f 20/40/3 12/41/3 16/42/3 24/43/3
f 10/44/3 19/45/3 23/46/3 14/47/3
f 19/45/3 20/40/3 24/43/3 23/46/3
f 11/48/1 17/49/1 21/50/1 15/51/1
f 17/49/1 18/52/1 22/53/1 21/50/1
f 32/54/2 15/55/2 69/56/2 57/57/2
f 15/58/4 58/59/4 43/60/4 69/61/4
f 26/62/5 37/63/5 19/64/5 10/65/5
f 37/63/5 39/24/5 20/27/5 19/64/5
f 18/66/5 17/67/5 38/68/5 36/69/5
f 36/69/5 38/68/5 39/70/5 37/71/5
f 9/72/5 18/66/5 36/69/5 25/73/5
f 25/73/5 36/69/5 37/71/5 26/74/5
f 15/75/1 21/76/1 66/77/1 69/78/1
f 51/79/2 50/80/2 48/81/2 47/82/2
f 16/83/2 31/84/2 59/85/2 68/86/2
f 52/87/4 56/88/4 46/89/4 47/90/4
f 9/91/4 25/92/4 29/93/4 13/94/4
f 25/95/4 26/36/4 30/39/4 29/96/4
f 12/97/2 27/98/2 31/99/2 16/100/2
f 27/101/2 28/32/2 32/35/2 31/102/2
f 49/103/4 52/87/4 47/90/4 48/104/4
f 17/67/5 11/105/5 28/106/5 38/68/5
f 38/68/5 28/106/5 27/107/5 39/70/5
f 34/108/4 33/109/4 56/110/4 53/111/4
f 13/112/4 67/113/4 41/114/4 44/115/4
f 16/116/4 55/117/4 45/118/4 68/119/4
f 54/120/3 51/121/3 47/122/3 46/123/3
f 30/39/4 14/38/4 40/124/4 60/125/4
f 14/126/4 63/127/4 42/128/4 40/129/4
f 44/130/6 42/131/6 64/132/6 65/133/6
f 35/134/1 34/135/1 53/136/1 49/137/1
f 29/96/4 30/39/4 60/125/4 61/138/4
f 21/76/1 22/139/1 65/140/1 66/77/1
f 23/141/3 24/142/3 62/143/3 64/144/3
f 22/145/1 13/146/1 44/147/1 65/148/1
f 14/149/3 23/141/3 64/144/3 40/150/3
f 50/151/4 35/152/4 49/103/4 48/104/4
f 24/142/3 16/153/3 68/154/3 62/143/3
f 31/155/2 32/54/2 57/57/2 59/156/2
f 33/157/4 54/158/4 46/89/4 56/88/4
f 13/94/4 29/93/4 61/159/4 44/160/4
f 62/161/6 68/162/6 69/163/6 66/164/6
f 62/165/6 52/166/6 56/167/6 64/168/6
f 66/169/6 65/170/6 53/171/6 49/172/6
f 51/173/5 54/174/5 34/175/5 50/176/5
f 70/177/7 71/178/7 73/179/7 72/180/7
f 72/181/8 73/182/8 77/183/8 76/184/8
f 76/185/9 77/186/9 75/187/9 74/188/9
f 74/189/10 75/190/10 71/191/10 70/192/10
f 72/193/11 76/194/11 74/195/11 70/196/11
f 77/197/12 73/198/12 71/199/12 75/200/12
f 78/201/13 80/202/13 81/203/13 79/204/13
f 80/205/14 84/206/14 85/207/14 81/208/14
f 84/209/15 82/210/15 83/211/15 85/212/15
f 82/213/16 78/214/16 79/215/16 83/216/16
f 80/217/17 78/218/17 82/219/17 84/220/17
f 85/221/18 83/222/18 79/223/18 81/224/18
f 86/225/7 88/226/7 89/227/7 87/228/7
f 88/229/19 92/230/19 93/231/19 89/232/19
f 92/233/9 90/234/9 91/235/9 93/236/9
f 90/237/20 86/238/20 87/239/20 91/240/20
f 88/241/21 86/242/21 90/243/21 92/244/21
f 93/245/22 91/246/22 87/247/22 89/248/22
f 94/249/13 95/250/13 97/251/13 96/252/13
f 96/253/23 97/254/23 101/255/23 100/256/23
f 100/257/15 101/258/15 99/259/15 98/260/15
f 98/261/24 99/262/24 95/263/24 94/264/24
f 96/265/25 100/266/25 98/267/25 94/268/25
f 101/269/26 97/270/26 95/271/26 99/272/26

View File

@ -0,0 +1,209 @@
--localize global functions
local vector_new = vector.new
local math_hypot = math.hypot
local atan = math.atan
local cos = math.cos
local sin = math.sin
local abs = math.abs
local pi = math.pi
local min = math.min
--max speed settings
local max_ballooning_vertical_speed = 1
local max_ballooning_horizontal_speed = 3
local function is_water_is_air(pos)
local node_name = minetest.get_node(pos).name
return minetest.get_item_group(node_name, "water") > 0,
node_name == "air"
end
local function get_vertical_acceleration(self)
local heat = self.heat
local vel_y = self.object:getvelocity().y
local acc_candidate = heat / 1000 - 0.5
--enforce max speed
if vel_y > max_ballooning_vertical_speed
and acc_candidate * vel_y > 0
then
return 0
else
return acc_candidate
end
end
--if balloon is submerged
local function float_up(self, vel)
self.submerged = true
vel.y = 1
return vel
end
local function swim(self, vel)
--allow controls, allow up
local pos = self.object:get_pos()
--keep y constant or rising
local acc_y = get_vertical_acceleration(self)
if self.submerged or acc_y < 0
then
self.submerged = false
vel.y = 0
return 0, vel
else
return acc_y, vel
end
end
local tau = pi * 2
--returns the radian equivalent of a in the range [0, tau)
local function to_radian(a)
if a < 0
then
return to_radian(a + tau)
elseif a >= tau
then
return to_radian(a - tau)
else
return a
end
end
--decides which is the shortest way to rotate towards where the player is looking
local function get_rotate_direction(a, b)
return to_radian(a - b) < to_radian(b - a)
end
--rotates the balloon towards where the player is looking
local pi_192ths = pi / 192 --radians to turn each step
local function rotate(self, player)
-- + pi so it finishes rotating when looking towards where the player is looking
local player_yaw = player:get_look_horizontal() + pi
local self_yaw = self.object:getyaw()
if get_rotate_direction(player_yaw, self_yaw)
then
self.object:setyaw(to_radian(self_yaw - pi_192ths))
else
self.object:setyaw(to_radian(self_yaw + pi_192ths))
end
end
--takes wasd and turns it into a 2d vector
local pi_halves = pi / 2
function get_direction(right, left, up, down)
local inline, cross = 0, 0
local move = right or left or up or down
if left then cross = 1 end
if right then cross = cross - 1 end
if up then inline = 1 end
if down then inline = inline - 1 end
local arg
if inline < 0
then
return atan(cross / inline) + pi, move
elseif inline > 0
then
return atan(cross / inline), move
else
return pi_halves * cross, move
end
end
--[[
space to rotate where the player is looking
wasd to apply acceleration
shift to let out hot air, cooling the balloon
]]
local function handle_control(self, vel)
if not self.pilot
then
return 0, 0
end
local player = minetest.get_player_by_name(self.pilot)
if not player --player left, balloon should get deleted
then
return 0, 0
end
local control = player:get_player_control()
if control.sneak --lowering heat quickly
then
local heat = self.heat - 30
if heat < 0
then
self.heat = 0
else
self.heat = heat
end
end
if control.jump --rotate towards player yaw
then
rotate(self, player)
end
--taking direction from get_direction
--and turning it into radians.
--if max speed is reached, only acceleration in the opposite direction is applied.
local dir_radians, move = get_direction(control.right, control.left, control.up, control.down)
if move and math_hypot(vel.x, vel.z)
then
dir_radians = dir_radians + player:get_look_horizontal()
local x, z = -sin(dir_radians), cos(dir_radians)
if math_hypot(vel.x, vel.z) > max_ballooning_horizontal_speed
then
if x * vel.x > 0
then
x = 0
end
if z * vel.z > 0
then
z = 0
end
end
return x, z
end
return 0, 0
end
--[[handle movement in different cases
movement restrictions:
-on ground: only vertical movement
-on water: free movement, though vertical only if up
-submerged: free movement, vertical goes up automatically
-in air: completely free movement
]]
return function(self)
local pos_in = self.object:get_pos()
local pos_under = vector_new(pos_in.x, pos_in.y - 0.1, pos_in.z)
local on_water, in_air = is_water_is_air(pos_under)
local acc = vector_new(0, 0, 0)
local vel = self.object:getvelocity()
if is_water_is_air(pos_in) --if submerged
then
vel = float_up(self, vel)
acc.x, acc.z = handle_control(self, vel)
self.object:setvelocity(vel)
elseif on_water --if on water
then
acc.y, vel = swim(self, vel)
self.object:setvelocity(vel)
acc.x, acc.z = handle_control(self, vel)
elseif in_air
then
--allow controls and height change
acc.y = get_vertical_acceleration(self)
acc.x, acc.z = handle_control(self, vel)
else --if on ground
--only allow height change
acc.y = get_vertical_acceleration(self)
vel.x = 0
vel.z = 0
self.object:setvelocity(vel)
end
self.object:setacceleration(acc)
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B