Basic kart implementation

master
Jordach 2021-12-03 04:18:48 +00:00
parent 377a5a5607
commit 0fd40b82bc
63 changed files with 1099 additions and 0 deletions

7
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"Lua.diagnostics.globals": [
"minetest",
"invector",
"vector"
]
}

2
game.conf Normal file
View File

@ -0,0 +1,2 @@
name = invector
disallowed_mapgens = v6, v7, valleys, carpathian, v5, fractal

BIN
menu/header.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
menu/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
menu/intro_title.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

9
minetest.conf Normal file
View File

@ -0,0 +1,9 @@
#time_speed = 4
dedicated_server_step = 0.03
item_entity_ttl = 1
active_object_send_range_blocks = 32
active_block_range = 32
ask_reconnect_on_crash = true
player_transfer_distance = 0
max_objects_per_block = 1024
max_packets_per_iteration = 2048

Binary file not shown.

Binary file not shown.

25
mods/invector/blocks.lua Normal file
View File

@ -0,0 +1,25 @@
-- Invector, License MIT, Author Jordach
minetest.register_node("invector:smoke_node", {
description = "don't use me",
tiles = {"invector_smoke.png"},
drawtype = "glasslike"
})
minetest.register_node("invector:boost_1_node", {
description = "don't use me",
tiles = {"invector_boost_small.png"},
drawtype = "glasslike"
})
minetest.register_node("invector:boost_2_node", {
description = "don't use me",
tiles = {"invector_boost_medium.png"},
drawtype = "glasslike"
})
minetest.register_node("invector:boost_3_node", {
description = "don't use me",
tiles = {"invector_boost_large.png"},
drawtype = "glasslike"
})

24
mods/invector/init.lua Normal file
View File

@ -0,0 +1,24 @@
-- Invector, License MIT, Author Jordach
minetest.override_item("", {
wield_scale = {x=1,y=1,z=1},
range = 1,
tool_capabilities = {
full_punch_interval = 1,
max_drop_level = 0,
groupcaps = {},
damage_groups = {},
}
})
invector = {}
invector.functions = {}
invector.path = minetest.get_modpath("invector")
local function exec(file)
dofile(invector.path.."/"..file..".lua")
end
exec("kart")
exec("karts/sam2")

14
mods/invector/kart.lua Normal file
View File

@ -0,0 +1,14 @@
-- Invector, License MIT, Author Jordach
invector.karts = {}
function invector.functions.register_kart(name, def)
invector.karts[name] = def
minetest.register_entity("invector:"..name, def)
end
-- This is fixed in code due to this not being a multiplayer release.
minetest.register_on_joinplayer(function(player)
solarsail.player.set_model(player, "invector:sam2", {x=0, y=159}, 60,
invector.karts.sam2._geo, invector.karts.sam2._geo3r, "",
invector.karts.sam2._prel, invector.karts.sam2._prot)
end)

View File

