master
Extex101 2020-03-03 19:41:05 -08:00 committed by GitHub
parent c4d60fa494
commit f14dcdcfd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 533 additions and 0 deletions

17
LICENSE Normal file
View File

@ -0,0 +1,17 @@
Minetest mod: Motorbike [motorbike]
------------------------------------------------------------------------------
Some code taken from lib_mount by blert2112 (https://github.com/blert2112/lib_mount)
Code MIT (Extex101) 2020-
Melkor (CC-BY-NC-SA 3.0) <https://forum.minetest.net/memberlist.php?mode=viewprofile&u=301>
motorbike_body.b3d (Designed and textured by Melkor, rigged by Extex101 using .blend file provided here: https://forum.minetest.net/download/file.php?id=21223)
motorbike_blue.png
Extex101 (CC-BY-NC-SA 3.0)
motorbike_burnout.png
All other colours are edits of motorbike_blue.png by Melkor
motorbike_wheel_inv.png
motorbike_(colour)_imv.png (Render of Melkors bike)
motorbike_biker.b3d (Edited version of minetest player model from 3d_armor)

4
depends.txt Normal file
View File

@ -0,0 +1,4 @@
player_api
default
wool
signs?

387
functions.lua Normal file
View File

@ -0,0 +1,387 @@
local charset = {} do -- [A-Z]
for c = 65, 90 do table.insert(charset, string.char(c)) end
end
local numset = {} do -- [0-9]
for c = 48, 57 do table.insert(numset, string.char(c)) end
end
local function randomString(length)
local text = ""
local i = 0
if not length or length <= 0 then return text end
while i < length do
text = text..charset[math.random(1, #charset)]
i = i + 1
end
return text
end
local function randomNumber(length)
local text = ""
local i = 0
if not length or length <= 0 then return text end
while i < length do
text = text..numset[math.random(1, #numset)]
i = i + 1
end
return text
end
local function def_plate() return randomString(3).."-"..randomNumber(3) end
function biker.get_plate(name)
local custom_plates = {
Jely = {"Jely-"..randomNumber(2), def_plate()},
Elkien = {"Elk-"..randomNumber(3), def_plate()},
Bob12 = {"Bob-"..randomNumber(3), "Boi-"..randomNumber(3), "MB-"..randomNumber(4), "N1nja-"..randomNumber(3), def_plate()},
Extex = {"Ex-"..randomNumber(4), "Bullet-"..randomNumber(2), def_plate(), "3xt3x-"..randomNumber(2)},
Merlok = {"Mer-"..randomNumber(3), "Nipe-"..randomNumber(2), "M3RL0k-"..randomNumber(2), "N1P3-"..randomNumber(2), def_plate(), "Snoopy-"..randomNumber(3)},
Nipe = {"Nipe-"..randomNumber(2), "Snoopy-"..randomNumber(3), def_plate()},
--"The-Black-Knight" = {"TBK-"..randomNumber(3), "Vike-"randomNumber(2), "Rock-"..randomNumber(2), def_plate()},
Queen_Vibe = {"QV-"..randomNumber(3), "Vibe-"..randomNumber(2), def_plate()},
Melkor = {"Creator", "ModelKing", "Melkor", def_plate()},
Hype = {"Hobo-"..randomNumber(2), "Hyper-"..randomNumber(1), def_plate()}
}
if custom_plates[name] then
return custom_plates[name][math.random(#custom_plates[name])]
end
return def_plate()
end
player_api.register_model("motorbike_biker.b3d", {
animation_speed = 30,
textures = {"character.png", "blank.png"},
animations = {
-- Standard animations.
stand = {x = 0, y = 79},
lay = {x = 162, y = 166},
walk = {x = 168, y = 187},
mine = {x = 189, y = 198},
walk_mine = {x = 200, y = 219},
sit = {x = 81, y = 160},
},
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
stepheight = 0.6,
eye_height = 1.47,
})
local function repair(num, p)
p = p or 3
return math.floor(num*math.pow(10,p)+0.5) / math.pow(10,p)
end
local function node_is(pos)
local node = minetest.get_node(pos)
if node.name == "air" then
return "air"
end
if minetest.get_item_group(node.name, "liquid") ~= 0 then
return "liquid"
end
if minetest.get_item_group(node.name, "walkable") ~= 0 then
return "walkable"
end
return "other"
end
local function shortAngleDist(a0,a1)
local max = math.pi*2
local da = (a1 - a0) % max
return 2*da % max - da
end
local function lerp(a, b, t)
return a + (a - b) * t
end
local function angleLerp(a0,a1,t)
local result = repair(a0 + shortAngleDist(a0,a1)*t)
if math.floor(result) == a1 then
return a1
end
return result
end
local function get_sign(i)
i = i or 0
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
function biker.turn_check(lerp, dest, range)
if math.floor(lerp) <= (dest-(math.rad(90)))-range then return true end
if math.floor(lerp) >= (dest-(math.rad(90)))+range then return true end
return false
end
function biker.clamp(value, min, max)
return math.min(math.max(value, min), max)
end
function biker.dist(v1, v2)
--if v1 - v2 > -math.rad(45) and v1 - v2 < math.rad(45) then return v1 - v2 end
return biker.clamp(-shortAngleDist(v1, v2), math.rad(-55), math.rad(55))
end
local function force_detach(player)
local attached_to = player:get_attach()
if not player:is_player() then return end
if attached_to then
local entity = attached_to:get_luaentity()
if entity.driver and entity.driver == player then
entity.driver = nil
end
local name = player:get_player_name()
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0}, {x=0, y=0, z=0})
if entity.info then
player_api.set_model(player, entity.info.model)
end
end
end
function biker.detach(player, crash)
force_detach(player)
player_api.player_attached[player:get_player_name()] = false
player_api.set_animation(player, "stand" , 30)
if crash then
end
end
function biker.wheelspeed(bike)
--if true then return end
if not bike then return end
if not bike.wheels then return end
if not bike.object then return end
if not bike.object:getvelocity() then return end
local direction = 1
if bike.v then
direction = get_sign(bike.v)
end
local v = get_v(bike.object:get_velocity())
local fps = v*4
bike.object:set_animation({x=1, y=20}, fps*direction, 0, true)
if v ~= 0 then
local i = 16
while true do
if i/fps > 1 then i = i/2 else break end
end
minetest.after(i/fps, biker.wheelspeed, bike)
end
end
function biker.attach(entity, player, is_passenger)
local attach_at, eye_offset = {}, {}
if not entity then
return
end
if entity.driver then return end
if not player:is_player() then
return
end
local name = player:get_player_name()
if not entity.driver_attach_at then
entity.driver_attach_at = {x=0, y=1.1, z=0.9}
end
if not entity.driver_eye_offset then
entity.driver_eye_offset = {x=0, y=-2.2, z=0.3}
end
attach_at = entity.driver_attach_at
eye_offset = entity.driver_eye_offset
entity.driver = player
local props = player:get_properties()
entity.info = {}
entity.info.model = player_api.get_animation(player).model
if props.textures[2] == nil then
props.textures[2] = "blank.png"
end
force_detach(player)
player:set_attach(entity.object, "", attach_at, entity.player_rotation)
player_api.player_attached[player:get_player_name()] = true
player:set_eye_offset(eye_offset, {x=0, y=0, z=0})
minetest.after(0.2, function()
player_api.set_model(player, "motorbike_biker.b3d")
end)
player:set_look_yaw(entity.object:getyaw())
end
local timer = 0
function biker.drive(entity, dtime)
timer = timer + dtime
local rot_steer, rot_view = math.pi/2, 0
local acce_y = 2
local velo = entity.object:getvelocity()
entity.v = get_v(velo) * get_sign(entity.v)
-- process controls
if entity.driver then
if entity.v then
local newv = entity.object:getvelocity()
if not entity.crash then entity.crash = false end
local crash = false
if math.abs(entity.lastv.x) > 5 and newv.x == 0 then crash = true end
if math.abs(entity.lastv.y) > 10 and newv.y == 0 then crash = true end
if math.abs(entity.lastv.z) > 5 and newv.z == 0 then crash = true end
if crash and not entity.crash then
entity.crash = true
minetest.after(.5, function()
entity.crash = false
end)
return
end
end
if not entity.wheelie then
entity.wheelie = 0
end
if not entity.lastv then
entity.lastv = {x=0,y=0,z=0}
end
local rots = entity.object:get_rotation()
local j = rots.y
local k = rots.x
local newrot = j
local rrot = entity.driver:get_look_yaw() - rot_steer
local ctrl = entity.driver:get_player_control()
if ctrl.up and not ctrl.sneak then
if get_sign(entity.v) >= 0 then
entity.v = entity.v + biker.acceleration/10
else
entity.v = entity.v + biker.acceleration/10
end
elseif ctrl.down then
if biker.max_reverse == 0 and entity.v == 0 then return end
if get_sign(entity.v) < 0 then
entity.v = entity.v - biker.acceleration/10
else
entity.v = entity.v - biker.braking/10
end
end
if ctrl.down and ctrl.sneak and not ctrl.jump and biker.turn_check(angleLerp(newrot, rrot, biker.turn_power)%math.rad(360), rrot, 3.2) then
if get_sign(entity.v) < 0 then
entity.v = entity.v - biker.acceleration/10
elseif get_sign(entity.v) > 0 and entity.v > (biker.max_speed/10)-1 then
entity.v = entity.v - biker.braking/10
local num = 1
local pos = entity.object:getpos()
local d = 0.2
for i = 0, 20, 1 do
local time = math.random(1, 2)
minetest.add_particle({
pos = {x=pos.x+math.random(-d, d),y = pos.y+math.random(0, d), z= pos.z+math.random(-d, d)},
velocity = {x=math.random(-num, num), y=math.random(0, num), z=math.random(-num, num)},
acceleration = {x=math.random(-num, num), y=math.random(0, num), z=math.random(-num, num)},
expirationtime = time,
glow = 20,
size = math.random(10, 20),
collisiondetection = false,
vertical = false,
texture = "motorbike_burnout.png",
animation = {
type = "vertical_frames",
aspect_w = 64,
aspect_h = 64,
length = time,
},
})
end
end
end
local l = rots.z
if ctrl.jump and entity.v > (biker.max_speed)-5 then
entity.driver:set_eye_offset({x=0, y=-6.0, z=0}, {x=0, y=0, z=0})
entity.wheelie = repair(angleLerp(k, 45, 0.1))
l = angleLerp(l, 0, 0.07)
entity.object:set_rotation({x=repair(entity.wheelie),y=repair(j),z=repair(l,3)})
elseif not ctrl.jump or entity.v < (biker.max_speed)-5 then
entity.driver:set_eye_offset({x=0, y=-7, z=0}, {x=0, y=0, z=0})
if entity.v > 1.2 and entity.wheelie == 0 then
newrot = angleLerp(newrot, rrot, biker.turn_power)%math.rad(360)
l = biker.dist(newrot+math.rad(360), rrot+math.rad(360))
elseif entity.v < 1.2 then
l = angleLerp(rots.z, 0, 0.2)
end
entity.wheelie = repair(angleLerp(k, 0 ,0.1))
entity.object:set_rotation({x=entity.wheelie, y=newrot, z=repair(l,3)})
end
if math.abs(entity.v) < .05 and math.abs(entity.v) > 0 then
biker.wheelspeed(entity)
end
if entity.lastv and vector.length(entity.lastv) == 0 and math.abs(entity.v) > 0 then
biker.wheelspeed(entity)
end
if not ctrl.sneak then
local s = get_sign(entity.v)
entity.v = entity.v - 0.04 * s
if s ~= get_sign(entity.v) then
entity.object:setvelocity({x=0, y=0, z=0})
entity.v = 0
return
end
end
elseif not entity.driver then
entity.object:set_rotation({x=entity.object:get_rotation().x, y=entity.object:get_rotation().y, z=0})
end
-- Stop!
if not entity.driver then
local s = get_sign(entity.v)
entity.v = entity.v - 0.04 * s
if s ~= get_sign(entity.v) then
entity.object:setvelocity({x=0, y=0, z=0})
entity.v = 0
return
end
end
-- enforce speed limit forward and reverse
local p = entity.object:getpos()
local ni = node_is(p)
local max_spd = biker.max_reverse
if get_sign(entity.v) >= 0 and ni ~= "liquid" then
max_spd = biker.max_speed
elseif ni == "liquid" then
max_spd = 2
end
if math.abs(entity.v) > max_spd then
entity.v = entity.v - get_sign(entity.v)
end
--Set position, velocity and acceleration
local new_velo = {x=0, y=0, z=0}
local new_acce = {x=0, y=-9.8, z=0}
p.y = p.y - 0.5
new_velo = get_velocity(entity.v, entity.object:getyaw() - rot_view, velo.y)
new_acce.y = new_acce.y + acce_y
entity.object:setvelocity(new_velo)
entity.object:setacceleration(new_acce)
entity.lastv = entity.object:getvelocity()
end
minetest.register_on_leaveplayer(function(player)
biker.detach(player)
end)
minetest.register_on_dieplayer(function(player)
biker.detach(player)
end)

123
init.lua Normal file
View File

@ -0,0 +1,123 @@
biker = {}
biker.riders = {}
biker.signs = minetest.get_modpath("signs")
biker.turn_power = minetest.settings:get("motorbike.turn_power") or 0.07--Turning speed of bike 1 is instant. 0.07 is suggested
biker.max_speed = minetest.settings:get("motorbike.max_speed") or 17--Top speed the bike can go.
biker.max_reverse = minetest.settings:get("motorbike.reverse") or 5--Top speed in reverse
biker.acceleration = minetest.settings:get("motorbike.acceleration") or 1.5--Acceleration
biker.braking = minetest.settings:get("motorbike.braking") or 5--Braking power
biker.stepheight = minetest.settings:get("motorbike.stepheight") or 1.3--Bike stephight
biker.path = minetest.get_modpath("motorbike")
dofile(biker.path.."/functions.lua")
local bikelist = {"black", "blue", "brown", "cyan",
"dark_green", "dark_grey", "green", "grey", "magenta",
"orange", "pink", "red", "violet", "white", "yellow"}
for id, colour in pairs (bikelist) do
minetest.register_entity("motorbike:bike_"..colour, {
visual = "mesh",
mesh = "motorbike_body.b3d",
textures = {"motorbike_"..colour..".png","motorbike_"..colour..".png","motorbike_"..colour..".png","motorbike_"..colour..".png"},
stepheight = biker.stepheight,
physical = true,
collisionbox = {0.5, 0.5, 0.5, -0.5, -0.83, -0.5},
on_activate = function(self, staticdata)
if staticdata then
if biker.signs then
self.platenumber = staticdata
end
end
local pos = self.object:get_pos()
self.object:set_armor_groups({fleshy=0, immortal=1})
if biker.signs then
minetest.after(0.1, function()
if not self.platenumber then
self.platenumber = biker.get_plate(self.placer)
end
if not self.plate then
self.plate = minetest.add_entity(pos, "motorbike:licenseplate")
end
if self.plate then
self.plate:set_attach(self.object, "", {x=-0.2, y=-1.9, z=-12.2}, {x=0, y=0, z=0})
end
end)
end
biker.wheelspeed(self)
end,
on_rightclick = function(self, clicker)
local name = clicker:get_player_name()
if not self.driver then
biker.attach(self, clicker, false)
return
end
if self.driver then
biker.detach(clicker, {x=0.5, y=0, z=0.5})
return
end
end,
on_step = function(self, dtime)
local pos = self.object:get_pos()
local node = minetest.get_node(pos)
biker.drive(self, dtime)
end,
get_staticdata = function(self)
if biker.signs then
return self.platenumber
end
end,
})
minetest.register_craftitem("motorbike:"..colour, {
description = colour:gsub("^%l", string.upper):gsub("_", " ").." bike",
inventory_image = "motorbike_"..colour.."_inv.png",
on_place = function(itemstack, placer, pointed_thing)
local pos = {x=pointed_thing.above.x, y=pointed_thing.above.y+1, z=pointed_thing.above.z}
local bike = minetest.add_entity(pos, "motorbike:bike_"..colour, biker.get_plate(placer:get_player_name()))
local ent = bike:get_luaentity()
end,
})
minetest.register_craft({
output = "motorbike:"..colour,
recipe = {
{"","","default:stick"},
{"default:steel_ingot","default:mese_crystal","default:steel_ingot"},
{"motorbike:wheel","wool:"..colour, "motorbike:wheel"},
}
})
end
minetest.register_craftitem("motorbike:wheel", {
description = "Motorbike Wheel",
inventory_image = "motorbike_wheel_inv.png",
})
minetest.register_craft({
output = "motorbike:wheel",
recipe = {
{"default:obsidian_shard","default:obsidian_shard","default:obsidian_shard"},
{"default:obsidian_shard","default:steel_ingot","default:obsidian_shard"},
{"default:obsidian_shard","default:obsidian_shard","default:obsidian_shard"}
}
})
if biker.signs then
minetest.register_entity("motorbike:licenseplate", {
collisionbox = { 0, 0, 0, 0, 0, 0 },
visual = "upright_sprite",
textures = {"blank.png"},
visual_size = {x=0.7, y=0.7, z=0.7},
physical = false,
pointable = false,
collide_with_objects = false,
on_activate = function(self)
minetest.after(0.2, function()
if not self.object:get_attach() then
self.object:remove()
else
self.object:set_armor_groups({immortal = 1})
local text = self.object:get_attach():get_luaentity().platenumber
if not text then return end
self.object:set_properties({textures={generate_texture(create_lines(text))}})
end
end)
end
})
end

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = motorbike
description = Adds various coloured motorbikes to Minetest Game

BIN
models/motorbike_biker.b3d Normal file

Binary file not shown.

BIN
models/motorbike_body.b3d Normal file

Binary file not shown.

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
textures/motorbike_blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
textures/motorbike_cyan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
textures/motorbike_grey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
textures/motorbike_pink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
textures/motorbike_red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB