diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d50d75f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "Lua.diagnostics.globals": [ + "minetest", + "invector", + "vector" + ] +} \ No newline at end of file diff --git a/game.conf b/game.conf new file mode 100644 index 0000000..b6e70c6 --- /dev/null +++ b/game.conf @@ -0,0 +1,2 @@ +name = invector +disallowed_mapgens = v6, v7, valleys, carpathian, v5, fractal \ No newline at end of file diff --git a/menu/header.png b/menu/header.png new file mode 100644 index 0000000..54bd3f4 Binary files /dev/null and b/menu/header.png differ diff --git a/menu/icon.png b/menu/icon.png new file mode 100644 index 0000000..c15bc72 Binary files /dev/null and b/menu/icon.png differ diff --git a/menu/intro_title.png b/menu/intro_title.png new file mode 100644 index 0000000..22bb332 Binary files /dev/null and b/menu/intro_title.png differ diff --git a/minetest.conf b/minetest.conf new file mode 100644 index 0000000..0d2ca04 --- /dev/null +++ b/minetest.conf @@ -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 \ No newline at end of file diff --git a/mods/invector/blends/sam2.blend b/mods/invector/blends/sam2.blend new file mode 100644 index 0000000..d07594f Binary files /dev/null and b/mods/invector/blends/sam2.blend differ diff --git a/mods/invector/blends/sam2.blend1 b/mods/invector/blends/sam2.blend1 new file mode 100644 index 0000000..dea7d6e Binary files /dev/null and b/mods/invector/blends/sam2.blend1 differ diff --git a/mods/invector/blocks.lua b/mods/invector/blocks.lua new file mode 100644 index 0000000..8398e5a --- /dev/null +++ b/mods/invector/blocks.lua @@ -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" +}) \ No newline at end of file diff --git a/mods/invector/init.lua b/mods/invector/init.lua new file mode 100644 index 0000000..3988955 --- /dev/null +++ b/mods/invector/init.lua @@ -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") diff --git a/mods/invector/kart.lua b/mods/invector/kart.lua new file mode 100644 index 0000000..0da7a5a --- /dev/null +++ b/mods/invector/kart.lua @@ -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) \ No newline at end of file diff --git a/mods/invector/karts/sam2.lua b/mods/invector/karts/sam2.lua new file mode 100644 index 0000000..07fa639 --- /dev/null +++ b/mods/invector/karts/sam2.lua @@ -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) \ No newline at end of file diff --git a/mods/invector/mod.conf b/mods/invector/mod.conf new file mode 100644 index 0000000..d1a83cc --- /dev/null +++ b/mods/invector/mod.conf @@ -0,0 +1,2 @@ +name = invector +depends = solarsail \ No newline at end of file diff --git a/mods/invector/models/player_test.b3d b/mods/invector/models/player_test.b3d new file mode 100644 index 0000000..2ea8566 Binary files /dev/null and b/mods/invector/models/player_test.b3d differ diff --git a/mods/invector/models/sam2.b3d b/mods/invector/models/sam2.b3d new file mode 100644 index 0000000..e463672 Binary files /dev/null and b/mods/invector/models/sam2.b3d differ diff --git a/mods/invector/textures/blocks/core_azan_leaves.png b/mods/invector/textures/blocks/core_azan_leaves.png new file mode 100644 index 0000000..7c30334 Binary files /dev/null and b/mods/invector/textures/blocks/core_azan_leaves.png differ diff --git a/mods/invector/textures/blocks/core_azan_log.png b/mods/invector/textures/blocks/core_azan_log.png new file mode 100644 index 0000000..69e0ced Binary files /dev/null and b/mods/invector/textures/blocks/core_azan_log.png differ diff --git a/mods/invector/textures/blocks/core_azan_log_top.png b/mods/invector/textures/blocks/core_azan_log_top.png new file mode 100644 index 0000000..685e0bd Binary files /dev/null and b/mods/invector/textures/blocks/core_azan_log_top.png differ diff --git a/mods/invector/textures/blocks/core_block_health_1.png b/mods/invector/textures/blocks/core_block_health_1.png new file mode 100644 index 0000000..b608c5f Binary files /dev/null and b/mods/invector/textures/blocks/core_block_health_1.png differ diff --git a/mods/invector/textures/blocks/core_block_health_2.png b/mods/invector/textures/blocks/core_block_health_2.png new file mode 100644 index 0000000..c832b7c Binary files /dev/null and b/mods/invector/textures/blocks/core_block_health_2.png differ diff --git a/mods/invector/textures/blocks/core_block_health_3.png b/mods/invector/textures/blocks/core_block_health_3.png new file mode 100644 index 0000000..aabc477 Binary files /dev/null and b/mods/invector/textures/blocks/core_block_health_3.png differ diff --git a/mods/invector/textures/blocks/core_cobble.png b/mods/invector/textures/blocks/core_cobble.png new file mode 100644 index 0000000..7d0b005 Binary files /dev/null and b/mods/invector/textures/blocks/core_cobble.png differ diff --git a/mods/invector/textures/blocks/core_cobble_mossy.png b/mods/invector/textures/blocks/core_cobble_mossy.png new file mode 100644 index 0000000..2555452 Binary files /dev/null and b/mods/invector/textures/blocks/core_cobble_mossy.png differ diff --git a/mods/invector/textures/blocks/core_dirt.png b/mods/invector/textures/blocks/core_dirt.png new file mode 100644 index 0000000..8c4b289 Binary files /dev/null and b/mods/invector/textures/blocks/core_dirt.png differ diff --git a/mods/invector/textures/blocks/core_grass.png b/mods/invector/textures/blocks/core_grass.png new file mode 100644 index 0000000..e5fe722 Binary files /dev/null and b/mods/invector/textures/blocks/core_grass.png differ diff --git a/mods/invector/textures/blocks/core_grass_side.png b/mods/invector/textures/blocks/core_grass_side.png new file mode 100644 index 0000000..a316396 Binary files /dev/null and b/mods/invector/textures/blocks/core_grass_side.png differ diff --git a/mods/invector/textures/blocks/core_gravel.png b/mods/invector/textures/blocks/core_gravel.png new file mode 100644 index 0000000..8176684 Binary files /dev/null and b/mods/invector/textures/blocks/core_gravel.png differ diff --git a/mods/invector/textures/blocks/core_ice.png b/mods/invector/textures/blocks/core_ice.png new file mode 100644 index 0000000..31dff2a Binary files /dev/null and b/mods/invector/textures/blocks/core_ice.png differ diff --git a/mods/invector/textures/blocks/core_lamp_blue.png b/mods/invector/textures/blocks/core_lamp_blue.png new file mode 100644 index 0000000..0190d1b Binary files /dev/null and b/mods/invector/textures/blocks/core_lamp_blue.png differ diff --git a/mods/invector/textures/blocks/core_lamp_red.png b/mods/invector/textures/blocks/core_lamp_red.png new file mode 100644 index 0000000..90587dc Binary files /dev/null and b/mods/invector/textures/blocks/core_lamp_red.png differ diff --git a/mods/invector/textures/blocks/core_long_grass_1.png b/mods/invector/textures/blocks/core_long_grass_1.png new file mode 100644 index 0000000..03bb4a2 Binary files /dev/null and b/mods/invector/textures/blocks/core_long_grass_1.png differ diff --git a/mods/invector/textures/blocks/core_long_grass_2.png b/mods/invector/textures/blocks/core_long_grass_2.png new file mode 100644 index 0000000..9909acb Binary files /dev/null and b/mods/invector/textures/blocks/core_long_grass_2.png differ diff --git a/mods/invector/textures/blocks/core_long_grass_3.png b/mods/invector/textures/blocks/core_long_grass_3.png new file mode 100644 index 0000000..90f84f8 Binary files /dev/null and b/mods/invector/textures/blocks/core_long_grass_3.png differ diff --git a/mods/invector/textures/blocks/core_neutral.png b/mods/invector/textures/blocks/core_neutral.png new file mode 100644 index 0000000..40af3d7 Binary files /dev/null and b/mods/invector/textures/blocks/core_neutral.png differ diff --git a/mods/invector/textures/blocks/core_neutral_lamp.png b/mods/invector/textures/blocks/core_neutral_lamp.png new file mode 100644 index 0000000..f041222 Binary files /dev/null and b/mods/invector/textures/blocks/core_neutral_lamp.png differ diff --git a/mods/invector/textures/blocks/core_reiz_log.png b/mods/invector/textures/blocks/core_reiz_log.png new file mode 100644 index 0000000..b0502a1 Binary files /dev/null and b/mods/invector/textures/blocks/core_reiz_log.png differ diff --git a/mods/invector/textures/blocks/core_reiz_log_top.png b/mods/invector/textures/blocks/core_reiz_log_top.png new file mode 100644 index 0000000..8877785 Binary files /dev/null and b/mods/invector/textures/blocks/core_reiz_log_top.png differ diff --git a/mods/invector/textures/blocks/core_reiz_needles.png b/mods/invector/textures/blocks/core_reiz_needles.png new file mode 100644 index 0000000..b389c1c Binary files /dev/null and b/mods/invector/textures/blocks/core_reiz_needles.png differ diff --git a/mods/invector/textures/blocks/core_reiz_needles_snowy.png b/mods/invector/textures/blocks/core_reiz_needles_snowy.png new file mode 100644 index 0000000..2dfac44 Binary files /dev/null and b/mods/invector/textures/blocks/core_reiz_needles_snowy.png differ diff --git a/mods/invector/textures/blocks/core_sand.png b/mods/invector/textures/blocks/core_sand.png new file mode 100644 index 0000000..33e6101 Binary files /dev/null and b/mods/invector/textures/blocks/core_sand.png differ diff --git a/mods/invector/textures/blocks/core_sandstone.png b/mods/invector/textures/blocks/core_sandstone.png new file mode 100644 index 0000000..5049a6b Binary files /dev/null and b/mods/invector/textures/blocks/core_sandstone.png differ diff --git a/mods/invector/textures/blocks/core_snow.png b/mods/invector/textures/blocks/core_snow.png new file mode 100644 index 0000000..6868f09 Binary files /dev/null and b/mods/invector/textures/blocks/core_snow.png differ diff --git a/mods/invector/textures/blocks/core_snow_side.png b/mods/invector/textures/blocks/core_snow_side.png new file mode 100644 index 0000000..dad6d67 Binary files /dev/null and b/mods/invector/textures/blocks/core_snow_side.png differ diff --git a/mods/invector/textures/blocks/core_stone.png b/mods/invector/textures/blocks/core_stone.png new file mode 100644 index 0000000..ed4d9b0 Binary files /dev/null and b/mods/invector/textures/blocks/core_stone.png differ diff --git a/mods/invector/textures/blocks/core_team_blue.png b/mods/invector/textures/blocks/core_team_blue.png new file mode 100644 index 0000000..5f76551 Binary files /dev/null and b/mods/invector/textures/blocks/core_team_blue.png differ diff --git a/mods/invector/textures/blocks/core_team_red.png b/mods/invector/textures/blocks/core_team_red.png new file mode 100644 index 0000000..dd85a04 Binary files /dev/null and b/mods/invector/textures/blocks/core_team_red.png differ diff --git a/mods/invector/textures/blocks/core_water.png b/mods/invector/textures/blocks/core_water.png new file mode 100644 index 0000000..8b1eb6b Binary files /dev/null and b/mods/invector/textures/blocks/core_water.png differ diff --git a/mods/invector/textures/blocks/core_water_flowing_animated.png b/mods/invector/textures/blocks/core_water_flowing_animated.png new file mode 100644 index 0000000..b3068ca Binary files /dev/null and b/mods/invector/textures/blocks/core_water_flowing_animated.png differ diff --git a/mods/invector/textures/blocks/core_water_source_animated.png b/mods/invector/textures/blocks/core_water_source_animated.png new file mode 100644 index 0000000..e2df454 Binary files /dev/null and b/mods/invector/textures/blocks/core_water_source_animated.png differ diff --git a/mods/invector/textures/blocks/core_zeith_ore.png b/mods/invector/textures/blocks/core_zeith_ore.png new file mode 100644 index 0000000..acb408a Binary files /dev/null and b/mods/invector/textures/blocks/core_zeith_ore.png differ diff --git a/mods/invector/textures/kart_texture_neo.xcf b/mods/invector/textures/kart_texture_neo.xcf new file mode 100644 index 0000000..bc6b699 Binary files /dev/null and b/mods/invector/textures/kart_texture_neo.xcf differ diff --git a/mods/invector/textures/misc/invector_smoke.png b/mods/invector/textures/misc/invector_smoke.png new file mode 100644 index 0000000..c751707 Binary files /dev/null and b/mods/invector/textures/misc/invector_smoke.png differ diff --git a/mods/invector/textures/misc/transparent.png b/mods/invector/textures/misc/transparent.png new file mode 100644 index 0000000..0c2976c Binary files /dev/null and b/mods/invector/textures/misc/transparent.png differ diff --git a/mods/invector/textures/sam2_kart_neo.png b/mods/invector/textures/sam2_kart_neo.png new file mode 100644 index 0000000..9abd483 Binary files /dev/null and b/mods/invector/textures/sam2_kart_neo.png differ diff --git a/mods/invector/textures/sam2_skin.png b/mods/invector/textures/sam2_skin.png new file mode 100644 index 0000000..86ed80a Binary files /dev/null and b/mods/invector/textures/sam2_skin.png differ diff --git a/mods/solarsail/control.lua b/mods/solarsail/control.lua new file mode 100644 index 0000000..d585771 --- /dev/null +++ b/mods/solarsail/control.lua @@ -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) \ No newline at end of file diff --git a/mods/solarsail/init.lua b/mods/solarsail/init.lua new file mode 100644 index 0000000..e929513 --- /dev/null +++ b/mods/solarsail/init.lua @@ -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 + diff --git a/mods/solarsail/player.lua b/mods/solarsail/player.lua new file mode 100644 index 0000000..cc0def7 --- /dev/null +++ b/mods/solarsail/player.lua @@ -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 \ No newline at end of file diff --git a/mods/solarsail/skybox.lua b/mods/solarsail/skybox.lua new file mode 100644 index 0000000..edfa7d4 --- /dev/null +++ b/mods/solarsail/skybox.lua @@ -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) \ No newline at end of file diff --git a/mods/solarsail/textures/solarsail_hsv_spectrum.png b/mods/solarsail/textures/solarsail_hsv_spectrum.png new file mode 100644 index 0000000..0947c66 Binary files /dev/null and b/mods/solarsail/textures/solarsail_hsv_spectrum.png differ diff --git a/mods/solarsail/textures/solarsail_ui_gradient.png b/mods/solarsail/textures/solarsail_ui_gradient.png new file mode 100644 index 0000000..590d36e Binary files /dev/null and b/mods/solarsail/textures/solarsail_ui_gradient.png differ diff --git a/mods/solarsail/textures/solarsail_ui_gradient_flip.png b/mods/solarsail/textures/solarsail_ui_gradient_flip.png new file mode 100644 index 0000000..aa97961 Binary files /dev/null and b/mods/solarsail/textures/solarsail_ui_gradient_flip.png differ diff --git a/mods/solarsail/textures/solarsail_wireframe.png b/mods/solarsail/textures/solarsail_wireframe.png new file mode 100644 index 0000000..4609f42 Binary files /dev/null and b/mods/solarsail/textures/solarsail_wireframe.png differ