@ -0,0 +1,343 @@
-- Invector, License MIT, Author Jordach
-- Fake third person but works like third person
local default_eye_offset = vector.new(0,0,0)
local ground_eye_offset = vector.new(0,1.8,-30)
local ground_eye_offset_3r = vector.new(0,-10,0)
local player_relative = vector.new(0,0,0)
local player_rot = vector.new(0,0,0)
-- Update rate, don't touch me
local tick_speed = 0.03
-- Bone rotation things;
local kart_root_pos = vector.new(0,0,0)
local kart_root_rot = vector.new(0,0,0)
-- Particle effect things
local front_left_tyre_pos = vector.new(0,0,0)
local front_right_tyre_pos = vector.new(0,0,0)
local rear_left_tyre_pos = vector.new(0,0,0)
local rear_right_tyre_pos = vector.new(0,0,0)
local rear_left_exhaust_pos = vector.new(0,0,0)
local rear_right_exhaust_pos = vector.new(0,0,0)
-- Handling specs
local turning_radius = 0.0472665
local drifting_radius = turning_radius * 1.75
local drifting_radius_lesser = drifting_radius * 0.5
local drifting_radius_greater = drifting_radius * 1.5
local reverse_radius = 0.0174533
-- Speed specs
local max_speed_boost = 8
local max_speed_norm = 6
local forwards_accel = 3
local reverse_accel = -0.25
local braking_factor = 0.75
-- Boost specs
local small_boost_time = 1.5
local med_boost_time = 3
local big_boost_time = 5
local kart = {
visual = "mesh",
mesh = "sam2.b3d",
use_texture_alpha = true,
backface_culling = false,
makes_footstep_sound = true,
textures = {
"sam2_kart_neo.png",
"sam2_skin.png",
},
visual_size = {x=1, y=1},
collisionbox = {-0.61, 0.0, -0.61, 0.61, 1.4, 0.61},
physical = true,
collide_with_objects = true,
pointable = false,
stepheight = 0.5/16,
-- Custom fields:
_timer = 0,
_boost_timer = 0,
_drift_timer = 0,
_xvel = 0,
_zvel = 0,
_dvel = 0,
_yvel = 0,
_last_cam_offset = 0,
_is_drifting = 0, -- 1 = left, -1 = right
-- Particle ID holders
_rear_left_tyre_spawner = 0,
_rear_right_tyre_spawner = 0,
_exhaust_left_spawner = 0,
_exhaust_right_spawner = 0,
_deo = default_eye_offset,
_geo = ground_eye_offset,
_geo3r = ground_eye_offset_3r,
_prel = player_relative,
_prot = player_rot
}
function kart:on_step(dtime)
if self.attached_player ~= nil then
self._timer = self._timer + dtime
if self._timer > tick_speed then
self._timer = 0
local control = solarsail.controls.player[self.attached_player:get_player_name()]
if control == nil then return end
--[[ if control.aux1 then
self.attached_player:set_detach()
self.attached_player = nil
return
end ]]
if self._boost_timer > 0 then
self._boost_timer = self._boost_timer - dtime
end
--self.object:set_animation({x=0, y=159}, 60, 0)
local velocity = self.object:get_velocity()
local accel = self.object:get_acceleration()
local rotation = self.object:get_yaw()
local cam_rot_offset = 0
local yaw_offset = 0
if velocity.y == 0 then
-- Handle node frictive types here;
-- Handle friction
if self._dvel > 1 then
self._dvel = self._dvel - 1
else
self._dvel = self._dvel * 0.96
end
end
-- Round down numbers when percentages exponentialise movement:
if self._dvel < 0.1 and self._dvel > 0 then
self._dvel = 0
elseif self._dvel > -0.1 and self._dvel < 0 then
self._dvel = 0
end
-- Handle controls;
-- Accel braking;
if control.up then
self._dvel = self._dvel + forwards_accel
elseif control.down then
-- Reversing
if self._dvel < 0.1 then
self._dvel = self._dvel + reverse_accel
else
self._dvel = self._dvel * braking_factor
end
end
-- Drifting;
if control.jump and self._dvel > 5.5 then
-- Direction of drifting
if self._is_drifting == 0 then
if control.left then
self._is_drifting = 1
elseif control.right then
self._is_drifting = -1
end
end
-- Drift steering
if control.left then
if self._is_drifting == 1 then --Left
yaw_offset = drifting_radius_greater
elseif self._is_drifting == -1 then
yaw_offset = -drifting_radius_lesser
end
elseif control.right then
if self._is_drifting == 1 then --Left adds, right removes
yaw_offset = drifting_radius_lesser
elseif self._is_drifting == -1 then
yaw_offset = -drifting_radius_greater
end
else
if self._is_drifting == 1 then --Left
yaw_offset = drifting_radius
elseif self._is_drifting == -1 then
yaw_offset = -drifting_radius
end
end
elseif control.left then
-- Fowards
if self._dvel > 0.5 then
yaw_offset = turning_radius
-- Reversing
elseif self._dvel < -0.1 then
cam_rot_offset = 3.142
yaw_offset = -reverse_radius
end
elseif control.right then
-- Fowards
if self._dvel > 0.5 then
yaw_offset = -turning_radius
-- Reversing
elseif self._dvel < -0.1 then
cam_rot_offset = 3.142
yaw_offset = reverse_radius
end
end
-- Give the boost
if not control.jump then
self._is_drifting = 0
-- Maximum boost
if self._drift_timer >=5 then
self._boost_timer = 3
-- Medium boost
elseif self._drift_timer >=3 then
self._boost_timer = 2
-- Small boost
elseif self._drift_timer >=1.5 then
self._boost_timer = 1
end
end
-- Do not give a boost if falling under the drifting speed
if self._dvel <= 5 then
self._is_drifting = 0
self._drift_timer = 0
end
-- Use Item/Boost;
if control.LMB then
elseif control.RMB then
end
local xv, zv = solarsail.util.functions.yaw_to_vec(rotation+yaw_offset, self._dvel, false)
local new_vel = vector.new(xv, 0, zv)
new_vel = vector.normalize(new_vel)
new_vel.y = velocity.y
-- Limit velocity based on boost status
if self._boost_timer > 0 then
if self._dvel > max_speed_boost then
self._dvel = max_speed_boost
elseif self._dvel < -max_speed_boost then
self._dvel = -max_speed_boost
end
else
if self._dvel > max_speed_norm then
self._dvel = max_speed_norm
elseif self._dvel < -max_speed_norm then
self._dvel = -max_speed_norm
end
end
-- Animation and camera handler:
local frange, fspeed, fblend, floop = self.object:get_animation()
local new_frames = {x=0, y=0}
local new_fps = 60
if control.up then
if control.left then
new_frames.x = 60
new_frames.y = 79
elseif control.right then
new_frames.x = 120
new_frames.y = 139
else
new_frames.x = 0
new_frames.y = 19
end
elseif control.down then -- Reversing
if self._dvel > 1.5 then
if control.left then
new_frames.x = 60
new_frames.y = 79
elseif control.right then
new_frames.x = 120
new_frames.y = 139
else
new_frames.x = 0
new_frames.y = 19
end
elseif self._dvel < -1.5 then
if control.left then
new_frames.x = 90
new_frames.y = 109
elseif control.right then
new_frames.x = 150
new_frames.y = 169
else
new_frames.x = 30
new_frames.y = 49
end
end
else -- Coming to a stop or idle
if self._dvel > 1.5 then
if control.left then
new_frames.x = 60
new_frames.y = 79
elseif control.right then
new_frames.x = 120
new_frames.y = 139
else
new_frames.x = 0
new_frames.y = 19
end
elseif self._dvel < -1.5 then
if control.left then
new_frames.x = 90
new_frames.y = 109
elseif control.right then
new_frames.x = 150
new_frames.y = 169
else
new_frames.x = 30
new_frames.y = 49
end
else -- Idle
if control.left then
new_frames.x = 79
new_frames.y = 79
elseif control.right then
new_frames.x = 139
new_frames.y = 139
else
new_frames.x = 19
new_frames.y = 19
end
end
end
if frange.x ~= new_frames.x then
if frange.y ~= new_frames.y then
self.object:set_animation(new_frames, 60, 0.1, true)
end
end
-- Reversing camera mode if required
if self._dvel < -1 and control.down then
cam_rot_offset = 3.142
end
-- Set camera rotation
if not control.sneak then
if self.attached_player:get_look_vertical() ~= 0 then
self.attached_player:set_look_vertical(0)
end
if self.attached_player:get_look_horizontal() ~= rotation+cam_rot_offset then
self.attached_player:set_look_horizontal(rotation+cam_rot_offset)
end
end
-- Set object rotation and speed
self.object:set_velocity({x=xv, y=velocity.y, z=zv})
self.object:set_yaw(rotation+yaw_offset)
end
else -- Self destruct
--self.object:remove()
end
end
invector.functions.register_kart("sam2", kart)

2
mods/invector/mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = invector
depends = solarsail

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,34 @@
-- SolarSail Engine Control Handler:
-- Author: Jordach
-- License: Reserved
--[[ solarsail.controls.focus[player_name]
Valid values, should be read only (but set by a authoritive script):
"talk" all controls are used to handle talking to NPCs, ie dialog options
"world" all controls are used to control the player when in the world
"menu" all controls are used to change the cursor in a menu
"battle" all controls are used to handle battle, behaves like "menu"
"cutscene" all controls aren't used, but pressing jump can skip things
--]]
solarsail.controls.focus = {}
--[[ solarsail.controls.player[player_name]
Read only:
Gets the player:get_player_control() result for [player_name]
]]--
solarsail.controls.player = {}
local function update_controls()
for _, player in ipairs(minetest.get_connected_players()) do
solarsail.controls.player[player:get_player_name()] = player:get_player_control()
end
minetest.after(0.03, update_controls)
end
minetest.register_on_joinplayer(function(player)
solarsail.controls.focus[player:get_player_name()] = "world"
end)
minetest.after(0.03, update_controls)

206
mods/solarsail/init.lua Normal file
View File

@ -0,0 +1,206 @@
-- SolarSail Engine
-- Author: Jordach
-- License: Reserved
-- Primary Namespaces:
solarsail = {}
solarsail.skybox = {}
solarsail.camera = {}
solarsail.controls = {}
solarsail.player = {}
solarsail.util = {}
solarsail.util.functions = {}
--[[
solarsail.util.function.normalize_pos()
pos_a = vector.new(); considered the zero point
pos_b = vector.new(); considered the space around the zero point
returns pos_b localised by pos_a.
]]
function solarsail.util.functions.get_local_pos(pos_a, pos_b)
local pa = table.copy(pos_a)
local pb = table.copy(pos_b)
local res = vector.new(
pb.x - pa.x,
pb.y - pa.y,
pb.z - pa.z
)
return res
end
--[[
solarsail.util.functions.convert_from_hex()
input = ColorSpec
returns three variables red, green and blue in base 10 values.
]]--
function solarsail.util.functions.convert_from_hex(input)
local r, g, b = input:match("^#(%x%x)(%x%x)(%x%x)")
return tonumber(r, 16), tonumber(g, 16), tonumber(b, 16)
end
--[[
solarsail.util.functions.lerp()
var_a = input number to blend from. (at ratio 0)
var_b = input number to blend to. (at ratio 1)
returns the blended value depending on ratio.
]]--
function solarsail.util.functions.lerp(var_a, var_b, ratio)
return (1-ratio)*var_a + (ratio*var_b)
end
--[[
solarsail.util.functions.remap()
val = Input value
min_val = minimum value of your expected range
max_val = maximum value of your expected range
min_map = minimum value of your remapped range
max_map = maximum value of your remapped range
returns a value between min_map and max_map based on where val is relative to min_val and max_val.
]]
function solarsail.util.functions.remap(val, min_val, max_val, min_map, max_map)
return (val-min_val)/(max_val-min_val) * (max_map-min_map) + min_map
end
function solarsail.util.functions.blend_colours(val, min_val, max_val, min_col, max_col)
if val <= min_val then
return min_col
elseif val >= max_val then
return max_col
end
local min_r, min_g, min_b = solarsail.util.functions.convert_from_hex(min_col)
local max_r, max_g, max_b = solarsail.util.functions.convert_from_hex(max_col)
local blend = solarsail.util.functions.remap(val, min_val, max_val, 0, 1)
local res_r = solarsail.util.functions.lerp(min_r, max_r, blend)
local res_g = solarsail.util.functions.lerp(min_g, max_g, blend)
local res_b = solarsail.util.functions.lerp(min_b, max_b, blend)
return minetest.rgba(res_r, res_g, res_b)
end
function solarsail.util.functions.y_direction(rads, recoil)
return math.sin(rads) * recoil
end
function solarsail.util.functions.xz_amount(rads)
local pi = math.pi
return math.sin(rads+(pi/2))
end
-- Takes vector based velocities or positions (as vec_a to vec_b)
function solarsail.util.functions.get_3d_angles(vector_a, vector_b)
-- Does the usual Pythagoras bullshit:
local x_dist = vector_a.x - vector_b.x + 1
local z_dist = vector_a.z - vector_b.z + 1
local hypo = math.sqrt(x_dist^2 + z_dist^2)
-- But here's the kicker: we're using arctan to get the cotangent of the angle,
-- but also applies to *negative* numbers. In such cases where the positions
-- are northbound (positive z); the angle is 180 degrees off.
local xz_angle = -math.atan(x_dist/z_dist)
-- For the pitch angle we do it very similar, but use the
-- Hypotenuse as the Adjacent side, and the Y distance as the
-- Opposite, so arctangents are needed.
local y_dist = vector_a.y - vector_b.y
local y_angle = math.atan(y_dist/hypo)
-- Fixes radians using south facing (-Z) radians when heading north (+Z)
if z_dist < 0 then
xz_angle = xz_angle - math.rad(180)
end
return xz_angle, y_angle
end
function solarsail.util.functions.pos_to_dist(pos_1, pos_2)
local res = {}
res.x = (pos_1.x - pos_2.x)
res.y = (pos_1.y - pos_2.y)
res.z = (pos_1.z - pos_2.z)
return math.sqrt(res.x*res.x + res.y*res.y + res.z*res.z)
end
solarsail.avg_dtime = 0
solarsail.last_dtime = {}
local dtime_steps = 0
local num_steps = 30*2
minetest.register_globalstep(function(dtime)
if dtime_steps == num_steps then
local avg = 0
for i=1, num_steps do
avg = avg + solarsail.last_dtime[i]
end
solarsail.avg_dtime = avg / num_steps
dtime_steps = 0
solarsail.last_dtime[1] = dtime
--print(string.format("%.4f", tostring(solarsail.avg_dtime)))
--minetest.chat_send_all(string.format("%.4f", tostring(solarsail.avg_dtime)))
else
dtime_steps = dtime_steps + 1
solarsail.last_dtime[dtime_steps] = dtime
end
end)
if true then
-- Handle flat mapgen, for building a world
minetest.register_node("solarsail:wireframe", {
description = "Wireframe, prototyping node",
tiles = {"solarsail_wireframe.png"},
groups = {debug=1}
})
minetest.register_alias("mapgen_stone", "solarsail:wireframe")
minetest.register_alias("mapgen_grass", "solarsail:wireframe")
minetest.register_alias("mapgen_water_source", "solarsail:wireframe")
minetest.register_alias("mapgen_river_water_source", "solarsail:wireframe")
-- Sava data handling (per-player):
--dofile(minetest.get_modpath("solarsail").."/save.lua")
-- HSVA->RGBA->HSVA handling:
--dofile(minetest.get_modpath("solarsail").."/colour.lua")
-- HUD rendering and formspec handling:
--dofile(minetest.get_modpath("solarsail").."/hud.lua")
-- Cameras used in dialog, cutscenes or when controlled by the player:
--dofile(minetest.get_modpath("solarsail").."/camera.lua")
-- Start skybox engine:
dofile(minetest.get_modpath("solarsail").."/skybox.lua")
-- Control handling for HUDs, player entity, etc:
dofile(minetest.get_modpath("solarsail").."/control.lua")
-- Third person player camera handling + third person model:
dofile(minetest.get_modpath("solarsail").."/player.lua")
-- Basic, advanced NPC AI;
--dofile(minetest.get_modpath("solarsail").."/npc.lua")
-- Player menus:
--dofile(minetest.get_modpath("solarsail").."/menu.lua")
end

