This commit is contained in:
natey2000 2025-04-11 17:53:58 -06:00
commit f5aae11a27
10 changed files with 258 additions and 176 deletions

View file

@ -1,19 +1,42 @@
[![ContentDB](https://content.luanti.org/packages/Sumianvoice/sum_airship/shields/downloads/)]
# sum_airship
Mod for minetest
[ContentDB](https://content.minetest.net/packages/Sumianvoice/sum_airship/)
Mod for [Luanti](https://luanti.org). You can download it from the in-game content manager, or [ContentDB](https://content.luanti.org/packages/Sumianvoice/sum_airship/).
This mod adds an airship to Minetest. It should work in most games, but only Minetest Game, MineClone (VoxeLibre) and RePixture are supported for crafting recipes. Games based on those may still have crafting if they use the same items. Other games are not because the mod doesn't know what each game calls each item or node. Although, it shouldn't crash no matter what game you use, this is only for crafting recipes.
**Controls:** Flies like a boat, WASD, jump and aux1 (sprint) for up and down. Shift to dismount. Does not require fuel but will go faster when given any type of coal.
This adds an airship to minetest_game or mcl2. Not tested on any other games. If it uses default:steel_ingot or mcl_core:iron_ingot for example, then it should work. It should not crash no matter what game you use though, this is only for the crafting recipes. The dependency on MTG or MCL2 is only for crafting, otherwise the ship it self can still be used just not crafted (because I don't know what your game calls each item / node etc)
### Crafting
Flies like a boat, WSAD controls with the addition of jump for up, sneak for down, and aux1 (sprint) to dismount. Does not require fuel but will go faster when given any type of coal.
### Crafting (mcl)
#### MineClon\* (VoxeLibre)
Craftable with wool > canvas and boats > hull. All items: wool: 27, string: 4, wood: 15, iron_ingot: 4
All items: wool: 27, string: 4, wood: 15, iron_ingot: 4
9 Wool -> Canvas
3 Boats & 3 Iron Ingots -> Hull
3 Canvas, 1 Hull, 4 String & 1 Iron ingot -> Airship
![MCL crafting.gif](crafting_mcl.gif)
#### Minetest Game
All items: wool: 27, string: 4, wood: 15, iron_ingot: 4
9 Wool -> Canvas
3 Boats & 3 Iron Ingots -> Hull
3 Canvas, 1 Hull, 4 String & 1 Iron ingot -> Airship
![MTG crafting.gif](crafting_mtg.gif)
#### RePixture
All items: wool: 27, fiber: 8, wood: varies depending on boat type, steel_ingot: 4
9 group:fuzzy (wool or cotton bale) -> Canvas
3 Boats & 3 Steel Ingots -> Hull
3 Canvas, 1 Hull, 8 Fiber, 1 Steel Ingot -> Airship
![RePixture crafting.gif](crafting_rp.gif)
#### Crafting Guide GIF:
![airship%20crafting.gif](airship%20crafting.gif)
### Air Currents
This optionally uses [sum_air_currents](https://content.minetest.net/packages/Sumianvoice/sum_air_currents/) to apply force based on the weather. Both this mod and the air currents mod are in development so expect changes made regularly.
This optionally uses [sum_air_currents](https://content.luanti.org/packages/Sumianvoice/sum_air_currents/) to apply force based on the weather.

View file

@ -2,23 +2,25 @@ local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)
local me = {
lift = 4,
speed = 4,
fuel_time = 10,
speed_mult = 4,
i = {},
lift = 4,
speed = 4,
fuel_time = 10,
speed_mult = 4,
i = {},
}
local ship = {
physical = true,
pointable = true,
collisionbox = {-0.6, -0.2, -0.6, 0.6, 0.3, 0.6},
selectionbox = {-0.7, -0.35, -0.7, 0.7, 0.3, 0.7},
hp_max = 3,
visual = "mesh",
backface_culling = false,
mesh = "sum_airship.b3d",
textures = {"sum_airship_texture.png"},
initial_properties = {
physical = true,
pointable = true,
collisionbox = {-0.6, -0.2, -0.6, 0.6, 0.4, 0.6},
selectionbox = {-0.7, -0.35, -0.7, 0.7, 0.4, 0.7},
hp_max = 3,
visual = "mesh",
backface_culling = true,
mesh = "sum_airship.b3d",
textures = {"sum_airship_texture.png"},
},
_animations = {
idle = {x= 10, y= 90},
fly = {x= 91, y= 170},
@ -26,8 +28,8 @@ local ship = {
},
_driver = nil,
_removed = false,
_flags = {},
_itemstring = "sum_airship:boat",
_flags = {},
_itemstring = "sum_airship:boat",
_passenger = nil,
_vel = 0,
_regen_timer = 0,
@ -88,7 +90,7 @@ function me.sound_countdown(self, dtime)
end
function me.update_sound(self, dtime, forward)
me.sound_countdown(self, dtime)
me.sound_countdown(self, dtime)
local is_thrust = (forward ~= 0) and self._driver
@ -128,15 +130,17 @@ function ship.on_activate(self, staticdata, dtime_s)
self._vel = data.v
self._itemstring = data.itemstring
self._fuel = data.fuel
if data._driver then
self._driver = minetest.get_player_by_name((data._driver))
else
self._driver = nil
end
self._flags = data._flags
if self._driver then me.detach(self) end
self._flags = data._flags
end
self.object:set_animation(ship._animations.idle, 24)
self.object:set_armor_groups({
pierce=100,
slash=100,
blunt=100,
magic=100,
poison=100,
fleshy=100,
})
self.object:set_animation(ship._animations.idle, 24)
self._sounds = { -- workaround for copy vs reference issue
engine = {
handle = nil,
@ -156,41 +160,39 @@ end
function ship.get_staticdata(self)
return minetest.serialize({
itemstring = self._itemstring,
_driver = ((self._driver and self._driver:is_player())
and self._driver:get_player_name()) or nil,
_flags = self._flags,
_flags = self._flags,
v = self._vel,
fuel = self._fuel,
})
end
function me.attach(self, player)
if not (player and player:is_player()) then
return false
end
if not (player and player:is_player()) then
return false
end
self._driver = player
self._driver:set_attach(self.object, "",
{x = 0, y = -3.0, z = 0}, {x = 0, y = 0, z = 0})
self._driver:set_look_horizontal(self.object:get_yaw())
self._driver:set_attach(self.object, "",
{x = 0, y = -0.0, z = -2}, {x = 0, y = 0, z = 0})
self._driver:set_look_horizontal(self.object:get_yaw())
end
function me.detach(self)
if not self._driver then return false end
self._driver:set_detach()
self._driver = nil
return true
if not self._driver then return false end
self._driver:set_detach()
self._driver = nil
return true
end
function ship.on_death(self, killer)
if killer and killer:is_player()
and not minetest.is_creative_enabled(killer:get_player_name()) then
and not minetest.is_creative_enabled(killer:get_player_name()) then
local inv = killer:get_inventory()
inv:add_item("main", self._itemstring)
else
minetest.add_item(self.object:get_pos(), self._itemstring)
end
me.detach(self)
me.detach(self)
self._driver = nil
end
@ -198,7 +200,7 @@ function ship.on_rightclick(self, clicker)
local item = clicker:get_wielded_item()
local item_name = item:get_name()
if clicker and (item and item_name)
and (string.find(item_name, ":coal")
and (string.find(item_name, ":coal")
or string.find(item_name, ":charcoal")) then
if not minetest.is_creative_enabled(clicker:get_player_name()) then
item:take_item()
@ -260,16 +262,16 @@ function me.get_balloon_collide(self)
for _, check in pairs(balloon_nodes) do
local n = minetest.get_node(vector.add(check.p, o))
if n and minetest.registered_nodes[n.name]
and minetest.registered_nodes[n.name].walkable then
and (minetest.registered_nodes[n.name] or {}).walkable then
force = vector.add(force, check.dir)
end
end
return force
end
me.chimney_dist = -1.0
me.chimney_dist = -0.8
me.chimney_yaw = 0.13
me.chimney_height = 0.9
me.chimney_height = 1.5
function me.get_chimney_pos(self)
local p = self.object:get_pos()
local yaw = self.object:get_yaw()
@ -281,50 +283,50 @@ function me.get_chimney_pos(self)
end
function ship.on_step(self, dtime, moveresult)
local exit = false
local pi = nil
-- allow to exit
if self._driver and self._driver:is_player() then
local name = self._driver:get_player_name()
pi = self._driver:get_player_control()
exit = pi.aux1
end
if exit then
me.detach(self)
return false
end
local exit = false
local pi = nil
-- allow to exit
if self._driver and self._driver:is_player() then
local name = self._driver:get_player_name()
pi = self._driver:get_player_control()
exit = pi.sneak
end
if exit then
me.detach(self)
return false
end
local climb = 0
local right = 0
local forward = 0
local v = self.object:get_velocity()
local p = self.object:get_pos()
local node_below = minetest.get_node(vector.offset(p, 0, -0.8, 0)).name
local is_on_floor = minetest.registered_nodes[node_below].walkable
local climb = 0
local right = 0
local forward = 0
local v = self.object:get_velocity()
local p = self.object:get_pos()
local node_below = minetest.get_node(vector.offset(p, 0, -0.8, 0)).name
local is_on_floor = (minetest.registered_nodes[node_below] or {}).walkable
local in_water = minetest.get_item_group(minetest.get_node(p).name, "liquid") ~= 0
local on_water = (minetest.get_item_group(minetest.get_node(vector.offset(p, 0, -0.2, 0)).name, "liquid") ~= 0 and not in_water)
local speedboost = 1
if self._fuel > 0 then
self._fuel = self._fuel - dtime
speedboost = 3
end
local speedboost = 1
if self._fuel > 0 then
self._fuel = self._fuel - dtime
speedboost = 3
end
if pi then
if pi.up then forward = 1
elseif pi.down then forward = -1 end
if pi.jump then climb = 1
elseif pi.sneak then climb = -1 end
if pi.right then right = 1
elseif pi.left then right = -1 end
if pi then
if pi.up then forward = 1
elseif pi.down then forward = -1 end
if pi.jump then climb = 1
elseif pi.aux1 then climb = -1 end
if pi.right then right = 1
elseif pi.left then right = -1 end
local yaw = self.object:get_yaw()
local dir = minetest.yaw_to_dir(yaw)
self.object:set_yaw(yaw - right * dtime)
local added_vel = vector.multiply(dir, forward * dtime * me.speed * speedboost)
added_vel.y = added_vel.y + (climb * dtime * me.lift)
v = vector.add(v, added_vel)
end
local yaw = self.object:get_yaw()
local dir = minetest.yaw_to_dir(yaw)
self.object:set_yaw(yaw - right * dtime)
local added_vel = vector.multiply(dir, forward * dtime * me.speed * speedboost)
added_vel.y = added_vel.y + (climb * dtime * me.lift)
v = vector.add(v, added_vel)
end
if self._driver then
local collide_force = me.get_balloon_collide(self)
@ -335,32 +337,32 @@ function ship.on_step(self, dtime, moveresult)
v = vector.add(v, collide_force)
end
if not self._driver then
v.y = v.y - dtime
end
if not self._driver then
v.y = v.y - dtime
end
if sum_air_currents ~= nil then
if minetest.get_modpath("sum_air_currents") then
if self._driver or not is_on_floor then
local wind_vel = sum_air_currents.get_wind(p)
wind_vel = vector.multiply(wind_vel, dtime)
local wind_vel = sum_air_currents.get_wind(p)
wind_vel = vector.multiply(wind_vel, dtime)
v = vector.add(wind_vel, v)
end
end
if in_water then
v.y = 1
elseif on_water and not self._driver then
v.y = 0
end
if in_water then
v.y = 1
elseif on_water and not self._driver then
v.y = 0
end
if (not self._driver) and is_on_floor then
v.x = v.x * 0.8
v.y = v.y * 0.95
v.z = v.z * 0.8
else
v.x = v.x * (0.98)
v.y = v.y * (0.98)
v.z = v.z * (0.98)
end
if (not self._driver) and is_on_floor then
v.x = v.x * 0.8
v.y = v.y * 0.95
v.z = v.z * 0.8
else
v.x = v.x * (0.98)
v.y = v.y * (0.98)
v.z = v.z * (0.98)
end
local wind_vel = vector.new(0,0,0)
if minetest.get_modpath("sum_air_currents") ~= nil then
@ -371,7 +373,7 @@ function ship.on_step(self, dtime, moveresult)
end
self.object:set_velocity(v)
self.object:set_velocity(v)
me.update_sound(self, dtime, forward)
@ -407,31 +409,32 @@ minetest.register_entity("sum_airship:boat", ship)
minetest.register_craftitem("sum_airship:boat", {
description = "Airship",
inventory_image = "sum_airship.png",
groups = { vehicle = 1, airship = 1, transport = 1},
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
local node = minetest.get_node(pointed_thing.under)
if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
end
end
local pos = vector.offset(pointed_thing.above, 0, 0.5, 0)
local self = minetest.add_entity(pos, "sum_airship:boat"):get_luaentity()
if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item()
end
return itemstack
end,
inventory_image = "sum_airship.png",
groups = { vehicle = 1, airship = 1, transport = 1},
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
local node = minetest.get_node(pointed_thing.under)
if placer and not placer:get_player_control().sneak then
local def = minetest.registered_nodes[node.name]
if def and def.on_rightclick then
return def.on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
end
end
local pos = vector.offset(pointed_thing.above, 0, 0, 0)
local self = minetest.add_entity(pos, "sum_airship:boat"):get_luaentity()
if not minetest.is_creative_enabled(placer:get_player_name()) then
itemstack:take_item()
end
return itemstack
end,
})
-- Support SilverSandstone's subtitles mod:
if minetest.get_modpath("subtitles") then
subtitles.register_description('sum_airship_lip_trill', 'Engine purring');
subtitles.register_description('sum_airship_lip_trill_end', 'Engine sputtering');
subtitles.register_description('sum_airship_fire', 'Engine stoked');
subtitles.register_description('sum_airship_lip_trill', 'Engine purring');
subtitles.register_description('sum_airship_lip_trill_end', 'Engine sputtering');
subtitles.register_description('sum_airship_fire', 'Engine stoked');
end

View file

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

28
crafting_mcl.lua Normal file
View file

@ -0,0 +1,28 @@
local w = "group:wool"
local b = "group:boat"
local m = "mcl_core:iron_ingot"
local s = "mcl_mobitems:string"
minetest.register_craft({
output = "sum_airship:canvas_roll",
recipe = {
{w, w, w},
{w, w, w},
{w, w, w},
},
})
minetest.register_craft({
output = "sum_airship:hull",
recipe = {
{b, b, b},
{m, m, m},
},
})
minetest.register_craft({
output = "sum_airship:boat",
recipe = {
{"sum_airship:canvas_roll","sum_airship:canvas_roll","sum_airship:canvas_roll",},
{s, m, s,},
{s, "sum_airship:hull", s,},
},
})

BIN
crafting_mtg.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

29
crafting_mtg.lua Normal file
View file

@ -0,0 +1,29 @@
local w = "group:wool"
if not minetest.get_modpath("farming") then w = "default:paper" end
local b = "boats:boat"
local m = "default:steel_ingot"
local s = "farming:string"
minetest.register_craft({
output = "sum_airship:canvas_roll",
recipe = {
{w, w, w},
{w, w, w},
{w, w, w},
},
})
minetest.register_craft({
output = "sum_airship:hull",
recipe = {
{b, b, b},
{m, m, m},
},
})
minetest.register_craft({
output = "sum_airship:boat",
recipe = {
{"sum_airship:canvas_roll","sum_airship:canvas_roll","sum_airship:canvas_roll",},
{s, m, s,},
{s, "sum_airship:hull", s,},
},
})

BIN
crafting_rp.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

23
crafting_rp.lua Normal file
View file

@ -0,0 +1,23 @@
crafting.register_craft({
output = "sum_airship:canvas_roll",
items = {
"group:fuzzy 9"
}
})
crafting.register_craft({
output = "sum_airship:hull",
items = {
"group:boat 3",
"rp_default:ingot_steel 3"
}
})
crafting.register_craft({
output = "sum_airship:boat",
items = {
"sum_airship:canvas_roll 3",
"rp_default:ingot_steel 8",
"rp_default:ingot_steel",
"sum_airship:hull",
}
})

View file

@ -1,3 +1,5 @@
local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)
local S = minetest.get_translator(minetest.get_current_modname())
@ -16,43 +18,16 @@ minetest.register_craftitem("sum_airship:hull", {
groups = { craftitem = 1 },
})
local w = "group:wool"
if not minetest.get_modpath("farming") then w = "default:paper" end
local b = "boats:boat"
local m = "default:steel_ingot"
local s = "farming:string"
if minetest.get_modpath("mcl_boats")
and minetest.get_modpath("mcl_wool")
and minetest.get_modpath("mcl_core")
and minetest.get_modpath("mcl_mobitems") then
w = "group:wool"
b = "group:boat"
m = "mcl_core:iron_ingot"
s = "mcl_mobitems:string"
end
minetest.register_craft({
output = "sum_airship:canvas_roll",
recipe = {
{w, w, w},
{w, w, w},
{w, w, w},
},
})
minetest.register_craft({
output = "sum_airship:hull",
recipe = {
{b, b, b},
{m, m, m},
},
})
minetest.register_craft({
output = "sum_airship:boat",
recipe = {
{"sum_airship:canvas_roll","sum_airship:canvas_roll","sum_airship:canvas_roll",},
{s, m, s,},
{s, "sum_airship:hull", s,},
},
})
if minetest.get_modpath("mcl_boats")
and minetest.get_modpath("mcl_wool")
and minetest.get_modpath("mcl_core")
and minetest.get_modpath("mcl_mobitems") then
dofile(mod_path .. "/crafting_mcl.lua")
elseif (minetest.get_modpath("rp_farming")
or minetest.get_modpath("rp_mobs_mobs"))
and minetest.get_modpath("rp_default")
and minetest.get_modpath("rp_crafting") then
dofile(mod_path .. "/crafting_rp.lua")
elseif minetest.get_modpath("default") then
dofile(mod_path .. "/crafting_mtg.lua")
end

View file

@ -1,4 +1,5 @@
name = sum_airship
title = Airship (sum)
author = Sumi
description = airship
optional_depends = default, mcl_core, mcl_wool, mcl_mobitems, mcl_player
description = Adds a simple airship to Minetest Game, MineClone (VoxeLibre) and RePixture.
optional_depends = default, mcl_core, mcl_wool, mcl_mobitems, mcl_player, rp_crafting, rp_default