142
mods/solarsail/player.lua Normal file
View File

@ -0,0 +1,142 @@
-- SolarSail Engine Player Handling:
-- Author: Jordach
-- License: Reserved
solarsail.player.model = {}
--[[ solarsail.player.model.entity_name[player_name]
Read only, set only by authoritative content.
Example values:
solarsail.player.model.entity_name[player_name] = "solarplains:starsuit"
solarsail.player.model.entity_name[player_name] = "anathema:model"
]]
solarsail.player.model.entity_name = {}
solarsail.player.model.entity_ref = {}
--[[ solarsail.player.set_model(player_ref, model_name, anim, framerate,
eye_offset, eye_offset_3r, attach_bone,
attach_relative, attach_rotation)
model_name = "model:name"
(See minetest.register_entity() for more information.)
anim:
anim.x = 123, The start position of the animation loop
anim.y = 456, The end position of the animation loop
Setting anim = nil will result in anim.x, anim.y = 0
framerate = 60, Sets the framerate of the animation,
can be configured upto about 300fps.
framerate = nil will default to 60.
eye_offset and eye_offset_3r:
x = 1, Position on the X axis where the "player's camera" will sit
y = 2, Position on the Y axis where the "player's camera" will sit
z = 3, Position on the Z axis where the "player's camera" will sit
Setting either table to nil will default to x, y, z = 0.
attach_bone = "bonename", Make sure the bone exists in the exported model.
(Can include . : , etc)
Setting attach_bone to nil will default to ""
attach_relative:
x = 1, Position on the X axis where the
"Minetest Player Entity" is attached
y = 2, Position on the Y axis where the
"Minetest Player Entity" is attached
z = 3, Position on the Z axis where the
"Minetest Player Entity" is attached
Setting attach_relative = nil will default to x, y, z = 0.
attach_rotation:
x = 1, Rotation on the X axis in degrees
(of either the entity or player, documentation unclear)
y = 2, Rotation on the Y axis in degrees
(of either the entity or player, documentation unclear)
z = 3, Rotation on the Z axis in degrees
(of either the entity or player, documentation unclear)
Setting attach_rotation = nil will default to x, y, z = 0.
]]
function solarsail.player.set_model(player_ref, model_name, anim, framerate,
eye_offset, eye_offset_3rv, attach_bone, relative_pos, relative_rotation)
-- Prevent impossible situations where the model may not exist.
if model_name == nil or type(model_name) ~= "string" then
error("model_name must be a string.")
end
-- Construct a player entity at the player's position:
local pos = player_ref:get_pos()
solarsail.player.model.entity_ref[player_ref:get_player_name()] = minetest.add_entity(pos, model_name)
-- Get LuaObject:
local entity_lua = solarsail.player.model.entity_ref[player_ref:get_player_name()]:get_luaentity()
-- Add the player_ref to the model, as it may be needed to ensure they player is still attached.
-- Set this to nil to detach the "player camera" from the "player model"
entity_lua.attached_player = player_ref
-- Set the idle animation:
solarsail.player.model.entity_ref[player_ref:get_player_name()]:set_animation(anim, framerate, 0)
-- Remove all normal MT HUD from the player:
player_ref:hud_set_flags({
crosshair = false,
hotbar = false,
healthbar = false,
wielditem = false,
breathbar = false
})
-- Set the eye offset for the "player camera"
player_ref:set_eye_offset(eye_offset, eye_offset_3r)
-- Attach the "Minetest player" to the "solarsail player"
player_ref:set_attach(entity_lua.object, attach_bone, relative_pos, relative_rotation)
end
-- Wrapper for Lua_SAO:set_properties()
function solarsail.player.set_properties(player_name, changes)
solarsail.player.model.entity_ref[player_name]:set_properties(changes)
end
-- Wrapper for Lua_SAO:get_properties()
function solarsail.player.get_properties(player_name)
return solarsail.player.model.entity_ref[player_name]:get_properties()
end
--store PI for quicker use:
local pi = math.pi
-- Supply a boolean value to go backwards, otherwise, forwards
function solarsail.util.functions.yaw_to_vec(rads, mult, backwards)
local z = math.cos(rads) * mult
local x = (math.sin(rads) * -1) * mult
if backwards then
return -x, -z
else
return x, z
end
end
-- Get left or right direction, supply a boolean to go left.
function solarsail.util.functions.yaw_to_vec_side(rads, mult, left)
local nrads = rads + pi/2
if left then
nrads = rads - pi/2
end
local x = (math.cos(nrads) * -1) * mult
local z = math.sin(nrads) * mult
return z, x
end
-- Convert our x, z vectors to a nice radian:
function solarsail.util.functions.vec_to_rad(x, z)
return math.atan2(z, x)
end
-- Quickly convert degrees to radians:
function solarsail.util.functions.deg_to_rad(deg)
return deg * (pi/180)
end

291
mods/solarsail/skybox.lua Normal file
View File

@ -0,0 +1,291 @@
-- SolarSail Engine Skybox Handler:
-- Author: Jordach
-- License: Reserved
-- Pre-Init:
solarsail.skybox.is_paused = false
solarsail.skybox.regions = {}
solarsail.skybox.regions.pos_1 = {}
solarsail.skybox.regions.pos_2 = {}
solarsail.skybox.regions.skybox = {}
solarsail.skybox.skybox_defs = {}
solarsail.skybox.cloud_defs = {}
--[[ solarsail.skybox.register_skybox(skybox_name, skybox_defs, cloud_defs, pos_1, pos_2)
API spec for registering clouds based on position:
skybox_defs table:
skybox_defs.textures = {1, 2, 3, 4, 5, 6}
skybox_defs.type = "regular", "bgcolor", "skybox"
skybox_defs.bgcolor = "#rrggbb"
skybox_defs.clouds = true, false
cloud_defs table:
cloud_defs.density: 0 to 1
cloud_defs.color: "#rrggbbaa"
cloud_defs.ambient: "#rrggbb"
cloud_defs.height: -31000 to 31000
cloud_defs.thickness: 0.01 to 31000
cloud_defs.x = -128 to 128
cloud_defs.y = -128 to 128
position_1 = {x = 1, y = 0, z = 0}
position_2 = {x = -1, y = 1, z = 10}
Note: Preferrably as game_skyboxname or mod_skyboxname
]]--
function solarsail.skybox.register_skybox(skybox_name, skybox_defs, cloud_defs, pos_1, pos_2)
solarsail.skybox.skybox_defs[skybox_name] = skybox_defs
solarsail.skybox.cloud_defs[skybox_name] = cloud_defs
solarsail.skybox.regions.pos_1[skybox_name] = pos_1
solarsail.skybox.regions.pos_2[skybox_name] = pos_2
solarsail.skybox.regions.skybox[skybox_name] = skybox_name
end
--[[ solarsail.skybox.override_skybox(skybox_defs, cloud_defs, player)
API spec for temporarily overriding skyboxes:
skybox_defs table:
skybox_defs.textures = {"1", "2", "3", "4", "5", "6"}
skybox_defs.type = "regular", "bgcolor", "skybox"
skybox_defs.bgcolor = "#rrggbb"s
skybox_defs.clouds = true, false
cloud_defs table:
cloud_defs.density: 0 to 1
cloud_defs.color: "#rrggbbaa"
cloud_defs.ambient: "#rrggbb"
cloud_defs.height: -31000 to 31000
cloud_defs.thickness: 0.01 to 31000
cloud_defs.x = -128 to 128
cloud_defs.y = -128 to 128
player is a PlayerRef created by the Minetest Engine.
]]--
function solarsail.skybox.override_skybox(skybox_defs, cloud_defs, player)
solarsail.skybox.is_paused = true
player:set_sky(
skybox_defs.bgcolor,
skybox_defs.type,
skybox_defs.textures,
skybox_defs.clouds
)
player:set_clouds({
density = cloud_defs.density,
color = cloud_defs.color,
ambient = cloud_defs.ambient,
height = cloud_defs.height,
thickness = cloud_defs.thickness,
speed = {x = cloud_defs.x, cloud_defs.y}
})
end
--[[ solarsail.skybox.restore_skybox()
Resume paused skybox functionality from overrides
]]--
function solarsail.skybox.restore_skybox()
solarsail.skybox.is_paused = false
solarsail_render_sky()
end
-- Simplified inbetween check:
local function inbetween(lower, upper, val)
if val >= lower and val <= upper then
return true
else
return false
end
end
-- Compare skybox settings against the new ones:
local function compare_sky(skybox_defs, one, two, three)
-- Compare bgcolor to supplied bgcolor:
local bgcolor = minetest.rgba(one.r, one.g, one.b)
if bgcolor ~= skybox_defs.bgcolor then return true end
-- Compare skybox types:
if two ~= skybox_defs.type then return true end
-- If we happen to be now using "skybox" do so here - otherwise we ignore it and flag it as changed
if skybox_defs.type == "skybox" and three == "skybox" then
for k, v in pairs(three) do
if v ~= skybox_defs.textures[k] then
return true
end
end
end
return false -- if somehow we get here by mistake
end
-- Compare cloud settings against the new ones:
local function compare_clouds(cloud_defs, player_clouds) -- Speed of clouds aren't changed as they're considered a changing value, eg wind
-- Compare cloud densities:
if cloud_defs.density ~= player_clouds.density then return true end
-- Compare base color:
if cloud_defs.color ~= minetest.rgba(
player_clouds.color.r,
player_clouds.color.g,
player_clouds.color.b,
player_clouds.color.a
) then return true end
-- Compare "ambiance colour"
if cloud_defs.ambient ~= minetest.rgba(
player_clouds.ambient.r,
player_clouds.ambient.g,
player_clouds.ambient.b,
player_clouds.ambient.a
) then return true end
-- Compare height
if cloud_defs.height ~= player_clouds.height then return true end
-- Compare thiccness
if cloud_defs.thickness ~= player_clouds.thickness then return true end
return false -- if somehow none of these values are considered changed
end
-- Change skybox for "connected players here":
local function solarsail_render_sky()
if solarsail.skybox.is_paused then
else
for _, player in ipairs(minetest.get_connected_players()) do
local ppos = player:get_pos()
local isx, isy, isz = false
-- Iterate over a table full of names
for k, v in pairs(solarsail.skybox.regions.skybox) do
if inbetween(solarsail.skybox.regions.pos_1[v].x, solarsail.skybox.regions.pos_2[v].x, ppos.x) then
isx = true
end
if inbetween(solarsail.skybox.regions.pos_1[v].y, solarsail.skybox.regions.pos_2[v].y, ppos.y) then
isy = true
end
if inbetween(solarsail.skybox.regions.pos_1[v].z, solarsail.skybox.regions.pos_2[v].z, ppos.z) then
isz = true
end
if isx and isy and isz then
local sky_1, sky_2, sky_3 = player:get_sky()
if compare_sky(solarsail.skybox.skybox_defs[v], sky_1, sky_2, sky_3) then
player:set_sky(
solarsail.skybox.skybox_defs[v].bgcolor,
solarsail.skybox.skybox_defs[v].type,
solarsail.skybox.skybox_defs[v].textures,
solarsail.skybox.skybox_defs[v].clouds
)
end
if compare_clouds(solarsail.skybox.cloud_defs[v], player:get_clouds()) then
player:set_clouds({
density = solarsail.skybox.cloud_defs[v].density,
color = solarsail.skybox.cloud_defs[v].color,
ambient = solarsail.skybox.cloud_defs[v].ambient,
height = solarsail.skybox.cloud_defs[v].height,
thickness = solarsail.skybox.cloud_defs[v].thickness,
speed = {x = solarsail.skybox.cloud_defs[v].x, solarsail.skybox.cloud_defs[v].y}
})
end
break
else
isx, isy, isz = false
end
end
end
minetest.after(0.1, solarsail_render_sky)
end
end
local player_count = 0
--[[
minetest.register_on_joinplayer(function(player)
-- magic values to make comparisons work, as MT does not provide defaults
player:set_sky("#ffffff", "regular", {"eror.png"}, true)
solarsail_render_sky()
-- Prevent player handling freaking out; but this may change in future
player_count = player_count + 1
if player_count > 1 then
--minetest.kick_player(player:get_player_name(), "[SolarSail]: Singleplayer only, multiplayer disallowed.")
end
end)
minetest.register_on_leaveplayer(function(player)
player_count = player_count - 1
end)
solarsail.skybox.register_skybox("default",
{
-- ["top"] = "#676891", ["bottom"] = "#c79161", ["base"] = "#a17268", ["light"] = 0.15} sunrise = #ffae5f horizon = #404164
bgcolor = "#a17268",
type = "regular",
clouds = true
},
{
density = 0.34
},
{
x = -31000,
y = -31000,
z = -31000
},
{
x = 31000,
y = 31000,
z = 31000
}
)
]]
local day_sky = "#c5b7ea"
local day_horizon = "#f0ecff"
local dawn_sky = "#bf9bb4"
local dawn_horizon = "#dec6d7"
local night_sky = "#030015"
local night_horizon = "#100033"
local sun_tint = "#dbbae7"
local moon_tint = "#d37dff"
local cloud_color = "#f3eaf8e7"
local star_color = "#c0c7ffaa"
minetest.register_on_joinplayer(function(player)
player:set_sky({
type = "regular",
clouds = true,
sky_color = {
day_sky = day_sky,
day_horizon = day_horizon,
dawn_sky = dawn_sky,
dawn_horizon = dawn_horizon,
night_sky = night_sky,
night_horizon = night_horizon,
fog_sun_tint = sun_tint,
fog_moon_tint = moon_tint,
fog_tint_type = "custom"
}
})
player:set_clouds({
color = cloud_color
})
player:set_stars({
count = 2000,
star_color = star_color,
scale = 0.65
})
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B